From 037a15a371d5c016ec1f6516f8b84e45fddcd026 Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Wed, 29 May 2024 11:01:24 +0100 Subject: [PATCH 001/161] Fix deprecated import style --- src/Mod/Fem/femguiutils/migrate_gui.py | 182 ++++++++-------------- src/Mod/Fem/femtools/migrate_app.py | 206 +++++++++---------------- 2 files changed, 133 insertions(+), 255 deletions(-) diff --git a/src/Mod/Fem/femguiutils/migrate_gui.py b/src/Mod/Fem/femguiutils/migrate_gui.py index ce0c5fc941fd..b682f733049c 100644 --- a/src/Mod/Fem/femguiutils/migrate_gui.py +++ b/src/Mod/Fem/femguiutils/migrate_gui.py @@ -30,129 +30,73 @@ __author__ = "Bernd Hahnebach" __url__ = "https://www.freecad.org" +from importlib.util import spec_from_loader -class FemMigrateGui(object): - - def find_module(self, fullname, path): - - if fullname == "femguiobjects": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintBodyHeatSource": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintElectrostaticPotential": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintFlowVelocity": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintInitialFlowVelocity": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintSelfWeight": - return self - if fullname == "femguiobjects._ViewProviderFemConstraintTie": - return self - if fullname == "femguiobjects._ViewProviderFemElementFluid1D": - return self - if fullname == "femguiobjects._ViewProviderFemElementGeometry1D": - return self - if fullname == "femguiobjects._ViewProviderFemElementGeometry2D": - return self - if fullname == "femguiobjects._ViewProviderFemElementRotation1D": - return self - if fullname == "femguiobjects._ViewProviderFemMaterial": - return self - if fullname == "femguiobjects._ViewProviderFemMaterialMechanicalNonlinear": - return self - if fullname == "femguiobjects._ViewProviderFemMaterialReinforced": - return self - if fullname == "femguiobjects._ViewProviderFemMeshBoundaryLayer": - return self - if fullname == "femguiobjects._ViewProviderFemMeshGmsh": - return self - if fullname == "femguiobjects._ViewProviderFemMeshGroup": - return self - if fullname == "femguiobjects._ViewProviderFemMeshRegion": - return self - if fullname == "femguiobjects._ViewProviderFemMeshResult": - return self - if fullname == "femguiobjects._ViewProviderFemResultMechanical": - return self - if fullname == "femguiobjects._ViewProviderFemSolverCalculix": - return self - if fullname == "PyGui": - return self - if fullname == "PyGui._ViewProviderFemConstraintBodyHeatSource": - return self - if fullname == "PyGui._ViewProviderFemConstraintElectrostaticPotential": - return self - if fullname == "PyGui._ViewProviderFemConstraintFlowVelocity": - return self - if fullname == "PyGui._ViewProviderFemConstraintSelfWeight": - return self - if fullname == "PyGui._ViewProviderFemElementFluid1D": - return self - if fullname == "PyGui._ViewProviderFemElementGeometry1D": - return self - if fullname == "PyGui._ViewProviderFemElementGeometry2D": - return self - if fullname == "PyGui._ViewProviderFemElementRotation1D": - return self - if fullname == "PyGui._ViewProviderFemMaterial": - return self - if fullname == "PyGui._ViewProviderFemMaterialMechanicalNonlinear": - return self - if fullname == "PyGui._ViewProviderFemMeshBoundaryLayer": - return self - if fullname == "PyGui._ViewProviderFemMeshGmsh": - return self - if fullname == "PyGui._ViewProviderFemMeshGroup": - return self - if fullname == "PyGui._ViewProviderFemMeshRegion": - return self - if fullname == "PyGui._ViewProviderFemMeshResult": - return self - if fullname == "PyGui._ViewProviderFemResultMechanical": - return self - if fullname == "PyGui._ViewProviderFemSolverCalculix": - return self - if fullname == "PyGui._ViewProviderFemSolverZ88": - return self - - if fullname == "PyGui._ViewProviderFemBeamSection": - return self - if fullname == "PyGui._ViewProviderFemFluidSection": - return self - if fullname == "PyGui._ViewProviderFemShellThickness": - return self +class FemMigrateGui(object): - if fullname == "_ViewProviderFemBeamSection": - return self - if fullname == "_ViewProviderFemConstraintSelfWeight": - return self - if fullname == "_ViewProviderFemMaterial": - return self - if fullname == "_ViewProviderFemMaterialMechanicalNonlinear": - return self - if fullname == "_ViewProviderFemMeshGmsh": - return self - if fullname == "_ViewProviderFemMeshGroup": - return self - if fullname == "_ViewProviderFemMeshRegion": - return self - if fullname == "_ViewProviderFemResultMechanical": - return self - if fullname == "_ViewProviderFemShellThickness": - return self - if fullname == "_ViewProviderFemSolverCalculix": - return self - if fullname == "_ViewProviderFemSolverZ88": - return self + def find_spec(self, fullname, path, target=None): - if fullname == "_ViewProviderFemMechanicalResult": - return self - if fullname == "ViewProviderFemResult": - return self - if fullname == "_ViewProviderMechanicalMaterial": - return self + if fullname in { + "femguiobjects", + "femguiobjects._ViewProviderFemConstraintBodyHeatSource", + "femguiobjects._ViewProviderFemConstraintElectrostaticPotential", + "femguiobjects._ViewProviderFemConstraintFlowVelocity", + "femguiobjects._ViewProviderFemConstraintInitialFlowVelocity", + "femguiobjects._ViewProviderFemConstraintSelfWeight", + "femguiobjects._ViewProviderFemConstraintTie", + "femguiobjects._ViewProviderFemElementFluid1D", + "femguiobjects._ViewProviderFemElementGeometry1D", + "femguiobjects._ViewProviderFemElementGeometry2D", + "femguiobjects._ViewProviderFemElementRotation1D", + "femguiobjects._ViewProviderFemMaterial", + "femguiobjects._ViewProviderFemMaterialMechanicalNonlinear", + "femguiobjects._ViewProviderFemMaterialReinforced", + "femguiobjects._ViewProviderFemMeshBoundaryLayer", + "femguiobjects._ViewProviderFemMeshGmsh", + "femguiobjects._ViewProviderFemMeshGroup", + "femguiobjects._ViewProviderFemMeshRegion", + "femguiobjects._ViewProviderFemMeshResult", + "femguiobjects._ViewProviderFemResultMechanical", + "femguiobjects._ViewProviderFemSolverCalculix", + "PyGui", + "PyGui._ViewProviderFemConstraintBodyHeatSource", + "PyGui._ViewProviderFemConstraintElectrostaticPotential", + "PyGui._ViewProviderFemConstraintFlowVelocity", + "PyGui._ViewProviderFemConstraintSelfWeight", + "PyGui._ViewProviderFemElementFluid1D", + "PyGui._ViewProviderFemElementGeometry1D", + "PyGui._ViewProviderFemElementGeometry2D", + "PyGui._ViewProviderFemElementRotation1D", + "PyGui._ViewProviderFemMaterial", + "PyGui._ViewProviderFemMaterialMechanicalNonlinear", + "PyGui._ViewProviderFemMeshBoundaryLayer", + "PyGui._ViewProviderFemMeshGmsh", + "PyGui._ViewProviderFemMeshGroup", + "PyGui._ViewProviderFemMeshRegion", + "PyGui._ViewProviderFemMeshResult", + "PyGui._ViewProviderFemResultMechanical", + "PyGui._ViewProviderFemSolverCalculix", + "PyGui._ViewProviderFemSolverZ88", + "PyGui._ViewProviderFemBeamSection", + "PyGui._ViewProviderFemFluidSection", + "PyGui._ViewProviderFemShellThickness", + "_ViewProviderFemBeamSection", + "_ViewProviderFemConstraintSelfWeight", + "_ViewProviderFemMaterial", + "_ViewProviderFemMaterialMechanicalNonlinear", + "_ViewProviderFemMeshGmsh", + "_ViewProviderFemMeshGroup", + "_ViewProviderFemMeshRegion", + "_ViewProviderFemResultMechanical", + "_ViewProviderFemShellThickness", + "_ViewProviderFemSolverCalculix", + "_ViewProviderFemSolverZ88", + "_ViewProviderFemMechanicalResult", + "ViewProviderFemResult", + "_ViewProviderMechanicalMaterial", + }: + return spec_from_loader(fullname, self) return None diff --git a/src/Mod/Fem/femtools/migrate_app.py b/src/Mod/Fem/femtools/migrate_app.py index ad3086f18b68..5b6e70b42601 100644 --- a/src/Mod/Fem/femtools/migrate_app.py +++ b/src/Mod/Fem/femtools/migrate_app.py @@ -30,147 +30,81 @@ __author__ = "Bernd Hahnebach" __url__ = "https://www.freecad.org" +from importlib.util import spec_from_loader + import FreeCAD class FemMigrateApp(object): - def find_module(self, fullname, path): - - if fullname == "femsolver.elmer.equations": - return self - if fullname == "femsolver.elmer.equations.fluxsolver": - return self - - if fullname == "femobjects": - return self - if fullname == "femobjects._FemConstraintBodyHeatSource": - return self - if fullname == "femobjects._FemConstraintElectrostaticPotential": - return self - if fullname == "femobjects._FemConstraintFlowVelocity": - return self - if fullname == "femobjects._FemConstraintInitialFlowVelocity": - return self - if fullname == "femobjects._FemConstraintSelfWeight": - return self - if fullname == "femobjects._FemConstraintTie": - return self - if fullname == "femobjects._FemElementFluid1D": - return self - if fullname == "femobjects._FemElementGeometry1D": - return self - if fullname == "femobjects._FemElementGeometry2D": - return self - if fullname == "femobjects._FemElementRotation1D": - return self - if fullname == "femobjects._FemMaterial": - return self - if fullname == "femobjects._FemMaterialMechanicalNonlinear": - return self - if fullname == "femobjects._FemMaterialReinforced": - return self - if fullname == "femobjects._FemMeshBoundaryLayer": - return self - if fullname == "femobjects._FemMeshGmsh": - return self - if fullname == "femobjects._FemMeshGroup": - return self - if fullname == "femobjects._FemMeshRegion": - return self - if fullname == "femobjects._FemMeshResult": - return self - if fullname == "femobjects._FemResultMechanical": - return self - if fullname == "femobjects._FemSolverCalculix": - return self - - if fullname == "PyObjects": - return self - if fullname == "PyObjects._FemConstraintBodyHeatSource": - return self - if fullname == "PyObjects._FemConstraintElectrostaticPotential": - return self - if fullname == "PyObjects._FemConstraintFlowVelocity": - return self - if fullname == "PyObjects._FemConstraintInitialFlowVelocity": - return self - if fullname == "PyObjects._FemConstraintSelfWeight": - return self - if fullname == "PyObjects._FemElementFluid1D": - return self - if fullname == "PyObjects._FemElementGeometry1D": - return self - if fullname == "PyObjects._FemElementGeometry2D": - return self - if fullname == "PyObjects._FemElementRotation1D": - return self - if fullname == "PyObjects._FemMaterial": - return self - if fullname == "PyObjects._FemMaterialMechanicalNonlinear": - return self - if fullname == "PyObjects._FemMeshBoundaryLayer": - return self - if fullname == "PyObjects._FemMeshGmsh": - return self - if fullname == "PyObjects._FemMeshGroup": - return self - if fullname == "PyObjects._FemMeshRegion": - return self - if fullname == "PyObjects._FemMeshResult": - return self - if fullname == "PyObjects._FemResultMechanical": - return self - if fullname == "PyObjects._FemSolverCalculix": - return self - if fullname == "PyObjects._FemSolverZ88": - return self - - if fullname == "PyObjects._FemBeamSection": - return self - if fullname == "PyObjects._FemFluidSection": - return self - if fullname == "PyObjects._FemShellThickness": - return self - - if fullname == "_FemBeamSection": - return self - if fullname == "_FemConstraintSelfWeight": - return self - if fullname == "_FemMaterial": - return self - if fullname == "_FemMaterialMechanicalNonlinear": - return self - if fullname == "_FemMeshGmsh": - return self - if fullname == "_FemMeshGroup": - return self - if fullname == "_FemMeshRegion": - return self - if fullname == "_FemResultMechanical": - return self - if fullname == "_FemShellThickness": - return self - if fullname == "_FemSolverCalculix": - return self - if fullname == "_FemSolverZ88": - return self - - if fullname == "_FemMechanicalResult": - return self - if fullname == "FemResult": - return self - if fullname == "_MechanicalMaterial": - return self - - if fullname == "FemBeamSection": - return self - if fullname == "FemShellThickness": - return self - if fullname == "MechanicalAnalysis": - return self - if fullname == "MechanicalMaterial": - return self + def find_spec(self, fullname, path, target=None): + if fullname in { + "femsolver.elmer.equations", + "femsolver.elmer.equations.fluxsolver", + "femobjects", + "femobjects._FemConstraintBodyHeatSource", + "femobjects._FemConstraintElectrostaticPotential", + "femobjects._FemConstraintFlowVelocity", + "femobjects._FemConstraintInitialFlowVelocity", + "femobjects._FemConstraintSelfWeight", + "femobjects._FemConstraintTie", + "femobjects._FemElementFluid1D", + "femobjects._FemElementGeometry1D", + "femobjects._FemElementGeometry2D", + "femobjects._FemElementRotation1D", + "femobjects._FemMaterial", + "femobjects._FemMaterialMechanicalNonlinear", + "femobjects._FemMaterialReinforced", + "femobjects._FemMeshBoundaryLayer", + "femobjects._FemMeshGmsh", + "femobjects._FemMeshGroup", + "femobjects._FemMeshRegion", + "femobjects._FemMeshResult", + "femobjects._FemResultMechanical", + "femobjects._FemSolverCalculix", + "PyObjects", + "PyObjects._FemConstraintBodyHeatSource", + "PyObjects._FemConstraintElectrostaticPotential", + "PyObjects._FemConstraintFlowVelocity", + "PyObjects._FemConstraintInitialFlowVelocity", + "PyObjects._FemConstraintSelfWeight", + "PyObjects._FemElementFluid1D", + "PyObjects._FemElementGeometry1D", + "PyObjects._FemElementGeometry2D", + "PyObjects._FemElementRotation1D", + "PyObjects._FemMaterial", + "PyObjects._FemMaterialMechanicalNonlinear", + "PyObjects._FemMeshBoundaryLayer", + "PyObjects._FemMeshGmsh", + "PyObjects._FemMeshGroup", + "PyObjects._FemMeshRegion", + "PyObjects._FemMeshResult", + "PyObjects._FemResultMechanical", + "PyObjects._FemSolverCalculix", + "PyObjects._FemSolverZ88", + "PyObjects._FemBeamSection", + "PyObjects._FemFluidSection", + "PyObjects._FemShellThickness", + "_FemBeamSection", + "_FemConstraintSelfWeight", + "_FemMaterial", + "_FemMaterialMechanicalNonlinear", + "_FemMeshGmsh", + "_FemMeshGroup", + "_FemMeshRegion", + "_FemResultMechanical", + "_FemShellThickness", + "_FemSolverCalculix", + "_FemSolverZ88", + "_FemMechanicalResult", + "FemResult", + "_MechanicalMaterial", + "FemBeamSection", + "FemShellThickness", + "MechanicalAnalysis", + "MechanicalMaterial", + }: + return spec_from_loader(fullname, self) return None def create_module(self, spec): From 244ba81c13d8bcbfe59e708fa33710cd9c14ac49 Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Wed, 29 May 2024 11:01:35 +0100 Subject: [PATCH 002/161] black format --- src/Mod/Fem/femguiutils/migrate_gui.py | 182 ++++++++++++++++++------- src/Mod/Fem/femtools/migrate_app.py | 92 +++++++++++-- 2 files changed, 218 insertions(+), 56 deletions(-) diff --git a/src/Mod/Fem/femguiutils/migrate_gui.py b/src/Mod/Fem/femguiutils/migrate_gui.py index b682f733049c..6824a4e8dd52 100644 --- a/src/Mod/Fem/femguiutils/migrate_gui.py +++ b/src/Mod/Fem/femguiutils/migrate_gui.py @@ -112,220 +112,308 @@ def load_module(self, module): module.__path__ = "femguiobjects" if module.__name__ == "femguiobjects._ViewProviderFemConstraintBodyHeatSource": import femviewprovider.view_constraint_bodyheatsource - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_bodyheatsource.VPConstraintBodyHeatSource + ) if module.__name__ == "femguiobjects._ViewProviderFemConstraintElectrostaticPotential": import femviewprovider.view_constraint_electrostaticpotential - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_electrostaticpotential.VPConstraintElectroStaticPotential + ) if module.__name__ == "femguiobjects._ViewProviderFemConstraintFlowVelocity": import femviewprovider.view_constraint_flowvelocity - module.ViewProxy = \ - femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity + + module.ViewProxy = femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity if module.__name__ == "femguiobjects._ViewProviderFemConstraintInitialFlowVelocity": import femviewprovider.view_constraint_initialflowvelocity - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_initialflowvelocity.VPConstraintInitialFlowVelocity + ) if module.__name__ == "femguiobjects._ViewProviderFemConstraintSelfWeight": import femviewprovider.view_constraint_selfweight - module._ViewProviderFemConstraintSelfWeight = \ + + module._ViewProviderFemConstraintSelfWeight = ( femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight + ) if module.__name__ == "femguiobjects._ViewProviderFemConstraintTie": import femviewprovider.view_constraint_tie - module._ViewProviderFemConstraintTie = \ + + module._ViewProviderFemConstraintTie = ( femviewprovider.view_constraint_tie.VPConstraintTie + ) if module.__name__ == "femguiobjects._ViewProviderFemElementFluid1D": import femviewprovider.view_element_fluid1D - module._ViewProviderFemElementFluid1D = \ + + module._ViewProviderFemElementFluid1D = ( femviewprovider.view_element_fluid1D.VPElementFluid1D + ) if module.__name__ == "femguiobjects._ViewProviderFemElementGeometry1D": import femviewprovider.view_element_geometry1D - module._ViewProviderFemElementGeometry1D = \ + + module._ViewProviderFemElementGeometry1D = ( femviewprovider.view_element_geometry1D.VPElementGeometry1D + ) if module.__name__ == "femguiobjects._ViewProviderFemElementGeometry2D": import femviewprovider.view_element_geometry2D - module._ViewProviderFemElementGeometry2D = \ + + module._ViewProviderFemElementGeometry2D = ( femviewprovider.view_element_geometry2D.VPElementGeometry2D + ) if module.__name__ == "femguiobjects._ViewProviderFemElementRotation1D": import femviewprovider.view_element_rotation1D - module._ViewProviderFemElementRotation1D = \ + + module._ViewProviderFemElementRotation1D = ( femviewprovider.view_element_rotation1D.VPElementRotation1D + ) if module.__name__ == "femguiobjects._ViewProviderFemMaterial": import femviewprovider.view_material_common + module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon if module.__name__ == "femguiobjects._ViewProviderFemMaterialMechanicalNonlinear": import femviewprovider.view_material_mechanicalnonlinear - module._ViewProviderFemMaterialMechanicalNonlinear = \ + + module._ViewProviderFemMaterialMechanicalNonlinear = ( femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear + ) if module.__name__ == "femguiobjects._ViewProviderFemMaterialReinforced": import femviewprovider.view_material_reinforced - module._ViewProviderFemMaterialReinforced = \ + + module._ViewProviderFemMaterialReinforced = ( femviewprovider.view_material_reinforced.VPMaterialReinforced + ) if module.__name__ == "femguiobjects._ViewProviderFemMeshBoundaryLayer": import femviewprovider.view_mesh_boundarylayer - module._ViewProviderFemMeshBoundaryLayer = \ + + module._ViewProviderFemMeshBoundaryLayer = ( femviewprovider.view_mesh_boundarylayer.VPMeshBoundaryLayer + ) if module.__name__ == "femguiobjects._ViewProviderFemMeshGmsh": import femviewprovider.view_mesh_gmsh + module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh if module.__name__ == "femguiobjects._ViewProviderFemMeshGroup": import femviewprovider.view_mesh_group + module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup if module.__name__ == "femguiobjects._ViewProviderFemMeshRegion": import femviewprovider.view_mesh_region + module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion if module.__name__ == "femguiobjects._ViewProviderFemMeshResult": import femviewprovider.view_mesh_result + module._ViewProviderFemMeshResult = femviewprovider.view_mesh_result.VPFemMeshResult if module.__name__ == "femguiobjects._ViewProviderFemResultMechanical": import femviewprovider.view_result_mechanical - module._ViewProviderFemResultMechanical = \ + + module._ViewProviderFemResultMechanical = ( femviewprovider.view_result_mechanical.VPResultMechanical + ) if module.__name__ == "femguiobjects._ViewProviderFemSolverCalculix": import femviewprovider.view_solver_ccxtools - module._ViewProviderFemSolverCalculix = \ + + module._ViewProviderFemSolverCalculix = ( femviewprovider.view_solver_ccxtools.VPSolverCcxTools + ) if module.__name__ == "PyGui": module.__path__ = "PyGui" if module.__name__ == "PyGui._ViewProviderFemConstraintBodyHeatSource": import femviewprovider.view_constraint_bodyheatsource - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_bodyheatsource.VPConstraintBodyHeatSource + ) if module.__name__ == "PyGui._ViewProviderFemConstraintElectrostaticPotential": import femviewprovider.view_constraint_electrostaticpotential - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_electrostaticpotential.VPConstraintElectroStaticPotential + ) if module.__name__ == "PyGui._ViewProviderFemConstraintFlowVelocity": import femviewprovider.view_constraint_flowvelocity - module.ViewProxy = \ - femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity + + module.ViewProxy = femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity if module.__name__ == "PyGui._ViewProviderFemConstraintInitialFlowVelocity": import femviewprovider.view_constraint_initialflowvelocity - module.ViewProxy = \ + + module.ViewProxy = ( femviewprovider.view_constraint_initialflowvelocity.VPConstraintInitialFlowVelocity + ) if module.__name__ == "PyGui._ViewProviderFemConstraintSelfWeight": import femviewprovider.view_constraint_selfweight - module._ViewProviderFemConstraintSelfWeight = \ + + module._ViewProviderFemConstraintSelfWeight = ( femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight + ) if module.__name__ == "PyGui._ViewProviderFemElementFluid1D": import femviewprovider.view_element_fluid1D - module._ViewProviderFemElementFluid1D = \ + + module._ViewProviderFemElementFluid1D = ( femviewprovider.view_element_fluid1D.VPElementFluid1D + ) if module.__name__ == "PyGui._ViewProviderFemElementGeometry1D": import femviewprovider.view_element_geometry1D - module._ViewProviderFemElementGeometry1D = \ + + module._ViewProviderFemElementGeometry1D = ( femviewprovider.view_element_geometry1D.VPElementGeometry1D + ) if module.__name__ == "PyGui._ViewProviderFemElementGeometry2D": import femviewprovider.view_element_geometry2D - module._ViewProviderFemElementGeometry2D = \ + + module._ViewProviderFemElementGeometry2D = ( femviewprovider.view_element_geometry2D.VPElementGeometry2D + ) if module.__name__ == "PyGui._ViewProviderFemElementRotation1D": import femviewprovider.view_element_rotation1D - module._ViewProviderFemElementRotation1D = \ + + module._ViewProviderFemElementRotation1D = ( femviewprovider.view_element_rotation1D.VPElementRotation1D + ) if module.__name__ == "PyGui._ViewProviderFemMaterial": import femviewprovider.view_material_common - module._ViewProviderFemMaterial = \ - femviewprovider.view_material_common.VPMaterialCommon + + module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon if module.__name__ == "PyGui._ViewProviderFemMaterialMechanicalNonlinear": import femviewprovider.view_material_mechanicalnonlinear - module._ViewProviderFemMaterialMechanicalNonlinear = \ + + module._ViewProviderFemMaterialMechanicalNonlinear = ( femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear + ) if module.__name__ == "PyGui._ViewProviderFemMeshBoundaryLayer": import femviewprovider.view_mesh_boundarylayer - module._ViewProviderFemMeshBoundaryLayer = \ + + module._ViewProviderFemMeshBoundaryLayer = ( femviewprovider.view_mesh_boundarylayer.VPMeshBoundaryLayer + ) if module.__name__ == "PyGui._ViewProviderFemMeshGmsh": import femviewprovider.view_mesh_gmsh + module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh if module.__name__ == "PyGui._ViewProviderFemMeshGroup": import femviewprovider.view_mesh_group + module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup if module.__name__ == "PyGui._ViewProviderFemMeshRegion": import femviewprovider.view_mesh_region + module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion if module.__name__ == "PyGui._ViewProviderFemMeshResult": import femviewprovider.view_mesh_result + module._ViewProviderFemMeshResult = femviewprovider.view_mesh_result.VPFemMeshResult if module.__name__ == "PyGui._ViewProviderFemResultMechanical": import femviewprovider.view_result_mechanical - module._ViewProviderFemResultMechanical = \ + + module._ViewProviderFemResultMechanical = ( femviewprovider.view_result_mechanical.VPResultMechanical + ) if module.__name__ == "PyGui._ViewProviderFemSolverCalculix": import femviewprovider.view_solver_ccxtools - module._ViewProviderFemSolverCalculix = \ + + module._ViewProviderFemSolverCalculix = ( femviewprovider.view_solver_ccxtools.VPSolverCcxTools + ) if module.__name__ == "PyGui._ViewProviderFemSolverZ88": import femsolver.z88.solver + module._ViewProviderFemSolverZ88 = femsolver.z88.solver.ViewProxy if module.__name__ == "PyGui._ViewProviderFemBeamSection": import femviewprovider.view_element_geometry1D - module._ViewProviderFemBeamSection = \ + + module._ViewProviderFemBeamSection = ( femviewprovider.view_element_geometry1D.VPElementGeometry1D + ) if module.__name__ == "PyGui._ViewProviderFemFluidSection": import femviewprovider.view_element_fluid1D - module._ViewProviderFemFluidSection = \ + + module._ViewProviderFemFluidSection = ( femviewprovider.view_element_fluid1D.VPElementFluid1D + ) if module.__name__ == "PyGui._ViewProviderFemShellThickness": import femviewprovider.view_element_geometry2D - module._ViewProviderFemShellThickness = \ + + module._ViewProviderFemShellThickness = ( femviewprovider.view_element_geometry2D.VPElementGeometry2D + ) if module.__name__ == "_ViewProviderFemBeamSection": import femviewprovider.view_element_geometry1D - module._ViewProviderFemBeamSection = \ + + module._ViewProviderFemBeamSection = ( femviewprovider.view_element_geometry1D.VPElementGeometry1D + ) if module.__name__ == "_ViewProviderFemConstraintSelfWeight": import femviewprovider.view_constraint_selfweight - module._ViewProviderFemConstraintSelfWeight = \ + + module._ViewProviderFemConstraintSelfWeight = ( femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight + ) if module.__name__ == "_ViewProviderFemMaterial": import femviewprovider.view_material_common - module._ViewProviderFemMaterial = \ - femviewprovider.view_material_common.VPMaterialCommon + + module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon if module.__name__ == "_ViewProviderFemMaterialMechanicalNonlinear": import femviewprovider.view_material_mechanicalnonlinear - module._ViewProviderFemMaterialMechanicalNonlinear = \ + + module._ViewProviderFemMaterialMechanicalNonlinear = ( femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear + ) if module.__name__ == "_ViewProviderFemMeshGmsh": import femviewprovider.view_mesh_gmsh + module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh if module.__name__ == "_ViewProviderFemMeshGroup": import femviewprovider.view_mesh_group + module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup if module.__name__ == "_ViewProviderFemMeshRegion": import femviewprovider.view_mesh_region + module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion if module.__name__ == "_ViewProviderFemResultMechanical": import femviewprovider.view_result_mechanical - module._ViewProviderFemResultMechanical = \ + + module._ViewProviderFemResultMechanical = ( femviewprovider.view_result_mechanical.VPResultMechanical + ) if module.__name__ == "_ViewProviderFemShellThickness": import femviewprovider.view_element_geometry2D - module._ViewProviderFemShellThickness = \ + + module._ViewProviderFemShellThickness = ( femviewprovider.view_element_geometry2D.VPElementGeometry2D + ) if module.__name__ == "_ViewProviderFemSolverCalculix": import femviewprovider.view_solver_ccxtools - module._ViewProviderFemSolverCalculix = \ + + module._ViewProviderFemSolverCalculix = ( femviewprovider.view_solver_ccxtools.VPSolverCcxTools + ) if module.__name__ == "_ViewProviderFemSolverZ88": import femsolver.z88.solver + module._ViewProviderFemSolverZ88 = femsolver.z88.solver.ViewProxy if module.__name__ == "_ViewProviderFemMechanicalResult": import femviewprovider.view_result_mechanical - module._ViewProviderFemMechanicalResult = \ + + module._ViewProviderFemMechanicalResult = ( femviewprovider.view_result_mechanical.VPResultMechanical + ) if module.__name__ == "ViewProviderFemResult": import femviewprovider.view_result_mechanical - module.ViewProviderFemResult = \ - femviewprovider.view_result_mechanical.VPResultMechanical + + module.ViewProviderFemResult = femviewprovider.view_result_mechanical.VPResultMechanical if module.__name__ == "_ViewProviderMechanicalMaterial": import femviewprovider.view_material_common - module._ViewProviderMechanicalMaterial = \ + + module._ViewProviderMechanicalMaterial = ( femviewprovider.view_material_common.VPMaterialCommon + ) return None diff --git a/src/Mod/Fem/femtools/migrate_app.py b/src/Mod/Fem/femtools/migrate_app.py index 5b6e70b42601..26c9085c6be0 100644 --- a/src/Mod/Fem/femtools/migrate_app.py +++ b/src/Mod/Fem/femtools/migrate_app.py @@ -119,6 +119,7 @@ def load_module(self, module): return self if module.__name__ == "femsolver.elmer.equations.fluxsolver": import femsolver.elmer.equations.flux + module.Proxy = femsolver.elmer.equations.flux.Proxy if FreeCAD.GuiUp: module.ViewProxy = femsolver.elmer.equations.flux.ViewProxy @@ -127,212 +128,285 @@ def load_module(self, module): module.__path__ = "femobjects" if module.__name__ == "femobjects._FemConstraintBodyHeatSource": import femobjects.constraint_bodyheatsource + module.Proxy = femobjects.constraint_bodyheatsource.ConstraintBodyHeatSource if module.__name__ == "femobjects._FemConstraintElectrostaticPotential": import femobjects.constraint_electrostaticpotential - module.Proxy = \ + + module.Proxy = ( femobjects.constraint_electrostaticpotential.ConstraintElectrostaticPotential + ) if module.__name__ == "femobjects._FemConstraintFlowVelocity": import femobjects.constraint_flowvelocity + module.Proxy = femobjects.constraint_flowvelocity.ConstraintFlowVelocity if module.__name__ == "femobjects._FemConstraintInitialFlowVelocity": import femobjects.constraint_initialflowvelocity + module.Proxy = femobjects.constraint_initialflowvelocity.ConstraintInitialFlowVelocity if module.__name__ == "femobjects._FemConstraintSelfWeight": import femobjects.constraint_selfweight + module._FemConstraintSelfWeight = femobjects.constraint_selfweight.ConstraintSelfWeight if module.__name__ == "femobjects._FemConstraintTie": import femobjects.constraint_tie + module._FemConstraintTie = femobjects.constraint_tie.ConstraintTie if module.__name__ == "femobjects._FemElementFluid1D": import femobjects.element_fluid1D + module._FemElementFluid1D = femobjects.element_fluid1D.ElementFluid1D if module.__name__ == "femobjects._FemElementGeometry1D": import femobjects.element_geometry1D + module._FemElementGeometry1D = femobjects.element_geometry1D.ElementGeometry1D if module.__name__ == "femobjects._FemElementGeometry2D": import femobjects.element_geometry2D + module._FemElementGeometry2D = femobjects.element_geometry2D.ElementGeometry2D if module.__name__ == "femobjects._FemElementRotation1D": import femobjects.element_rotation1D + module._FemElementRotation1D = femobjects.element_rotation1D.ElementRotation1D if module.__name__ == "femobjects._FemMaterial": import femobjects.material_common + module._FemMaterial = femobjects.material_common.MaterialCommon if module.__name__ == "femobjects._FemMaterialMechanicalNonlinear": import femobjects.material_mechanicalnonlinear - module._FemMaterialMechanicalNonlinear = \ + + module._FemMaterialMechanicalNonlinear = ( femobjects.material_mechanicalnonlinear.MaterialMechanicalNonlinear + ) if module.__name__ == "femobjects._FemMaterialReinforced": import femobjects.material_reinforced + module._FemMaterialReinforced = femobjects.material_reinforced.MaterialReinforced if module.__name__ == "femobjects._FemMeshBoundaryLayer": import femobjects.mesh_boundarylayer + module._FemMeshBoundaryLayer = femobjects.mesh_boundarylayer.MeshBoundaryLayer if module.__name__ == "femobjects._FemMeshGmsh": import femobjects.mesh_gmsh + module._FemMeshGmsh = femobjects.mesh_gmsh.MeshGmsh if module.__name__ == "femobjects._FemMeshGroup": import femobjects.mesh_group + module._FemMeshGroup = femobjects.mesh_group.MeshGroup if module.__name__ == "femobjects._FemMeshRegion": import femobjects.mesh_region + module._FemMeshRegion = femobjects.mesh_region.MeshRegion if module.__name__ == "femobjects._FemMeshResult": import femobjects.mesh_result + module._FemMeshResult = femobjects.mesh_result.MeshResult if module.__name__ == "femobjects._FemResultMechanical": import femobjects.result_mechanical + module._FemResultMechanical = femobjects.result_mechanical.ResultMechanical if module.__name__ == "femobjects._FemSolverCalculix": import femobjects.solver_ccxtools + module._FemSolverCalculix = femobjects.solver_ccxtools.SolverCcxTools if module.__name__ == "PyObjects": module.__path__ = "PyObjects" if module.__name__ == "PyObjects._FemConstraintBodyHeatSource": import femobjects.constraint_bodyheatsource + module.Proxy = femobjects.constraint_bodyheatsource.ConstraintBodyHeatSource if module.__name__ == "PyObjects._FemConstraintElectrostaticPotential": import femobjects.constraint_electrostaticpotential - module.Proxy = \ + + module.Proxy = ( femobjects.constraint_electrostaticpotential.ConstraintElectrostaticPotential + ) if module.__name__ == "PyObjects._FemConstraintFlowVelocity": import femobjects.constraint_flowvelocity + module.Proxy = femobjects.constraint_flowvelocity.ConstraintFlowVelocity if module.__name__ == "PyObjects._FemConstraintInitialFlowVelocity": import femobjects.constraint_initialflowvelocity + module.Proxy = femobjects.constraint_initialflowvelocity.ConstraintInitialFlowVelocity if module.__name__ == "PyObjects._FemConstraintSelfWeight": import femobjects.constraint_selfweight + module._FemConstraintSelfWeight = femobjects.constraint_selfweight.ConstraintSelfWeight if module.__name__ == "PyObjects._FemElementFluid1D": import femobjects.element_fluid1D + module._FemElementFluid1D = femobjects.element_fluid1D.ElementFluid1D if module.__name__ == "PyObjects._FemElementGeometry1D": import femobjects.element_geometry1D + module._FemElementGeometry1D = femobjects.element_geometry1D.ElementGeometry1D if module.__name__ == "PyObjects._FemElementGeometry2D": import femobjects.element_geometry2D + module._FemElementGeometry2D = femobjects.element_geometry2D.ElementGeometry2D if module.__name__ == "PyObjects._FemElementRotation1D": import femobjects.element_rotation1D + module._FemElementRotation1D = femobjects.element_rotation1D.ElementRotation1D if module.__name__ == "PyObjects._FemMaterial": import femobjects.material_common + module._FemMaterial = femobjects.material_common.MaterialCommon if module.__name__ == "PyObjects._FemMaterialMechanicalNonlinear": import femobjects.material_mechanicalnonlinear - module._FemMaterialMechanicalNonlinear = \ + + module._FemMaterialMechanicalNonlinear = ( femobjects.material_mechanicalnonlinear.MaterialMechanicalNonlinear + ) if module.__name__ == "PyObjects._FemMeshBoundaryLayer": import femobjects.mesh_boundarylayer + module._FemMeshBoundaryLayer = femobjects.mesh_boundarylayer.MeshBoundaryLayer if module.__name__ == "PyObjects._FemMeshGmsh": import femobjects.mesh_gmsh + module._FemMeshGmsh = femobjects.mesh_gmsh.MeshGmsh if module.__name__ == "PyObjects._FemMeshGroup": import femobjects.mesh_group + module._FemMeshGroup = femobjects.mesh_group.MeshGroup if module.__name__ == "PyObjects._FemMeshRegion": import femobjects.mesh_region + module._FemMeshRegion = femobjects.mesh_region.MeshRegion if module.__name__ == "PyObjects._FemMeshResult": import femobjects.mesh_result + module._FemMeshResult = femobjects.mesh_result.MeshResult if module.__name__ == "PyObjects._FemResultMechanical": import femobjects.result_mechanical + module._FemResultMechanical = femobjects.result_mechanical.ResultMechanical if module.__name__ == "PyObjects._FemSolverCalculix": import femobjects.solver_ccxtools + module._FemSolverCalculix = femobjects.solver_ccxtools.SolverCcxTools if module.__name__ == "PyObjects._FemSolverZ88": import femsolver.z88.solver + module._FemSolverZ88 = femsolver.z88.solver.Proxy if module.__name__ == "PyObjects._FemBeamSection": import femobjects.element_geometry1D + module._FemBeamSection = femobjects.element_geometry1D.ElementGeometry1D if module.__name__ == "PyObjects._FemFluidSection": import femobjects.element_fluid1D + module._FemFluidSection = femobjects.element_fluid1D.ElementFluid1D if module.__name__ == "PyObjects._FemShellThickness": import femobjects.element_geometry2D + module._FemShellThickness = femobjects.element_geometry2D.ElementGeometry2D if module.__name__ == "_FemBeamSection": import femobjects.element_geometry1D + module._FemBeamSection = femobjects.element_geometry1D.ElementGeometry1D if module.__name__ == "_FemConstraintSelfWeight": import femobjects.constraint_selfweight + module._FemConstraintSelfWeight = femobjects.constraint_selfweight.ConstraintSelfWeight if module.__name__ == "_FemMaterial": import femobjects.material_common + module._FemMaterial = femobjects.material_common.MaterialCommon if module.__name__ == "_FemMaterialMechanicalNonlinear": import femobjects.material_mechanicalnonlinear - module._FemMaterialMechanicalNonlinear = \ + + module._FemMaterialMechanicalNonlinear = ( femobjects.material_mechanicalnonlinear.MaterialMechanicalNonlinear + ) if module.__name__ == "_FemMeshGmsh": import femobjects.mesh_gmsh + module._FemMeshGmsh = femobjects.mesh_gmsh.MeshGmsh if module.__name__ == "_FemMeshGroup": import femobjects.mesh_group + module._FemMeshGroup = femobjects.mesh_group.MeshGroup if module.__name__ == "_FemMeshRegion": import femobjects.mesh_region + module._FemMeshRegion = femobjects.mesh_region.MeshRegion if module.__name__ == "_FemResultMechanical": import femobjects.result_mechanical + module._FemResultMechanical = femobjects.result_mechanical.ResultMechanical if module.__name__ == "_FemShellThickness": import femobjects.element_geometry2D + module._FemShellThickness = femobjects.element_geometry2D.ElementGeometry2D if module.__name__ == "_FemSolverCalculix": import femobjects.solver_ccxtools + module._FemSolverCalculix = femobjects.solver_ccxtools.SolverCcxTools if module.__name__ == "_FemSolverZ88": import femsolver.z88.solver + module._FemSolverZ88 = femsolver.z88.solver.Proxy if module.__name__ == "_FemMechanicalResult": import femobjects.result_mechanical + module._FemMechanicalResult = femobjects.result_mechanical.ResultMechanical if module.__name__ == "FemResult": import femobjects.result_mechanical + module.FemResult = femobjects.result_mechanical.ResultMechanical if module.__name__ == "_MechanicalMaterial": import femobjects.material_common + module._MechanicalMaterial = femobjects.material_common.MaterialCommon if module.__name__ == "FemBeamSection": import femobjects.element_geometry1D + module._FemBeamSection = femobjects.element_geometry1D.ElementGeometry1D if FreeCAD.GuiUp: import femviewprovider.view_element_geometry1D - module._ViewProviderFemBeamSection = \ + + module._ViewProviderFemBeamSection = ( femviewprovider.view_element_geometry1D.VPElementGeometry1D + ) if module.__name__ == "FemShellThickness": import femobjects.element_geometry2D + module._FemShellThickness = femobjects.element_geometry2D.ElementGeometry2D if FreeCAD.GuiUp: import femviewprovider.view_element_geometry2D - module._ViewProviderFemShellThickness = \ + + module._ViewProviderFemShellThickness = ( femviewprovider.view_element_geometry2D.VPElementGeometry2D + ) if module.__name__ == "MechanicalAnalysis": import femobjects.base_fempythonobject + module._FemAnalysis = femobjects.base_fempythonobject.BaseFemPythonObject if FreeCAD.GuiUp: import femviewprovider.view_base_femobject - module._ViewProviderFemAnalysis = \ + + module._ViewProviderFemAnalysis = ( femviewprovider.view_base_femobject.VPBaseFemObject + ) if module.__name__ == "MechanicalMaterial": import femobjects.material_common + module._MechanicalMaterial = femobjects.material_common.MaterialCommon if FreeCAD.GuiUp: import femviewprovider.view_material_common - module._ViewProviderMechanicalMaterial = \ + + module._ViewProviderMechanicalMaterial = ( femviewprovider.view_material_common.VPMaterialCommon + ) return None From 4c6b7dadebc3b7319b6c9502b7e1507f18eeebe2 Mon Sep 17 00:00:00 2001 From: liukaiwen Date: Sat, 20 Jul 2024 01:07:04 +0800 Subject: [PATCH 003/161] refactor: move some nodes to Inventor folder --- src/Gui/CMakeLists.txt | 16 +- src/Gui/CommandView.cpp | 2 +- src/Gui/{ => Inventor}/So3DAnnotation.cpp | 7 +- src/Gui/{ => Inventor}/So3DAnnotation.h | 0 src/Gui/{ => Inventor}/SoAxisCrossKit.cpp | 3 - src/Gui/{ => Inventor}/SoAxisCrossKit.h | 240 ++++---- src/Gui/Inventor/SoDrawingGrid.cpp | 12 +- src/Gui/{ => Inventor}/SoFCBoundingBox.cpp | 542 +++++++++--------- src/Gui/{ => Inventor}/SoFCBoundingBox.h | 212 +++---- src/Gui/{ => Inventor}/SoMouseWheelEvent.cpp | 0 src/Gui/{ => Inventor}/SoMouseWheelEvent.h | 0 src/Gui/InventorNavigationStyle.cpp | 2 +- src/Gui/ManualAlignment.cpp | 7 +- src/Gui/NavigationStyle.cpp | 2 +- src/Gui/Quarter/Mouse.cpp | 2 +- src/Gui/SoFCCSysDragger.cpp | 2 +- src/Gui/SoFCCSysDragger.h | 2 - src/Gui/SoFCDB.cpp | 8 +- src/Gui/View3DInventorViewer.cpp | 4 +- src/Gui/View3DPy.cpp | 2 +- src/Gui/ViewProvider.cpp | 2 +- src/Gui/ViewProviderGeometryObject.cpp | 5 +- src/Mod/CAM/Gui/ViewProviderPath.cpp | 4 +- src/Mod/Part/Gui/ViewProvider2DObject.cpp | 2 +- .../Part/Gui/ViewProviderGridExtension.cpp | 2 +- src/Mod/Sketcher/Gui/EditModeCoinManager.cpp | 2 +- 26 files changed, 537 insertions(+), 545 deletions(-) rename src/Gui/{ => Inventor}/So3DAnnotation.cpp (97%) rename src/Gui/{ => Inventor}/So3DAnnotation.h (100%) rename src/Gui/{ => Inventor}/SoAxisCrossKit.cpp (99%) rename src/Gui/{ => Inventor}/SoAxisCrossKit.h (97%) rename src/Gui/{ => Inventor}/SoFCBoundingBox.cpp (96%) rename src/Gui/{ => Inventor}/SoFCBoundingBox.h (97%) rename src/Gui/{ => Inventor}/SoMouseWheelEvent.cpp (100%) rename src/Gui/{ => Inventor}/SoMouseWheelEvent.h (100%) diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 93fd4262a0c1..e4b7b7483a77 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1009,8 +1009,11 @@ SET(Inventor_CPP_SRCS Inventor/SoAutoZoomTranslation.cpp Inventor/MarkerBitmaps.cpp Inventor/SmSwitchboard.cpp + Inventor/SoFCBoundingBox.cpp + Inventor/So3DAnnotation.cpp + Inventor/SoAxisCrossKit.cpp + Inventor/SoMouseWheelEvent.cpp SoFCBackgroundGradient.cpp - SoFCBoundingBox.cpp SoFCColorBar.cpp SoFCColorBarNotifier.cpp SoFCColorGradient.cpp @@ -1025,12 +1028,9 @@ SET(Inventor_CPP_SRCS SoFCSelectionAction.cpp SoFCVectorizeSVGAction.cpp SoFCVectorizeU3DAction.cpp - So3DAnnotation.cpp - SoAxisCrossKit.cpp SoTextLabel.cpp SoDatumLabel.cpp SoTouchEvents.cpp - SoMouseWheelEvent.cpp SoFCCSysDragger.cpp ArcEngine.cpp ) @@ -1040,8 +1040,10 @@ SET(Inventor_SRCS Inventor/SoAutoZoomTranslation.h Inventor/MarkerBitmaps.h Inventor/SmSwitchboard.h + Inventor/SoFCBoundingBox.h + Inventor/SoAxisCrossKit.h + Inventor/SoMouseWheelEvent.h SoFCBackgroundGradient.h - SoFCBoundingBox.h SoFCColorBar.h SoFCColorBarNotifier.h SoFCColorGradient.h @@ -1056,11 +1058,9 @@ SET(Inventor_SRCS SoFCSelectionAction.h SoFCVectorizeSVGAction.h SoFCVectorizeU3DAction.h - SoAxisCrossKit.h SoTextLabel.h SoDatumLabel.h SoTouchEvents.h - SoMouseWheelEvent.h SoFCCSysDragger.h ArcEngine.h ) @@ -1297,7 +1297,7 @@ SET(FreeCADGui_SRCS ${Dock_Windows_SRCS} ${Editor_SRCS} ${Help_SRCS} - ${Inventor_SRCS} + ${Inventor_CPP_SRCS} ${Language_SRCS} ${Propertyeditor_SRCS} ${Task_View_SRCS} diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index f9b2d408ae93..5213cdc108e0 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -65,6 +65,7 @@ #include "Document.h" #include "FileDialog.h" #include "ImageView.h" +#include "Inventor/SoAxisCrossKit.h" #include "Macro.h" #include "MainWindow.h" #include "NavigationStyle.h" @@ -73,7 +74,6 @@ #include "SceneInspector.h" #include "Selection.h" #include "SelectionObject.h" -#include "SoAxisCrossKit.h" #include "SoFCOffscreenRenderer.h" #include "TextureMapping.h" #include "Tools.h" diff --git a/src/Gui/So3DAnnotation.cpp b/src/Gui/Inventor/So3DAnnotation.cpp similarity index 97% rename from src/Gui/So3DAnnotation.cpp rename to src/Gui/Inventor/So3DAnnotation.cpp index a42662bb8bd2..b28126cf4505 100644 --- a/src/Gui/So3DAnnotation.cpp +++ b/src/Gui/Inventor/So3DAnnotation.cpp @@ -23,11 +23,14 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include +#ifdef FC_OS_MACOSX +#include +#else +#include +#endif #include #endif -#include "SoFCDB.h" #include "So3DAnnotation.h" using namespace Gui; diff --git a/src/Gui/So3DAnnotation.h b/src/Gui/Inventor/So3DAnnotation.h similarity index 100% rename from src/Gui/So3DAnnotation.h rename to src/Gui/Inventor/So3DAnnotation.h diff --git a/src/Gui/SoAxisCrossKit.cpp b/src/Gui/Inventor/SoAxisCrossKit.cpp similarity index 99% rename from src/Gui/SoAxisCrossKit.cpp rename to src/Gui/Inventor/SoAxisCrossKit.cpp index 4c637e40afb1..ff02b98d29f4 100644 --- a/src/Gui/SoAxisCrossKit.cpp +++ b/src/Gui/Inventor/SoAxisCrossKit.cpp @@ -23,9 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# ifdef FC_OS_WIN32 -# include -# endif # ifdef FC_OS_MACOSX # include # else diff --git a/src/Gui/SoAxisCrossKit.h b/src/Gui/Inventor/SoAxisCrossKit.h similarity index 97% rename from src/Gui/SoAxisCrossKit.h rename to src/Gui/Inventor/SoAxisCrossKit.h index 922e35d13be1..151f5f40c394 100644 --- a/src/Gui/SoAxisCrossKit.h +++ b/src/Gui/Inventor/SoAxisCrossKit.h @@ -1,120 +1,120 @@ -/*************************************************************************** - * Copyright (c) 2010 Werner Mayer * - * * - * 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 GUI_SOSHAPESCALE_H -#define GUI_SOSHAPESCALE_H - -#include -#include -#include -#include -#include -#include -#include - - -class SbViewport; -class SoState; -class SbColor; -class SbVec2s; - -namespace Gui { -class GuiExport SoShapeScale : public SoBaseKit { - using inherited = SoBaseKit; - - SO_KIT_HEADER(SoShapeScale); - - SO_KIT_CATALOG_ENTRY_HEADER(topSeparator); - SO_KIT_CATALOG_ENTRY_HEADER(scale); - SO_KIT_CATALOG_ENTRY_HEADER(shape); - -public: - SoShapeScale(); - static void initClass(); - - SoSFFloat active; - SoSFFloat scaleFactor; - -protected: - void GLRender(SoGLRenderAction * action) override; - ~SoShapeScale() override; -}; - -class GuiExport SoAxisCrossKit : public SoBaseKit { - using inherited = SoBaseKit; - - SO_KIT_HEADER(SoAxisCrossKit); - - SO_KIT_CATALOG_ENTRY_HEADER(xAxis); - SO_KIT_CATALOG_ENTRY_HEADER(xHead); - SO_KIT_CATALOG_ENTRY_HEADER(yAxis); - SO_KIT_CATALOG_ENTRY_HEADER(yHead); - SO_KIT_CATALOG_ENTRY_HEADER(zAxis); - SO_KIT_CATALOG_ENTRY_HEADER(zHead); - -public: - SoAxisCrossKit(); - - // Overrides default method. All the parts are shapeKits, - // so this node will not affect the state. - SbBool affectsState() const override; - void addWriteReference(SoOutput * out, SbBool isfromfield = false) override; - void getBoundingBox(SoGetBoundingBoxAction * action) override; - - static void initClass(); - -private: - // Constructor calls to build and set up parts. - void createAxes(); - ~SoAxisCrossKit() override; -}; - -class GuiExport SoRegPoint : public SoShape { - using inherited = SoShape; - - SO_NODE_HEADER(SoRegPoint); - -public: - static void initClass(); - SoRegPoint(); - - void notify(SoNotList * node) override; - - SoSFVec3f base; - SoSFVec3f normal; - SoSFFloat length; - SoSFColor color; - SoSFString text; - -protected: - ~SoRegPoint() override; - void GLRender(SoGLRenderAction *action) override; - void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) override; - void generatePrimitives(SoAction *action) override; - -private: - SoSeparator* root; -}; - -} // namespace Gui - -#endif // GUI_SOSHAPESCALE_H +/*************************************************************************** + * Copyright (c) 2010 Werner Mayer * + * * + * 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 GUI_SOSHAPESCALE_H +#define GUI_SOSHAPESCALE_H + +#include +#include +#include +#include +#include +#include +#include + + +class SbViewport; +class SoState; +class SbColor; +class SbVec2s; + +namespace Gui { +class GuiExport SoShapeScale : public SoBaseKit { + using inherited = SoBaseKit; + + SO_KIT_HEADER(SoShapeScale); + + SO_KIT_CATALOG_ENTRY_HEADER(topSeparator); + SO_KIT_CATALOG_ENTRY_HEADER(scale); + SO_KIT_CATALOG_ENTRY_HEADER(shape); + +public: + SoShapeScale(); + static void initClass(); + + SoSFFloat active; + SoSFFloat scaleFactor; + +protected: + void GLRender(SoGLRenderAction * action) override; + ~SoShapeScale() override; +}; + +class GuiExport SoAxisCrossKit : public SoBaseKit { + using inherited = SoBaseKit; + + SO_KIT_HEADER(SoAxisCrossKit); + + SO_KIT_CATALOG_ENTRY_HEADER(xAxis); + SO_KIT_CATALOG_ENTRY_HEADER(xHead); + SO_KIT_CATALOG_ENTRY_HEADER(yAxis); + SO_KIT_CATALOG_ENTRY_HEADER(yHead); + SO_KIT_CATALOG_ENTRY_HEADER(zAxis); + SO_KIT_CATALOG_ENTRY_HEADER(zHead); + +public: + SoAxisCrossKit(); + + // Overrides default method. All the parts are shapeKits, + // so this node will not affect the state. + SbBool affectsState() const override; + void addWriteReference(SoOutput * out, SbBool isfromfield = false) override; + void getBoundingBox(SoGetBoundingBoxAction * action) override; + + static void initClass(); + +private: + // Constructor calls to build and set up parts. + void createAxes(); + ~SoAxisCrossKit() override; +}; + +class GuiExport SoRegPoint : public SoShape { + using inherited = SoShape; + + SO_NODE_HEADER(SoRegPoint); + +public: + static void initClass(); + SoRegPoint(); + + void notify(SoNotList * node) override; + + SoSFVec3f base; + SoSFVec3f normal; + SoSFFloat length; + SoSFColor color; + SoSFString text; + +protected: + ~SoRegPoint() override; + void GLRender(SoGLRenderAction *action) override; + void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) override; + void generatePrimitives(SoAction *action) override; + +private: + SoSeparator* root; +}; + +} // namespace Gui + +#endif // GUI_SOSHAPESCALE_H diff --git a/src/Gui/Inventor/SoDrawingGrid.cpp b/src/Gui/Inventor/SoDrawingGrid.cpp index 6bfe086d956d..39e8c7042eba 100644 --- a/src/Gui/Inventor/SoDrawingGrid.cpp +++ b/src/Gui/Inventor/SoDrawingGrid.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include # include # include @@ -31,13 +30,12 @@ # include # include # include -#endif - #ifdef FC_OS_MACOSX #include #else #include #endif +#endif #include "SoDrawingGrid.h" @@ -179,14 +177,14 @@ SoDrawingGrid::GLRenderOffPath(SoGLRenderAction *) void SoDrawingGrid::generatePrimitives(SoAction* action) { - Q_UNUSED(action); + (void)action; } void SoDrawingGrid::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) { - Q_UNUSED(action); - Q_UNUSED(box); - Q_UNUSED(center); + (void)action; + (void)box; + (void)center; //SoState* state = action->getState(); } diff --git a/src/Gui/SoFCBoundingBox.cpp b/src/Gui/Inventor/SoFCBoundingBox.cpp similarity index 96% rename from src/Gui/SoFCBoundingBox.cpp rename to src/Gui/Inventor/SoFCBoundingBox.cpp index 3f4c38cb8313..0b7761fa1b82 100644 --- a/src/Gui/SoFCBoundingBox.cpp +++ b/src/Gui/Inventor/SoFCBoundingBox.cpp @@ -1,272 +1,270 @@ -/*************************************************************************** - * Copyright (c) 2007 Werner Mayer * - * * - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "SoFCBoundingBox.h" - - -using namespace Gui; - -SO_NODE_SOURCE(SoFCBoundingBox) - -// vertices used to create a box -static const int32_t bBoxVerts[8][3] = -{ - {0, 0, 0}, - {1, 0, 0}, - {1, 1, 0}, - {0, 1, 0}, - {0, 0, 1}, - {1, 0, 1}, - {1, 1, 1}, - {0, 1, 1} -}; - -// indexes used to create the edges -static const int32_t bBoxEdges[36] = -{ - 0,1,-1, 1,2,-1, 2,3,-1, 3,0,-1, - 4,5,-1, 5,6,-1, 6,7,-1, 7,4,-1, - 0,4,-1, 1,5,-1, 2,6,-1, 3,7,-1 -}; - -void SoFCBoundingBox::initClass () -{ - SO_NODE_INIT_CLASS(SoFCBoundingBox, SoShape, "Shape"); -} - -SoFCBoundingBox::SoFCBoundingBox () -{ - SO_NODE_CONSTRUCTOR(SoFCBoundingBox); - - SO_NODE_ADD_FIELD(minBounds, (-1.0, -1.0, -1.0)); - SO_NODE_ADD_FIELD(maxBounds, ( 1.0, 1.0, 1.0)); - SO_NODE_ADD_FIELD(coordsOn, (true)); - SO_NODE_ADD_FIELD(dimensionsOn, (true)); - - root = new SoSeparator(); - auto bboxSep = new SoSeparator(); - - bboxCoords = new SoCoordinate3(); - bboxCoords->point.setNum(8); - bboxSep->addChild(bboxCoords); - root->addChild(bboxSep); - - // the lines of the box - bboxLines = new SoIndexedLineSet(); - bboxLines->coordIndex.setNum(36); - bboxLines->coordIndex.setValues(0, 36, bBoxEdges); - bboxSep->addChild(bboxLines); - - - // create the text nodes, including a transform for each vertice offset - textSep = new SoSeparator(); - for (int i = 0; i < 8; i++) { - auto temp = new SoSeparator(); - auto trans = new SoTransform(); - temp->addChild(trans); - auto text = new SoText2(); - text->justification.setValue(SoText2::CENTER); - temp->addChild(text); - textSep->addChild(temp); - } - - // create the text nodes, including a transform for each dimension - dimSep = new SoSeparator(); - for (int i = 0; i < 3; i++) { - auto temp = new SoSeparator(); - auto trans = new SoTransform(); - temp->addChild(trans); - auto text = new SoText2(); - text->justification.setValue(SoText2::CENTER); - temp->addChild(text); - dimSep->addChild(temp); - } - - root->addChild(textSep); - root->addChild(dimSep); - root->ref(); -} - -SoFCBoundingBox::~SoFCBoundingBox () -{ - root->unref(); -} - -void SoFCBoundingBox::GLRender (SoGLRenderAction *action) -{ - SbVec3f corner[2], ctr, *vptr; - SbBool coord, dimension; - - // grab the current state - //SoState *state = action->getState(); - - if (!shouldGLRender(action)) - return; - - // get the latest values from the fields - corner[0] = minBounds.getValue(); - corner[1] = maxBounds.getValue(); - coord = coordsOn.getValue(); - dimension = dimensionsOn.getValue(); - - // set the coordinates for the LineSet to point to - vptr = bboxCoords->point.startEditing(); - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 3; j++) { - vptr[i][j] = corner[bBoxVerts[i][j]][j]; - } - } - - // if coord is true then set the text nodes - if (coord) { - ctr = (corner[1] - corner[0]) / 2.0f; - for (int i = 0; i < 8; i++) { - // create the string for the text - std::stringstream str; - str.precision(2); - str.setf(std::ios::fixed | std::ios::showpoint); - str << "(" << vptr[i][0] << "," << vptr[i][1] << "," << vptr[i][2] << ")"; - - SoSeparator *sep = static_cast(textSep->getChild(i)); - SoTransform *trans = static_cast(sep->getChild(0)); - - trans->translation.setValue(vptr[i].getValue()); - SoText2* t = static_cast(sep->getChild(1)); - t->string.setValue(str.str().c_str()); - } - - textSep->ref(); - if (root->findChild(textSep) < 0) - root->addChild(textSep); - } else { - if (root->findChild(textSep) >= 0) - root->removeChild(textSep); - } - - // if dimension is true then set the text nodes - if (dimension) { - ctr = (corner[1] - corner[0]) / 2.0f; - for (int i = 0; i < 3; i++) { - // create the string for the text - std::stringstream str; - str.precision(2); - str.setf(std::ios::fixed | std::ios::showpoint); - str << (2.0f * ctr[i]); - - SoSeparator *sep = static_cast(dimSep->getChild(i)); - SoTransform *trans = static_cast(sep->getChild(0)); - - SbVec3f point = corner[0]; - point[i] += ctr[i]; - trans->translation.setValue(point.getValue()); - SoText2* t = static_cast(sep->getChild(1)); - t->string.setValue(str.str().c_str()); - } - - dimSep->ref(); - if (root->findChild(dimSep) < 0) - root->addChild(dimSep); - } else { - if (root->findChild(dimSep) >= 0) - root->removeChild(dimSep); - } - - bboxCoords->point.finishEditing(); - - // Avoid shading - SoState * state = action->getState(); - state->push(); - SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); - root->GLRender(action); - state->pop(); -} - -void SoFCBoundingBox::generatePrimitives (SoAction * /*action*/) -{ -} - -void SoFCBoundingBox::computeBBox (SoAction * /*action*/, SbBox3f &box, SbVec3f ¢er) -{ - center = (minBounds.getValue() + maxBounds.getValue()) / 2.0f; - box.setBounds(minBounds.getValue(), maxBounds.getValue()); -} - -void SoFCBoundingBox::finish() -{ - atexit_cleanup(); -} - -// --------------------------------------------------------------- - -SO_NODE_SOURCE(SoSkipBoundingGroup) - -/*! - Constructor. -*/ -SoSkipBoundingGroup::SoSkipBoundingGroup() -{ - SO_NODE_CONSTRUCTOR(SoSkipBoundingGroup); - - SO_NODE_ADD_FIELD(mode, (INCLUDE_BBOX)); - - SO_NODE_DEFINE_ENUM_VALUE(Modes, INCLUDE_BBOX); - SO_NODE_DEFINE_ENUM_VALUE(Modes, EXCLUDE_BBOX); - SO_NODE_SET_SF_ENUM_TYPE (mode, Modes); -} - -/*! - Destructor. -*/ -SoSkipBoundingGroup::~SoSkipBoundingGroup() = default; - -void -SoSkipBoundingGroup::initClass() -{ - SO_NODE_INIT_CLASS(SoSkipBoundingGroup,SoGroup,"Group"); -} - -void SoSkipBoundingGroup::finish() -{ - atexit_cleanup(); -} - -void SoSkipBoundingGroup::getBoundingBox(SoGetBoundingBoxAction *action) -{ - if (mode.getValue() == INCLUDE_BBOX) - inherited::getBoundingBox(action); -} - +/*************************************************************************** + * Copyright (c) 2007 Werner Mayer * + * * + * 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 + +#include +#include +#include +#include +#include +#include +#endif + +#include "SoFCBoundingBox.h" + + +using namespace Gui; + +SO_NODE_SOURCE(SoFCBoundingBox) + +// vertices used to create a box +static const int32_t bBoxVerts[8][3] = +{ + {0, 0, 0}, + {1, 0, 0}, + {1, 1, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 0, 1}, + {1, 1, 1}, + {0, 1, 1} +}; + +// indexes used to create the edges +static const int32_t bBoxEdges[36] = +{ + 0,1,-1, 1,2,-1, 2,3,-1, 3,0,-1, + 4,5,-1, 5,6,-1, 6,7,-1, 7,4,-1, + 0,4,-1, 1,5,-1, 2,6,-1, 3,7,-1 +}; + +void SoFCBoundingBox::initClass () +{ + SO_NODE_INIT_CLASS(SoFCBoundingBox, SoShape, "Shape"); +} + +SoFCBoundingBox::SoFCBoundingBox () +{ + SO_NODE_CONSTRUCTOR(SoFCBoundingBox); + + SO_NODE_ADD_FIELD(minBounds, (-1.0, -1.0, -1.0)); + SO_NODE_ADD_FIELD(maxBounds, ( 1.0, 1.0, 1.0)); + SO_NODE_ADD_FIELD(coordsOn, (true)); + SO_NODE_ADD_FIELD(dimensionsOn, (true)); + + root = new SoSeparator(); + auto bboxSep = new SoSeparator(); + + bboxCoords = new SoCoordinate3(); + bboxCoords->point.setNum(8); + bboxSep->addChild(bboxCoords); + root->addChild(bboxSep); + + // the lines of the box + bboxLines = new SoIndexedLineSet(); + bboxLines->coordIndex.setNum(36); + bboxLines->coordIndex.setValues(0, 36, bBoxEdges); + bboxSep->addChild(bboxLines); + + + // create the text nodes, including a transform for each vertice offset + textSep = new SoSeparator(); + for (int i = 0; i < 8; i++) { + auto temp = new SoSeparator(); + auto trans = new SoTransform(); + temp->addChild(trans); + auto text = new SoText2(); + text->justification.setValue(SoText2::CENTER); + temp->addChild(text); + textSep->addChild(temp); + } + + // create the text nodes, including a transform for each dimension + dimSep = new SoSeparator(); + for (int i = 0; i < 3; i++) { + auto temp = new SoSeparator(); + auto trans = new SoTransform(); + temp->addChild(trans); + auto text = new SoText2(); + text->justification.setValue(SoText2::CENTER); + temp->addChild(text); + dimSep->addChild(temp); + } + + root->addChild(textSep); + root->addChild(dimSep); + root->ref(); +} + +SoFCBoundingBox::~SoFCBoundingBox () +{ + root->unref(); +} + +void SoFCBoundingBox::GLRender (SoGLRenderAction *action) +{ + SbVec3f corner[2], ctr, *vptr; + SbBool coord, dimension; + + // grab the current state + //SoState *state = action->getState(); + + if (!shouldGLRender(action)) + return; + + // get the latest values from the fields + corner[0] = minBounds.getValue(); + corner[1] = maxBounds.getValue(); + coord = coordsOn.getValue(); + dimension = dimensionsOn.getValue(); + + // set the coordinates for the LineSet to point to + vptr = bboxCoords->point.startEditing(); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 3; j++) { + vptr[i][j] = corner[bBoxVerts[i][j]][j]; + } + } + + // if coord is true then set the text nodes + if (coord) { + ctr = (corner[1] - corner[0]) / 2.0f; + for (int i = 0; i < 8; i++) { + // create the string for the text + std::stringstream str; + str.precision(2); + str.setf(std::ios::fixed | std::ios::showpoint); + str << "(" << vptr[i][0] << "," << vptr[i][1] << "," << vptr[i][2] << ")"; + + SoSeparator *sep = static_cast(textSep->getChild(i)); + SoTransform *trans = static_cast(sep->getChild(0)); + + trans->translation.setValue(vptr[i].getValue()); + SoText2* t = static_cast(sep->getChild(1)); + t->string.setValue(str.str().c_str()); + } + + textSep->ref(); + if (root->findChild(textSep) < 0) + root->addChild(textSep); + } else { + if (root->findChild(textSep) >= 0) + root->removeChild(textSep); + } + + // if dimension is true then set the text nodes + if (dimension) { + ctr = (corner[1] - corner[0]) / 2.0f; + for (int i = 0; i < 3; i++) { + // create the string for the text + std::stringstream str; + str.precision(2); + str.setf(std::ios::fixed | std::ios::showpoint); + str << (2.0f * ctr[i]); + + SoSeparator *sep = static_cast(dimSep->getChild(i)); + SoTransform *trans = static_cast(sep->getChild(0)); + + SbVec3f point = corner[0]; + point[i] += ctr[i]; + trans->translation.setValue(point.getValue()); + SoText2* t = static_cast(sep->getChild(1)); + t->string.setValue(str.str().c_str()); + } + + dimSep->ref(); + if (root->findChild(dimSep) < 0) + root->addChild(dimSep); + } else { + if (root->findChild(dimSep) >= 0) + root->removeChild(dimSep); + } + + bboxCoords->point.finishEditing(); + + // Avoid shading + SoState * state = action->getState(); + state->push(); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); + root->GLRender(action); + state->pop(); +} + +void SoFCBoundingBox::generatePrimitives (SoAction * /*action*/) +{ +} + +void SoFCBoundingBox::computeBBox (SoAction * /*action*/, SbBox3f &box, SbVec3f ¢er) +{ + center = (minBounds.getValue() + maxBounds.getValue()) / 2.0f; + box.setBounds(minBounds.getValue(), maxBounds.getValue()); +} + +void SoFCBoundingBox::finish() +{ + atexit_cleanup(); +} + +// --------------------------------------------------------------- + +SO_NODE_SOURCE(SoSkipBoundingGroup) + +/*! + Constructor. +*/ +SoSkipBoundingGroup::SoSkipBoundingGroup() +{ + SO_NODE_CONSTRUCTOR(SoSkipBoundingGroup); + + SO_NODE_ADD_FIELD(mode, (INCLUDE_BBOX)); + + SO_NODE_DEFINE_ENUM_VALUE(Modes, INCLUDE_BBOX); + SO_NODE_DEFINE_ENUM_VALUE(Modes, EXCLUDE_BBOX); + SO_NODE_SET_SF_ENUM_TYPE (mode, Modes); +} + +/*! + Destructor. +*/ +SoSkipBoundingGroup::~SoSkipBoundingGroup() = default; + +void +SoSkipBoundingGroup::initClass() +{ + SO_NODE_INIT_CLASS(SoSkipBoundingGroup,SoGroup,"Group"); +} + +void SoSkipBoundingGroup::finish() +{ + atexit_cleanup(); +} + +void SoSkipBoundingGroup::getBoundingBox(SoGetBoundingBoxAction *action) +{ + if (mode.getValue() == INCLUDE_BBOX) + inherited::getBoundingBox(action); +} + diff --git a/src/Gui/SoFCBoundingBox.h b/src/Gui/Inventor/SoFCBoundingBox.h similarity index 97% rename from src/Gui/SoFCBoundingBox.h rename to src/Gui/Inventor/SoFCBoundingBox.h index b394d4942ada..d33bf51cde66 100644 --- a/src/Gui/SoFCBoundingBox.h +++ b/src/Gui/Inventor/SoFCBoundingBox.h @@ -1,106 +1,106 @@ -/*************************************************************************** - * Copyright (c) 2007 Werner Mayer * - * * - * 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 COIN_SOFCBOUNDINGBOX_H -#define COIN_SOFCBOUNDINGBOX_H - -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace Gui { - -/** - * A subclass of SoShape used to create an axis aligned wire frame box based - * on the minBounds and maxBounds fields. The class also has a field which - * can be toggled on or off for displaying text coordinate labels at the - * vertices of the box. - * @note Original source are taken from http://www.wheatchex.com/projects/openinventor/bbox/BoundingBox.h and - * http://www.wheatchex.com/projects/openinventor/bbox/BoundingBox.cpp - * @date November 12th, 2001 - * @author Josh Grant - */ -class GuiExport SoFCBoundingBox : public SoShape { - using inherited = SoShape; - - SO_NODE_HEADER(Gui::SoFCBoundingBox); - -public: - static void initClass(); - static void finish(); - -public: - SoFCBoundingBox(); - SoSFVec3f minBounds; /**< minimum box coordinates */ - SoSFVec3f maxBounds; /**< maximum box coordinates */ - SoSFBool coordsOn; /**< If true, the coordinates are displayed at each vertex */ - SoSFBool dimensionsOn; /**< If true, the dimensions are displayed in x,y and z direction */ - - -protected: - ~SoFCBoundingBox() override; - void GLRender(SoGLRenderAction *action) override; - void generatePrimitives (SoAction *action) override; - void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) override; - -private: - SoSeparator *root, *textSep, *dimSep; - SoCoordinate3 *bboxCoords; - SoIndexedLineSet *bboxLines; -}; - -/** - * This is a special group node which must be defined to ignore bounding box actions. - * @author Werner Mayer - */ -class GuiExport SoSkipBoundingGroup : public SoGroup { - using inherited = SoGroup; - - SO_NODE_HEADER(Gui::SoSkipBoundingGroup); - -public: - static void initClass(); - static void finish(); - SoSkipBoundingGroup(); - - enum Modes { - INCLUDE_BBOX, EXCLUDE_BBOX - }; - - SoSFEnum mode; - - void getBoundingBox(SoGetBoundingBoxAction *action) override; - -protected: - ~SoSkipBoundingGroup() override; -}; - -} // namespace Gui - - -#endif //COIN_SOFCBOUNDINGBOX_H +/*************************************************************************** + * Copyright (c) 2007 Werner Mayer * + * * + * 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 COIN_SOFCBOUNDINGBOX_H +#define COIN_SOFCBOUNDINGBOX_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Gui { + +/** + * A subclass of SoShape used to create an axis aligned wire frame box based + * on the minBounds and maxBounds fields. The class also has a field which + * can be toggled on or off for displaying text coordinate labels at the + * vertices of the box. + * @note Original source are taken from http://www.wheatchex.com/projects/openinventor/bbox/BoundingBox.h and + * http://www.wheatchex.com/projects/openinventor/bbox/BoundingBox.cpp + * @date November 12th, 2001 + * @author Josh Grant + */ +class GuiExport SoFCBoundingBox : public SoShape { + using inherited = SoShape; + + SO_NODE_HEADER(Gui::SoFCBoundingBox); + +public: + static void initClass(); + static void finish(); + +public: + SoFCBoundingBox(); + SoSFVec3f minBounds; /**< minimum box coordinates */ + SoSFVec3f maxBounds; /**< maximum box coordinates */ + SoSFBool coordsOn; /**< If true, the coordinates are displayed at each vertex */ + SoSFBool dimensionsOn; /**< If true, the dimensions are displayed in x,y and z direction */ + + +protected: + ~SoFCBoundingBox() override; + void GLRender(SoGLRenderAction *action) override; + void generatePrimitives (SoAction *action) override; + void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) override; + +private: + SoSeparator *root, *textSep, *dimSep; + SoCoordinate3 *bboxCoords; + SoIndexedLineSet *bboxLines; +}; + +/** + * This is a special group node which must be defined to ignore bounding box actions. + * @author Werner Mayer + */ +class GuiExport SoSkipBoundingGroup : public SoGroup { + using inherited = SoGroup; + + SO_NODE_HEADER(Gui::SoSkipBoundingGroup); + +public: + static void initClass(); + static void finish(); + SoSkipBoundingGroup(); + + enum Modes { + INCLUDE_BBOX, EXCLUDE_BBOX + }; + + SoSFEnum mode; + + void getBoundingBox(SoGetBoundingBoxAction *action) override; + +protected: + ~SoSkipBoundingGroup() override; +}; + +} // namespace Gui + + +#endif //COIN_SOFCBOUNDINGBOX_H diff --git a/src/Gui/SoMouseWheelEvent.cpp b/src/Gui/Inventor/SoMouseWheelEvent.cpp similarity index 100% rename from src/Gui/SoMouseWheelEvent.cpp rename to src/Gui/Inventor/SoMouseWheelEvent.cpp diff --git a/src/Gui/SoMouseWheelEvent.h b/src/Gui/Inventor/SoMouseWheelEvent.h similarity index 100% rename from src/Gui/SoMouseWheelEvent.h rename to src/Gui/Inventor/SoMouseWheelEvent.h diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 6eae6323fc78..9acf9f6255ce 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -27,8 +27,8 @@ # include #endif +#include "Inventor/SoMouseWheelEvent.h" #include "NavigationStyle.h" -#include "SoMouseWheelEvent.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/ManualAlignment.cpp b/src/Gui/ManualAlignment.cpp index 0884768a44ff..270c5f14704d 100644 --- a/src/Gui/ManualAlignment.cpp +++ b/src/Gui/ManualAlignment.cpp @@ -47,18 +47,17 @@ #include #include #include +#include #include +#include #include #include #include +#include #include #include #include - #include "ManualAlignment.h" -#include "BitmapFactory.h" -#include "SoAxisCrossKit.h" -#include "Tools.h" using namespace Gui; diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index bf9ca75d32c3..24ff54ec4a2c 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -43,11 +43,11 @@ #include "NavigationStyle.h" #include "Application.h" +#include "Inventor/SoMouseWheelEvent.h" #include "MenuManager.h" #include "MouseSelection.h" #include "NavigationAnimator.h" #include "NavigationAnimation.h" -#include "SoMouseWheelEvent.h" #include "View3DInventorViewer.h" using namespace Gui; diff --git a/src/Gui/Quarter/Mouse.cpp b/src/Gui/Quarter/Mouse.cpp index 66bd3b83e69c..1d91f77d959b 100644 --- a/src/Gui/Quarter/Mouse.cpp +++ b/src/Gui/Quarter/Mouse.cpp @@ -45,8 +45,8 @@ #include #include -#include #include +#include #include #include diff --git a/src/Gui/SoFCCSysDragger.cpp b/src/Gui/SoFCCSysDragger.cpp index 3ec2c397f0b1..84d9840f6aac 100644 --- a/src/Gui/SoFCCSysDragger.cpp +++ b/src/Gui/SoFCCSysDragger.cpp @@ -51,7 +51,7 @@ #include #include "SoFCCSysDragger.h" -#include "So3DAnnotation.h" +#include "Inventor/So3DAnnotation.h" #include "MainWindow.h" #include "SoFCDB.h" diff --git a/src/Gui/SoFCCSysDragger.h b/src/Gui/SoFCCSysDragger.h index 25fb355be564..20364506b1ad 100644 --- a/src/Gui/SoFCCSysDragger.h +++ b/src/Gui/SoFCCSysDragger.h @@ -35,8 +35,6 @@ #include #include -#include "So3DAnnotation.h" - class SoCamera; namespace Gui diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index ec58e5ffd4ca..66f3ec633b62 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -53,10 +53,7 @@ #include "GestureNavigationStyle.h" #include "NavigationStyle.h" #include "SelectionObject.h" -#include "So3DAnnotation.h" -#include "SoAxisCrossKit.h" #include "SoFCBackgroundGradient.h" -#include "SoFCBoundingBox.h" #include "SoFCColorBar.h" #include "SoFCColorGradient.h" #include "SoFCColorLegend.h" @@ -67,13 +64,16 @@ #include "SoFCUnifiedSelection.h" #include "SoFCVectorizeSVGAction.h" #include "SoFCVectorizeU3DAction.h" -#include "SoMouseWheelEvent.h" #include "SoTextLabel.h" #include "SoDatumLabel.h" #include "Inventor/MarkerBitmaps.h" #include "Inventor/SmSwitchboard.h" +#include "Inventor/So3DAnnotation.h" #include "Inventor/SoAutoZoomTranslation.h" +#include "Inventor/SoAxisCrossKit.h" #include "Inventor/SoDrawingGrid.h" +#include "Inventor/SoFCBoundingBox.h" +#include "Inventor/SoMouseWheelEvent.h" #include "propertyeditor/PropertyItem.h" #include "ArcEngine.h" diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index d168c25f552d..94af3716cb5a 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -94,14 +94,14 @@ #include "Application.h" #include "Document.h" #include "GLPainter.h" +#include "Inventor/SoAxisCrossKit.h" +#include "Inventor/SoFCBoundingBox.h" #include "MainWindow.h" #include "Multisample.h" #include "NaviCube.h" #include "NavigationStyle.h" #include "Selection.h" -#include "SoAxisCrossKit.h" #include "SoFCBackgroundGradient.h" -#include "SoFCBoundingBox.h" #include "SoFCDB.h" #include "SoFCInteractiveElement.h" #include "SoFCOffscreenRenderer.h" diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index f6113588f177..3d9e6e6a6002 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -55,6 +55,7 @@ #include "Camera.h" #include "Document.h" +#include "Inventor/SoMouseWheelEvent.h" #include "NavigationStyle.h" #include "PythonWrapper.h" #include "SoFCDB.h" @@ -62,7 +63,6 @@ #include "SoFCSelectionAction.h" #include "SoFCVectorizeSVGAction.h" #include "SoFCVectorizeU3DAction.h" -#include "SoMouseWheelEvent.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" #include "ViewProviderDocumentObject.h" diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index 143a85bff6e7..fdd63583bede 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -41,7 +41,7 @@ #include #include -#include "SoMouseWheelEvent.h" +#include "Inventor/SoMouseWheelEvent.h" #include "ViewProvider.h" #include "ActionFunction.h" #include "Application.h" diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index d7c1754c1516..5e45d86d627c 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -32,18 +32,17 @@ #include #include #include +#include #include #include #endif -#include - #include #include #include "Application.h" #include "Document.h" -#include "SoFCBoundingBox.h" +#include "Inventor/SoFCBoundingBox.h" #include "SoFCSelection.h" #include "View3DInventorViewer.h" #include "ViewProviderGeometryObject.h" diff --git a/src/Mod/CAM/Gui/ViewProviderPath.cpp b/src/Mod/CAM/Gui/ViewProviderPath.cpp index 0be6dd03affd..e96b71f02fad 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPath.cpp @@ -44,8 +44,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.cpp b/src/Mod/Part/Gui/ViewProvider2DObject.cpp index dfde26fa8993..b9a2d96dfc41 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.cpp +++ b/src/Mod/Part/Gui/ViewProvider2DObject.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "ViewProvider2DObject.h" diff --git a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp index 561503ced70f..9b6130c7b621 100644 --- a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp +++ b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp @@ -50,7 +50,7 @@ #include #include -#include +#include #include "ViewProviderGridExtension.h" diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp index abdacaae7640..e29026c9dd9c 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include From 229d2902bdea51406d6e6e3d23423a8594238b19 Mon Sep 17 00:00:00 2001 From: liukaiwen Date: Mon, 22 Jul 2024 02:48:53 +0800 Subject: [PATCH 004/161] add SoFCBackgroundGradient to inventor folder --- src/Gui/CMakeLists.txt | 16 ++++++++-------- .../{ => Inventor}/SoFCBackgroundGradient.cpp | 0 src/Gui/{ => Inventor}/SoFCBackgroundGradient.h | 0 src/Gui/SoFCDB.cpp | 2 +- src/Gui/View3DInventorViewer.cpp | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) rename src/Gui/{ => Inventor}/SoFCBackgroundGradient.cpp (100%) rename src/Gui/{ => Inventor}/SoFCBackgroundGradient.h (100%) diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index e4b7b7483a77..9dd92cda9adc 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1005,15 +1005,15 @@ SOURCE_GROUP("View3D\\Viewprovider" FILES ${Viewprovider_SRCS}) # The Inventor sources SET(Inventor_CPP_SRCS - Inventor/SoDrawingGrid.cpp - Inventor/SoAutoZoomTranslation.cpp Inventor/MarkerBitmaps.cpp Inventor/SmSwitchboard.cpp - Inventor/SoFCBoundingBox.cpp Inventor/So3DAnnotation.cpp + Inventor/SoAutoZoomTranslation.cpp Inventor/SoAxisCrossKit.cpp + Inventor/SoDrawingGrid.cpp + Inventor/SoFCBackgroundGradient.cpp + Inventor/SoFCBoundingBox.cpp Inventor/SoMouseWheelEvent.cpp - SoFCBackgroundGradient.cpp SoFCColorBar.cpp SoFCColorBarNotifier.cpp SoFCColorGradient.cpp @@ -1036,14 +1036,14 @@ SET(Inventor_CPP_SRCS ) SET(Inventor_SRCS ${Inventor_CPP_SRCS} - Inventor/SoDrawingGrid.h - Inventor/SoAutoZoomTranslation.h Inventor/MarkerBitmaps.h Inventor/SmSwitchboard.h - Inventor/SoFCBoundingBox.h + Inventor/SoAutoZoomTranslation.h Inventor/SoAxisCrossKit.h + Inventor/SoDrawingGrid.h + Inventor/SoFCBackgroundGradient.h + Inventor/SoFCBoundingBox.h Inventor/SoMouseWheelEvent.h - SoFCBackgroundGradient.h SoFCColorBar.h SoFCColorBarNotifier.h SoFCColorGradient.h diff --git a/src/Gui/SoFCBackgroundGradient.cpp b/src/Gui/Inventor/SoFCBackgroundGradient.cpp similarity index 100% rename from src/Gui/SoFCBackgroundGradient.cpp rename to src/Gui/Inventor/SoFCBackgroundGradient.cpp diff --git a/src/Gui/SoFCBackgroundGradient.h b/src/Gui/Inventor/SoFCBackgroundGradient.h similarity index 100% rename from src/Gui/SoFCBackgroundGradient.h rename to src/Gui/Inventor/SoFCBackgroundGradient.h diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 66f3ec633b62..26b17df1729e 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -53,7 +53,6 @@ #include "GestureNavigationStyle.h" #include "NavigationStyle.h" #include "SelectionObject.h" -#include "SoFCBackgroundGradient.h" #include "SoFCColorBar.h" #include "SoFCColorGradient.h" #include "SoFCColorLegend.h" @@ -72,6 +71,7 @@ #include "Inventor/SoAutoZoomTranslation.h" #include "Inventor/SoAxisCrossKit.h" #include "Inventor/SoDrawingGrid.h" +#include "Inventor/SoFCBackgroundGradient.h" #include "Inventor/SoFCBoundingBox.h" #include "Inventor/SoMouseWheelEvent.h" #include "propertyeditor/PropertyItem.h" diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 94af3716cb5a..eea95ef090d4 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -95,13 +95,13 @@ #include "Document.h" #include "GLPainter.h" #include "Inventor/SoAxisCrossKit.h" +#include "Inventor/SoFCBackgroundGradient.h" #include "Inventor/SoFCBoundingBox.h" #include "MainWindow.h" #include "Multisample.h" #include "NaviCube.h" #include "NavigationStyle.h" #include "Selection.h" -#include "SoFCBackgroundGradient.h" #include "SoFCDB.h" #include "SoFCInteractiveElement.h" #include "SoFCOffscreenRenderer.h" From 795730382af1278a80238a06fd105b66b380f843 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Mon, 7 Oct 2024 07:22:10 -0300 Subject: [PATCH 005/161] Fem: Netgen local refinement --- src/Mod/Fem/femcommands/commands.py | 2 +- src/Mod/Fem/femmesh/netgentools.py | 34 ++++++++++++++++++- src/Mod/Fem/femobjects/mesh_netgen.py | 10 ++++++ .../Fem/femviewprovider/view_mesh_netgen.py | 4 +++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 19fefd76e788..b2f6f7ea453a 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -863,7 +863,7 @@ def __init__(self): super().__init__() self.menutext = Qt.QT_TRANSLATE_NOOP("FEM_MeshRegion", "FEM mesh refinement") self.tooltip = Qt.QT_TRANSLATE_NOOP("FEM_MeshRegion", "Creates a FEM mesh refinement") - self.is_active = "with_gmsh_femmesh" + self.is_active = "with_femmesh" self.do_activated = "add_obj_on_gui_selobj_set_edit" diff --git a/src/Mod/Fem/femmesh/netgentools.py b/src/Mod/Fem/femmesh/netgentools.py index 701937ed5425..0d8b890ba7e1 100644 --- a/src/Mod/Fem/femmesh/netgentools.py +++ b/src/Mod/Fem/femmesh/netgentools.py @@ -112,6 +112,7 @@ def prepare(self): "params": self.get_meshing_parameters(), "second_order": self.obj.SecondOrder, "result_file": self.result_file, + "mesh_region": self.get_mesh_region(), } def compute(self): @@ -121,12 +122,27 @@ def compute(self): return self.process @staticmethod - def run_netgen(brep_file, threads, heal, params, second_order, result_file): + def run_netgen(brep_file, threads, heal, params, second_order, result_file, mesh_region): + import pyngcore as ngcore + from netgen import meshing geom = occ.OCCGeometry(brep_file) ngcore.SetNumThreads(threads) + shape = geom.shape + for items, l in mesh_region: + for t, n in items: + if t == "Vertex": + shape.vertices.vertices[n - 1].maxh = l + elif t == "Edge": + shape.edges.edges[n - 1].maxh = l + elif t == "Face": + shape.faces.faces[n - 1].maxh = l + elif t == "Solid": + shape.solids.solids[n - 1].maxh = l + with ngcore.TaskManager(): + geom = occ.OCCGeometry(shape) if heal: geom.Heal() mesh = geom.GenerateMesh(mp=meshing.MeshingParameters(**params)) @@ -306,6 +322,22 @@ def get_meshing_parameters(self): return params + def get_mesh_region(self): + import Part + + d = [] + for reg in self.obj.MeshRegionList: + for s, sub_list in reg.References: + if s.isDerivedFrom("App::GeoFeature") and isinstance( + s.getPropertyOfGeometry(), Part.Shape + ): + geom = s.getPropertyOfGeometry() + sub_sh = [s.getSubObject(_) for _ in sub_list] + res = geom.findSubShape(sub_sh) + l = reg.CharacteristicLength.getValueAs("mm").Value + d.append((res, l)) + return d + @staticmethod def version(): result = "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}" diff --git a/src/Mod/Fem/femobjects/mesh_netgen.py b/src/Mod/Fem/femobjects/mesh_netgen.py index 3b023b384f30..d8f412000841 100644 --- a/src/Mod/Fem/femobjects/mesh_netgen.py +++ b/src/Mod/Fem/femobjects/mesh_netgen.py @@ -51,6 +51,16 @@ def __init__(self, obj): def _get_properties(self): prop = [] + prop.append( + _PropHelper( + type="App::PropertyLinkList", + name="MeshRegionList", + group="Base", + doc="Refinements of the mesh", + value=[], + ) + ) + # mesh parameters prop.append( _PropHelper( type="App::PropertyString", diff --git a/src/Mod/Fem/femviewprovider/view_mesh_netgen.py b/src/Mod/Fem/femviewprovider/view_mesh_netgen.py index 34a60d36981d..b2835fe253ff 100644 --- a/src/Mod/Fem/femviewprovider/view_mesh_netgen.py +++ b/src/Mod/Fem/femviewprovider/view_mesh_netgen.py @@ -151,6 +151,10 @@ def doubleClicked(self, vobj): FreeCAD.Console.PrintError(message + "\n") return True + def claimChildren(self): + reg_childs = self.Object.MeshRegionList + return reg_childs + def dumps(self): return None From 6328c7ece1a75ab3453f410adf574bfe64cf7c57 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 10 Oct 2024 09:51:39 -0300 Subject: [PATCH 006/161] Fem: Add second order linear option to Netgen mesh --- src/Mod/Fem/femmesh/netgentools.py | 31 +++++++++++++++++---------- src/Mod/Fem/femobjects/mesh_netgen.py | 9 ++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/Mod/Fem/femmesh/netgentools.py b/src/Mod/Fem/femmesh/netgentools.py index 0d8b890ba7e1..5c65ba9bcae3 100644 --- a/src/Mod/Fem/femmesh/netgentools.py +++ b/src/Mod/Fem/femmesh/netgentools.py @@ -111,6 +111,7 @@ def prepare(self): "heal": self.obj.HealShape, "params": self.get_meshing_parameters(), "second_order": self.obj.SecondOrder, + "second_order_linear": self.obj.SecondOrderLinear, "result_file": self.result_file, "mesh_region": self.get_mesh_region(), } @@ -122,10 +123,16 @@ def compute(self): return self.process @staticmethod - def run_netgen(brep_file, threads, heal, params, second_order, result_file, mesh_region): - import pyngcore as ngcore - from netgen import meshing - + def run_netgen( + brep_file, + threads, + heal, + params, + second_order, + second_order_linear, + result_file, + mesh_region, + ): geom = occ.OCCGeometry(brep_file) ngcore.SetNumThreads(threads) @@ -148,6 +155,8 @@ def run_netgen(brep_file, threads, heal, params, second_order, result_file, mesh mesh = geom.GenerateMesh(mp=meshing.MeshingParameters(**params)) if second_order: + if second_order_linear: + mesh.SetGeometry(None) mesh.SecondOrder() coords = mesh.Coordinates() @@ -323,20 +332,20 @@ def get_meshing_parameters(self): return params def get_mesh_region(self): - import Part + from Part import Shape as PartShape - d = [] + result = [] for reg in self.obj.MeshRegionList: for s, sub_list in reg.References: if s.isDerivedFrom("App::GeoFeature") and isinstance( - s.getPropertyOfGeometry(), Part.Shape + s.getPropertyOfGeometry(), PartShape ): geom = s.getPropertyOfGeometry() - sub_sh = [s.getSubObject(_) for _ in sub_list] - res = geom.findSubShape(sub_sh) + sub_obj = [s.getSubObject(_) for _ in sub_list] + sub_sh = geom.findSubShape(sub_obj) l = reg.CharacteristicLength.getValueAs("mm").Value - d.append((res, l)) - return d + result.append((sub_sh, l)) + return result @staticmethod def version(): diff --git a/src/Mod/Fem/femobjects/mesh_netgen.py b/src/Mod/Fem/femobjects/mesh_netgen.py index d8f412000841..539d567e2a4e 100644 --- a/src/Mod/Fem/femobjects/mesh_netgen.py +++ b/src/Mod/Fem/femobjects/mesh_netgen.py @@ -413,6 +413,15 @@ def _get_properties(self): value=True, ) ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="SecondOrderLinear", + group="Mesh Parameters", + doc="Second order nodes are created by linear interpolation", + value=False, + ) + ) prop.append( _PropHelper( type="App::PropertyInteger", From c14ef04b70b6bc5cbfc2a2e9e62b1c3c07057d6c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Nov 2024 18:11:57 +0100 Subject: [PATCH 007/161] Core: Avoid cyclic dependencies when dragging an object into a group --- src/Gui/ViewProviderGroupExtension.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Gui/ViewProviderGroupExtension.cpp b/src/Gui/ViewProviderGroupExtension.cpp index 310997929ec2..594fa95a19f9 100644 --- a/src/Gui/ViewProviderGroupExtension.cpp +++ b/src/Gui/ViewProviderGroupExtension.cpp @@ -72,22 +72,27 @@ bool ViewProviderGroupExtension::extensionCanDropObjects() const { return true; } -bool ViewProviderGroupExtension::extensionCanDropObject(App::DocumentObject* obj) const { - +bool ViewProviderGroupExtension::extensionCanDropObject(App::DocumentObject* obj) const +{ #ifdef FC_DEBUG Base::Console().Log("Check ViewProviderGroupExtension"); #endif - auto* group = getExtendedViewProvider()->getObject()->getExtensionByType(); + auto extobj = getExtendedViewProvider()->getObject(); + auto group = extobj->getExtensionByType(); //we cannot drop thing of this group into it again if it does not allow reorder - if (group->hasObject(obj) && !getExtendedViewProvider()->acceptReorderingObjects()) + if (group->hasObject(obj) && !getExtendedViewProvider()->acceptReorderingObjects()) { return false; + } - if (group->allowObject(obj)) - return true; + // Check for possible cyclic dependencies if we allowed to drop the object + const auto& list = obj->getOutList(); + if (std::find(list.begin(), list.end(), extobj) != list.end()) { + return false; + } - return false; + return group->allowObject(obj); } void ViewProviderGroupExtension::extensionDropObject(App::DocumentObject* obj) { From 76a3ec410fd31ddfea63d32f4653cbff6cff83c9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 10 Nov 2024 17:14:18 +0100 Subject: [PATCH 008/161] Core: Print warning if dragging is not allowed --- src/Gui/ViewProviderGroupExtension.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Gui/ViewProviderGroupExtension.cpp b/src/Gui/ViewProviderGroupExtension.cpp index 594fa95a19f9..254a68dbae7f 100644 --- a/src/Gui/ViewProviderGroupExtension.cpp +++ b/src/Gui/ViewProviderGroupExtension.cpp @@ -75,7 +75,7 @@ bool ViewProviderGroupExtension::extensionCanDropObjects() const { bool ViewProviderGroupExtension::extensionCanDropObject(App::DocumentObject* obj) const { #ifdef FC_DEBUG - Base::Console().Log("Check ViewProviderGroupExtension"); + Base::Console().Log("Check ViewProviderGroupExtension\n"); #endif auto extobj = getExtendedViewProvider()->getObject(); @@ -89,6 +89,7 @@ bool ViewProviderGroupExtension::extensionCanDropObject(App::DocumentObject* obj // Check for possible cyclic dependencies if we allowed to drop the object const auto& list = obj->getOutList(); if (std::find(list.begin(), list.end(), extobj) != list.end()) { + Base::Console().Warning("Do not add cyclic dependency to %s\n", extobj->Label.getValue()); return false; } From f638c38dfdfdb204314c773659ce06dfedeec79e Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sat, 16 Nov 2024 09:57:45 -0300 Subject: [PATCH 009/161] Fem: Set mesher task panel log text to read-only --- src/Mod/Fem/Gui/Resources/ui/MeshGmsh.ui | 3 +++ src/Mod/Fem/Gui/Resources/ui/MeshNetgen.ui | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Mod/Fem/Gui/Resources/ui/MeshGmsh.ui b/src/Mod/Fem/Gui/Resources/ui/MeshGmsh.ui index 4878d8dfdedc..f8b0014e35ae 100644 --- a/src/Mod/Fem/Gui/Resources/ui/MeshGmsh.ui +++ b/src/Mod/Fem/Gui/Resources/ui/MeshGmsh.ui @@ -156,6 +156,9 @@ QTextEdit::NoWrap + + true + diff --git a/src/Mod/Fem/Gui/Resources/ui/MeshNetgen.ui b/src/Mod/Fem/Gui/Resources/ui/MeshNetgen.ui index 8b1644bbc492..24907dd71168 100644 --- a/src/Mod/Fem/Gui/Resources/ui/MeshNetgen.ui +++ b/src/Mod/Fem/Gui/Resources/ui/MeshNetgen.ui @@ -204,6 +204,9 @@ QTextEdit::NoWrap + + true + From 7183de92a44e1438b5b25234ec0eb7156dfeec8f Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Sat, 16 Nov 2024 16:43:46 +0000 Subject: [PATCH 010/161] Draft: Make startup and tests independent of BIM (#17390) --- src/Mod/Draft/drafttests/test_svg.py | 9 ++++++++- src/Mod/Draft/draftutils/params.py | 5 ++++- src/Mod/Draft/draftviewproviders/view_wpproxy.py | 4 +++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/drafttests/test_svg.py b/src/Mod/Draft/drafttests/test_svg.py index 481a96ab32d7..5ff9709b6780 100644 --- a/src/Mod/Draft/drafttests/test_svg.py +++ b/src/Mod/Draft/drafttests/test_svg.py @@ -37,6 +37,13 @@ from draftutils.messages import _msg +try: + import Arch +except ModuleNotFoundError: + have_arch = False +else: + have_arch = True + class DraftSVG(unittest.TestCase): """Test reading and writing of SVGs with Draft.""" @@ -87,10 +94,10 @@ def test_export_svg(self): obj = Draft.export_svg(out_file) self.assertTrue(obj, "'{}' failed".format(operation)) + @unittest.skipIf(not have_arch, "BIM module is not installed") def test_get_svg_from_arch_space_with_zero_vector(self): """Try to get a svg string from an Arch Space with a zero-vector as direction.""" import Part - import Arch import Draft sb = Part.makeBox(1,1,1) diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index 8ba533fcac67..640b74293006 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -28,7 +28,10 @@ import FreeCAD as App import Draft_rc -import Arch_rc +try: + import Arch_rc +except ModuleNotFoundError: + pass from draftutils import init_draft_statusbar from draftutils.translate import translate diff --git a/src/Mod/Draft/draftviewproviders/view_wpproxy.py b/src/Mod/Draft/draftviewproviders/view_wpproxy.py index 734f28dbda6b..26d8fc290a60 100644 --- a/src/Mod/Draft/draftviewproviders/view_wpproxy.py +++ b/src/Mod/Draft/draftviewproviders/view_wpproxy.py @@ -71,7 +71,9 @@ def __init__(self,vobj): vobj.Transparency = 70 vobj.LineWidth = 1 - vobj.LineColor = params.get_param_arch("ColorHelpers") & 0xFFFFFF00 + ch = params.get_param_arch("ColorHelpers") + if ch: + vobj.LineColor = ch & 0xFFFFFF00 vobj.Proxy = self vobj.RestoreView = True From ee2f384b2fdfb5a3201b2d619fde8f45950da9f8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 16 Nov 2024 17:48:28 +0100 Subject: [PATCH 011/161] Draft: Independence from BIM (#17444) * Draft: Independence from BIM - follow-up of #17390 * Draft: More info in DXF importer if BIM not present --- src/Mod/Draft/draftmake/make_clone.py | 53 +++++++++++++---------- src/Mod/Draft/draftobjects/shape2dview.py | 6 ++- src/Mod/Draft/importDXF.py | 26 +++++++---- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_clone.py b/src/Mod/Draft/draftmake/make_clone.py index 0af48100dbfc..8fe82ee1df95 100644 --- a/src/Mod/Draft/draftmake/make_clone.py +++ b/src/Mod/Draft/draftmake/make_clone.py @@ -72,32 +72,37 @@ def make_clone(obj, delta=None, forcedraft=False): cl.Label = prefix + obj[0].Label + " (2D)" elif (len(obj) == 1) and (hasattr(obj[0],"CloneOf") or (utils.get_type(obj[0]) == "BuildingPart")) and (not forcedraft): # arch objects can be clones - import Arch - if utils.get_type(obj[0]) == "BuildingPart": - cl = Arch.makeComponent() + try: + import Arch + except: + # BIM not present + pass else: - try: # new-style make function - cl = getattr(Arch, "make_" + obj[0].Proxy.Type.lower())() - except Exception: - try: # old-style make function - cl = getattr(Arch, "make" + obj[0].Proxy.Type)() + if utils.get_type(obj[0]) == "BuildingPart": + cl = Arch.makeComponent() + else: + try: # new-style make function + cl = getattr(Arch, "make_" + obj[0].Proxy.Type.lower())() except Exception: - pass # not a standard Arch object... Fall back to Draft mode - if cl: - base = utils.get_clone_base(obj[0]) - cl.Label = prefix + base.Label - cl.CloneOf = base - if utils.get_type(obj[0]) != "BuildingPart": - cl.Placement = obj[0].Placement - for prop in ("Description", "IfcType", "Material", "Subvolume", "Tag"): - try: - setattr(cl, prop, getattr(base, prop)) - except Exception: - pass - if App.GuiUp: - gui_utils.format_object(cl, base) - gui_utils.select(cl) - return cl + try: # old-style make function + cl = getattr(Arch, "make" + obj[0].Proxy.Type)() + except Exception: + pass # not a standard Arch object... Fall back to Draft mode + if cl: + base = utils.get_clone_base(obj[0]) + cl.Label = prefix + base.Label + cl.CloneOf = base + if utils.get_type(obj[0]) != "BuildingPart": + cl.Placement = obj[0].Placement + for prop in ("Description", "IfcType", "Material", "Subvolume", "Tag"): + try: + setattr(cl, prop, getattr(base, prop)) + except Exception: + pass + if App.GuiUp: + gui_utils.format_object(cl, base) + gui_utils.select(cl) + return cl # fall back to Draft clone mode if not cl: diff --git a/src/Mod/Draft/draftobjects/shape2dview.py b/src/Mod/Draft/draftobjects/shape2dview.py index 1a9e49ec579e..8cfbf10a16b7 100644 --- a/src/Mod/Draft/draftobjects/shape2dview.py +++ b/src/Mod/Draft/draftobjects/shape2dview.py @@ -230,7 +230,11 @@ def execute(self, obj): onlysolids = obj.Base.OnlySolids if hasattr(obj,"OnlySolids"): # override base object onlysolids = obj.OnlySolids - import Arch + try: + import Arch + except: + print("Shape2DView: BIM not present, unable to recompute") + return objs = groups.get_group_contents(objs, walls=True) if getattr(obj,"VisibleOnly",True): objs = gui_utils.remove_hidden(objs) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index d908465c54dc..324212d2b007 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -104,6 +104,22 @@ def errorDXFLib(gui): ----- Use local variables, not global variables. """ + + def show_addon_message(gui): + if gui: + message = translate("Draft", """Download of dxf libraries failed. +Please install the dxf Library addon manually +from menu Tools -> Addon Manager""") + QtWidgets.QMessageBox.information(None, "", message) + else: + FCC.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n") + FCC.PrintWarning("Please install the dxf Library addon from Tools -> Addon Manager\n") + try: + import ArchCommands + except: + # BIM not present + show_addon_message(gui) + return dxfAllowDownload = params.get_param("dxfAllowDownload") if dxfAllowDownload: files = ['dxfColorMap.py', 'dxfImportObjects.py', @@ -111,7 +127,6 @@ def errorDXFLib(gui): baseurl = 'https://raw.githubusercontent.com/yorikvanhavre/' baseurl += 'Draft-dxf-importer/master/' - import ArchCommands from FreeCAD import Base progressbar = Base.ProgressIndicator() progressbar.start("Downloading files...", 4) @@ -120,14 +135,7 @@ def errorDXFLib(gui): p = None p = ArchCommands.download(baseurl + f, force=True) if not p: - if gui: - message = translate("Draft", """Download of dxf libraries failed. -Please install the dxf Library addon manually -from menu Tools -> Addon Manager""") - QtWidgets.QMessageBox.information(None, "", message) - else: - FCC.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n") - FCC.PrintWarning("Please install the dxf Library addon from Tools -> Addon Manager\n") + show_addon_message(gui) break progressbar.stop() sys.path.append(FreeCAD.ConfigGet("UserAppData")) From f723f36d2a776aacf7555e3e401b36411483f689 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:49:35 +0100 Subject: [PATCH 012/161] Draft: Fix extra_scale error in hatch.py (#17715) Fixes #17712. --- src/Mod/Draft/draftobjects/hatch.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/draftobjects/hatch.py b/src/Mod/Draft/draftobjects/hatch.py index c7b117aae1e1..44b7849f4168 100644 --- a/src/Mod/Draft/draftobjects/hatch.py +++ b/src/Mod/Draft/draftobjects/hatch.py @@ -120,16 +120,16 @@ def execute(self,obj): mtx = App.Placement(cen, rot).Matrix face = face.transformShape(mtx.inverse()).Faces[0] - # In TechDraw edges longer than 9999.9 (ca. 10m) are considered 'crazy'. - # Lines in a hatch pattern are also checked. In the code below 9999 is - # used. With extra scaling based on that value a 1000m x 1000m rectangle - # can be hatched. Tested with pattern: Diagonal4, and pattern scale: 1000. - # With a limit of 9999.9 the same test fails. - if face.BoundBox.DiagonalLength > 9999: - extra_scale = 9999 / face.BoundBox.DiagonalLength - else: - extra_scale = 1.0 - face.scale(extra_scale) + # In TechDraw edges longer than 9999.9 (ca. 10m) are considered 'crazy'. + # Lines in a hatch pattern are also checked. In the code below 9999 is + # used. With extra scaling based on that value a 1000m x 1000m rectangle + # can be hatched. Tested with pattern: Diagonal4, and pattern scale: 1000. + # With a limit of 9999.9 the same test fails. + if face.BoundBox.DiagonalLength > 9999: + extra_scale = 9999 / face.BoundBox.DiagonalLength + else: + extra_scale = 1.0 + face.scale(extra_scale) if obj.Rotation.Value: face.rotate(App.Vector(), App.Vector(0, 0, 1), -obj.Rotation) shape = TechDraw.makeGeomHatch(face, obj.Scale * extra_scale, obj.Pattern, obj.File) From 8f9718ebc6790795567c9d1401faf94efaa07591 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 16 Nov 2024 17:52:55 +0100 Subject: [PATCH 013/161] Draft: minor fixes (#17793) - more tolerance on faultly solids in shape2Dview - fixed display of dimensions in arch override unit --- src/Mod/Draft/draftobjects/shape2dview.py | 11 ++++++++--- src/Mod/Draft/draftviewproviders/view_dimension.py | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/draftobjects/shape2dview.py b/src/Mod/Draft/draftobjects/shape2dview.py index 8cfbf10a16b7..fc082e37b08f 100644 --- a/src/Mod/Draft/draftobjects/shape2dview.py +++ b/src/Mod/Draft/draftobjects/shape2dview.py @@ -291,15 +291,20 @@ def execute(self, obj): for s in shapes: shapes_to_cut.extend(s.Faces) for sh in shapes_to_cut: - if cutv: + if cutv and (not cutv.isNull()) and (not sh.isNull()): if sh.Volume < 0: sh.reverse() #if cutv.BoundBox.intersect(sh.BoundBox): # c = sh.cut(cutv) #else: # c = sh.copy() - c = sh.cut(cutv) - cuts.extend(self._get_shapes(c, onlysolids)) + try: + c = sh.cut(cutv) + except ValueError: + print("DEBUG: Error subtracting shapes in", obj.Label) + cuts.extend(self._get_shapes(sh, onlysolids)) + else: + cuts.extend(self._get_shapes(c, onlysolids)) else: cuts.extend(self._get_shapes(sh, onlysolids)) comp = Part.makeCompound(cuts) diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index 2526da2ece71..289c296916d5 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -582,7 +582,7 @@ def updateData(self, obj, prop): unit = vobj.UnitOverride # Special representation if we use 'Building US' scheme - if params.get_param("UserSchema", path="Units") == 5: + if (params.get_param("UserSchema", path="Units") == 5) or (unit == "arch"): self.string = App.Units.Quantity(length, App.Units.Length).UserString if self.string.count('"') > 1: # multiple inch tokens From f08cf60155a0155d2aaa283091dd8ce32c0f2e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gauthier=20Bri=C3=A8re?= Date: Sat, 16 Nov 2024 18:02:02 +0100 Subject: [PATCH 014/161] [Draft] add font path relative (#17819) * Permit a font file path relative to the FreeCAD file * Use obj.Document instead of App.ActiveDocument * use filename = instead of directory = --- src/Mod/Draft/draftobjects/shapestring.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/draftobjects/shapestring.py b/src/Mod/Draft/draftobjects/shapestring.py index 05c5a564e763..6dca3f6e24f8 100644 --- a/src/Mod/Draft/draftobjects/shapestring.py +++ b/src/Mod/Draft/draftobjects/shapestring.py @@ -27,6 +27,7 @@ ## \addtogroup draftobjects # @{ +import os import math from PySide.QtCore import QT_TRANSLATE_NOOP @@ -129,6 +130,12 @@ def execute(self, obj): if obj.String and obj.FontFile: plm = obj.Placement + if obj.FontFile[0] == ".": + # FontFile path relative to the FreeCAD file directory. + font_file = os.path.join(os.path.dirname(obj.Document.FileName), obj.FontFile) + else: + font_file = obj.FontFile + fill = obj.MakeFace if fill is True: # Test a simple letter to know if we have a sticky font or not. @@ -136,7 +143,7 @@ def execute(self, obj): # The 0.03 total area minimum is based on tests with: # 1CamBam_Stick_0.ttf and 1CamBam_Stick_0C.ttf. # See the make_faces function for more information. - char = Part.makeWireString("L", obj.FontFile, 1, 0)[0] + char = Part.makeWireString("L", font_file, 1, 0)[0] shapes = self.make_faces(char) # char is list of wires if not shapes: fill = False @@ -146,7 +153,7 @@ def execute(self, obj): Part.Compound(shapes).BoundBox.DiagonalLength, rel_tol=1e-7) - chars = Part.makeWireString(obj.String, obj.FontFile, obj.Size, obj.Tracking) + chars = Part.makeWireString(obj.String, font_file, obj.Size, obj.Tracking) shapes = [] for char in chars: @@ -164,7 +171,7 @@ def execute(self, obj): ss_shape = Part.Compound([ss_shape]) else: ss_shape = Part.Compound(shapes) - cap_char = Part.makeWireString("M", obj.FontFile, obj.Size, obj.Tracking)[0] + cap_char = Part.makeWireString("M", font_file, obj.Size, obj.Tracking)[0] cap_height = Part.Compound(cap_char).BoundBox.YMax if obj.ScaleToSize: ss_shape.scale(obj.Size / cap_height) From 1c19a7e85d00a9847ec55f935b4e9df9d28e9fe6 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Sat, 16 Nov 2024 18:04:26 +0100 Subject: [PATCH 015/161] Draft: fix tray construction mode button for Light and Dark themes (#17886) Fixes #17869. --- src/Mod/Draft/DraftGui.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 1c9368036fcc..c9b6c004a8db 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -228,11 +228,14 @@ def __init__(self): def _pushbutton(self,name, layout, hide=True, icon=None, width=None, checkable=False, square=False): - button = QtWidgets.QPushButton(self.baseWidget) - button.setObjectName(name) if square: - button.setMaximumSize(QtCore.QSize(button.height(), button.height())) - button.setFlat(True) + button = QtWidgets.QToolButton(self.baseWidget) + if width is not None: + button.setFixedHeight(width) + button.setFixedWidth(width) + else: + button = QtWidgets.QPushButton(self.baseWidget) + button.setObjectName(name) if hide: button.hide() if icon: @@ -488,7 +491,7 @@ def setupTray(self): self.setStyleButton() self.constrButton = self._pushbutton( "constrButton", self.toptray, hide=False, icon='Draft_Construction', - checkable=True, square=True) + width=self.styleButton.sizeHint().height(), checkable=True, square=True) self.constrColor = QtGui.QColor(self.paramconstr) self.autoGroupButton = self._pushbutton( "autoGroup", self.bottomtray,icon=":/icons/button_invalid.svg", From 89d1d717eb5395848aa634084c26b776964610b6 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 16 Nov 2024 18:10:04 +0100 Subject: [PATCH 016/161] BIM: Optimized leader UI (#17310) * BIM: Optimized leader UI - fixes #17284 * Correct task panel icon for BIM Leader. * Make BIM Leader task panel title translatable. * Use a single mode parameter for the Line class. --------- Co-authored-by: Roy-043 --- src/Mod/BIM/bimcommands/BimLeader.py | 6 ++++-- src/Mod/Draft/draftguitools/gui_beziers.py | 10 +++++----- src/Mod/Draft/draftguitools/gui_lines.py | 20 ++++++++++++-------- src/Mod/Draft/draftguitools/gui_splines.py | 4 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index 7fac7446af57..6f65590b79fd 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -35,7 +35,7 @@ class BIM_Leader(gui_lines.Line): def __init__(self): - super(BIM_Leader, self).__init__(wiremode=True) + super().__init__(mode="leader") def GetResources(self): return { @@ -48,7 +48,9 @@ def GetResources(self): } def Activated(self): - super(BIM_Leader, self).Activated(name="Leader", icon="Draft_Wire") + super().Activated( + name="Leader", icon="BIM_Leader", task_title=translate("BIM", "Leader") + ) def finish(self, closed=False, cont=False): import DraftVecUtils diff --git a/src/Mod/Draft/draftguitools/gui_beziers.py b/src/Mod/Draft/draftguitools/gui_beziers.py index 32fb48b84803..59c869b1b7f8 100644 --- a/src/Mod/Draft/draftguitools/gui_beziers.py +++ b/src/Mod/Draft/draftguitools/gui_beziers.py @@ -55,7 +55,7 @@ class BezCurve(gui_lines.Line): """Gui command for the Bézier Curve tool.""" def __init__(self): - super().__init__(wiremode=True) + super().__init__(mode="wire") self.degree = None def GetResources(self): @@ -121,7 +121,7 @@ def action(self, arg): # if mod(len(cpoints), 2) == 0 # then create 2 handle points? self.drawUpdate(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) if len(self.node) > 2: # does this make sense for a BCurve? @@ -241,7 +241,7 @@ class CubicBezCurve(gui_lines.Line): """ def __init__(self): - super().__init__(wiremode=True) + super().__init__(mode="wire") self.degree = 3 self.old_EnableSelection = True @@ -320,7 +320,7 @@ def action(self, arg): # if mod(len(cpoints), 2) == 0 # then create 2 handle points? self.drawUpdate(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) # does this make sense for a BCurve? if len(self.node) > 2: @@ -357,7 +357,7 @@ def action(self, arg): # if mod(len(cpoints),2) == 0 # then create 2 handle points? self.drawUpdate(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) # Does this make sense for a BCurve? if len(self.node) > 2: diff --git a/src/Mod/Draft/draftguitools/gui_lines.py b/src/Mod/Draft/draftguitools/gui_lines.py index 752e2fbb779a..49c8a3279f39 100644 --- a/src/Mod/Draft/draftguitools/gui_lines.py +++ b/src/Mod/Draft/draftguitools/gui_lines.py @@ -51,9 +51,9 @@ class Line(gui_base_original.Creator): """Gui command for the Line tool.""" - def __init__(self, wiremode=False): + def __init__(self, mode="line"): super().__init__() - self.isWire = wiremode + self.mode = mode def GetResources(self): """Set icon, menu and tooltip.""" @@ -70,8 +70,12 @@ def Activated(self, name=QT_TRANSLATE_NOOP("draft", "Line"), icon="Draft_Line", title = translate("draft", name) else: title = task_title - if self.isWire: + if self.mode == "wire": self.ui.wireUi(title=title, icon=icon) + elif self.mode == "leader": + self.ui.wireUi(title=title, icon=icon) + self.ui.closeButton.hide() + self.ui.hasFill.hide() else: self.ui.lineUi(title=title, icon=icon) @@ -120,7 +124,7 @@ def action(self, arg): self.pos = arg["Position"] self.node.append(self.point) self.drawSegment(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) if len(self.node) > 2: # The wire is closed @@ -236,7 +240,7 @@ def drawSegment(self, point): newseg = Part.LineSegment(last, point).toShape() self.obj.Shape = newseg self.obj.ViewObject.Visibility = True - if self.isWire: + if self.mode != "line": _toolmsg(translate("draft", "Pick next point")) else: currentshape = self.obj.Shape.copy() @@ -279,7 +283,7 @@ def numericInput(self, numx, numy, numz): self.point = App.Vector(numx, numy, numz) self.node.append(self.point) self.drawSegment(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) self.ui.setNextFocus() @@ -291,12 +295,12 @@ class Wire(Line): """Gui command for the Wire or Polyline tool. It inherits the `Line` class, and calls essentially the same code, - only this time the `wiremode` is set to `True`, + only this time the `mode` is set to `"wire"`, so we are allowed to place more than two points. """ def __init__(self): - super().__init__(wiremode=True) + super().__init__(mode="wire") def GetResources(self): """Set icon, menu and tooltip.""" diff --git a/src/Mod/Draft/draftguitools/gui_splines.py b/src/Mod/Draft/draftguitools/gui_splines.py index 6390b551202f..46cf38553429 100644 --- a/src/Mod/Draft/draftguitools/gui_splines.py +++ b/src/Mod/Draft/draftguitools/gui_splines.py @@ -50,7 +50,7 @@ class BSpline(gui_lines.Line): """Gui command for the BSpline tool.""" def __init__(self): - super(BSpline, self).__init__(wiremode=True) + super(BSpline, self).__init__(mode="wire") def GetResources(self): """Set icon, menu and tooltip.""" @@ -109,7 +109,7 @@ def action(self, arg): self.pos = arg["Position"] self.node.append(self.point) self.drawUpdate(self.point) - if not self.isWire and len(self.node) == 2: + if self.mode == "line" and len(self.node) == 2: self.finish(cont=None, closed=False) if len(self.node) > 2: # DNC: allows to close the curve From 6f8abe880c07ad0d2d39122b7f697f78da60e1d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 16 Nov 2024 14:47:56 +0100 Subject: [PATCH 017/161] Core: Fix flaw in XMLReader class Remove implementation details of the Document class from the XMLReader class. Instead keep an array of failed files and check them in the calling instance. --- src/App/Document.cpp | 16 +++++++++++++++- src/App/private/DocumentP.h | 1 + src/Base/Reader.cpp | 15 +++++++-------- src/Base/Reader.h | 3 +++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index eff22db58438..11ee02c52277 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1007,7 +1007,8 @@ void Document::Restore(Base::XMLReader &reader) if (reader.hasAttribute("StringHasher")) { d->Hasher->Restore(reader); - } else { + } + else { d->Hasher->clear(); } @@ -1075,6 +1076,17 @@ void Document::Restore(Base::XMLReader &reader) reader.readEndElement("Document"); } +void DocumentP::checkStringHasher(const Base::XMLReader& reader) +{ + if (reader.hasReadFailed("StringHasher.Table.txt")) { + Base::Console().Error(QT_TRANSLATE_NOOP( + "Notifications", + "\nIt is recommended that the user right-click the root of " + "the document and select Mark to recompute.\n" + "The user should then click the Refresh button in the main toolbar.\n")); + } +} + std::pair Document::addStringHasher(const StringHasherRef & hasher) const { if (!hasher) return std::make_pair(false, 0); @@ -2118,6 +2130,8 @@ void Document::restore (const char *filename, signalRestoreDocument(reader); reader.readFiles(zipstream); + DocumentP::checkStringHasher(reader); + if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestore)) { setStatus(Document::PartialRestore, true); Base::Console().Error("There were errors while loading the file. Some data might have been modified or not recovered at all. Look above for more specific information about the objects involved.\n"); diff --git a/src/App/private/DocumentP.h b/src/App/private/DocumentP.h index d6c2ac107e2c..f3930a442daa 100644 --- a/src/App/private/DocumentP.h +++ b/src/App/private/DocumentP.h @@ -144,6 +144,7 @@ struct DocumentP topologicalSort(const std::vector& objects) const; std::vector static partialTopologicalSort(const std::vector& objects); + static void checkStringHasher(const Base::XMLReader& reader); }; } // namespace App diff --git a/src/Base/Reader.cpp b/src/Base/Reader.cpp index 257dc63d8d8c..63b85bfa81a5 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -38,7 +38,6 @@ #include "Persistence.h" #include "Sequencer.h" #include "Stream.h" -#include "Tools.h" #include "XMLTools.h" #ifdef _MSC_VER @@ -438,13 +437,7 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream& zipstream) const // failure. Base::Console().Error("Reading failed from embedded file: %s\n", entry->toString().c_str()); - if (jt->FileName == "StringHasher.Table.txt") { - Base::Console().Error(QT_TRANSLATE_NOOP( - "Notifications", - "\nIt is recommended that the user right-click the root of " - "the document and select Mark to recompute.\n" - "The user should then click the Refresh button in the main toolbar.\n")); - } + FailedFiles.push_back(jt->FileName); } // Go to the next registered file name it = jt + 1; @@ -480,6 +473,12 @@ const std::vector& Base::XMLReader::getFilenames() const return FileNames; } +bool Base::XMLReader::hasReadFailed(const std::string& filename) const +{ + auto it = std::find(FailedFiles.begin(), FailedFiles.end(), filename); + return (it != FailedFiles.end()); +} + bool Base::XMLReader::isRegistered(Base::Persistence* Object) const { if (Object) { diff --git a/src/Base/Reader.h b/src/Base/Reader.h index 81b546e93f4c..a11b1966a25b 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -253,6 +253,8 @@ class BaseExport XMLReader: public XERCES_CPP_NAMESPACE_QUALIFIER DefaultHandler void readFiles(zipios::ZipInputStream& zipstream) const; /// get all registered file names const std::vector& getFilenames() const; + /// returns true if reading the file \a filename has failed + bool hasReadFailed(const std::string& filename) const; bool isRegistered(Base::Persistence* Object) const; virtual void addName(const char*, const char*); virtual const char* getName(const char*) const; @@ -363,6 +365,7 @@ class BaseExport XMLReader: public XERCES_CPP_NAMESPACE_QUALIFIER DefaultHandler private: std::vector FileNames; + mutable std::vector FailedFiles; std::bitset<32> StatusBits; From 36cf031f0ba007bf6150114b0e6e210eb25a12ca Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 15 Nov 2024 13:23:53 +0100 Subject: [PATCH 018/161] BIM: Fixed image loading of the tutorial - fixes #17863 --- src/Mod/BIM/bimcommands/BimTutorial.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Mod/BIM/bimcommands/BimTutorial.py b/src/Mod/BIM/bimcommands/BimTutorial.py index 51d82f049e2a..43fd1a5c6489 100644 --- a/src/Mod/BIM/bimcommands/BimTutorial.py +++ b/src/Mod/BIM/bimcommands/BimTutorial.py @@ -169,8 +169,12 @@ def load(self, arg=None): os.makedirs(store) for path in imagepaths: # name = re.findall(r"[\\w.-]+\\.(?i)(?:jpg|png|gif|bmp)",path) - name = re.findall(r"(?i)[\\w.-]+\\.(?:jpg|png|gif|bmp)", path) - if name: + # name = re.findall(r"(?i)[\\w.-]+\\.(?:jpg|png|gif|bmp)", path) + try: + name = os.path.splitext(os.path.basename(path))[0] + except: + print("unparsable image path:", path) + else: name = name[-1] storename = os.path.join(store, name) if not os.path.exists(storename): @@ -190,8 +194,6 @@ def load(self, arg=None): descr = descr.replace( path, "file:///" + storename.replace("\\", "/") ) - else: - print("unparsable image path:", path) nd.append(descr) self.descriptions = nd From 8619b03bbc7c259d14a3b981b33ca13abfe884e8 Mon Sep 17 00:00:00 2001 From: hasecilu Date: Wed, 18 Sep 2024 09:46:31 -0600 Subject: [PATCH 019/161] Addon Manager: Show involved branches' names on branch change operation Fix #12969 --- .../addonmanager_package_details_controller.py | 12 ++++++++---- src/Mod/AddonManager/change_branch.py | 8 ++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Mod/AddonManager/addonmanager_package_details_controller.py b/src/Mod/AddonManager/addonmanager_package_details_controller.py index 09a6c7a76f04..cfcc7860b663 100644 --- a/src/Mod/AddonManager/addonmanager_package_details_controller.py +++ b/src/Mod/AddonManager/addonmanager_package_details_controller.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Provides the PackageDetails widget. """ +"""Provides the PackageDetails widget.""" import os from typing import Optional @@ -237,7 +237,7 @@ def disable_clicked(self) -> None: self.addon.set_status(self.original_status) self.update_status.emit(self.addon) - def branch_changed(self, name: str) -> None: + def branch_changed(self, old_branch: str, name: str) -> None: """Displays a dialog confirming the branch changed, and tries to access the metadata file from that branch.""" QtWidgets.QMessageBox.information( @@ -245,8 +245,12 @@ def branch_changed(self, name: str) -> None: translate("AddonsInstaller", "Success"), translate( "AddonsInstaller", - "Branch change succeeded, please restart to use the new version.", - ), + "Branch change succeeded.\n" + "Moved\n" + "from: {}\n" + "to: {}\n" + "Please restart to use the new version.", + ).format(old_branch, name), ) # See if this branch has a package.xml file: basedir = fci.getUserAppDataDir() diff --git a/src/Mod/AddonManager/change_branch.py b/src/Mod/AddonManager/change_branch.py index 5a92f29c1a14..3fb73358decb 100644 --- a/src/Mod/AddonManager/change_branch.py +++ b/src/Mod/AddonManager/change_branch.py @@ -34,7 +34,7 @@ class ChangeBranchDialog(QtWidgets.QWidget): - branch_changed = QtCore.Signal(str) + branch_changed = QtCore.Signal(str, str) def __init__(self, path: str, parent=None): super().__init__(parent) @@ -55,10 +55,10 @@ def __init__(self, path: str, parent=None): # Figure out what row gets selected: git_manager = initialize_git() row = 0 - current_ref = git_manager.current_branch(path) + self.current_ref = git_manager.current_branch(path) selection_model = self.ui.tableView.selectionModel() for ref in self.item_model.branches: - if ref["ref_name"] == current_ref: + if ref["ref_name"] == self.current_ref: index = self.item_filter.mapFromSource(self.item_model.index(row, 0)) selection_model.select(index, QtCore.QItemSelectionModel.ClearAndSelect) selection_model.select(index.siblingAtColumn(1), QtCore.QItemSelectionModel.Select) @@ -118,7 +118,7 @@ def exec(self): gm.checkout(self.item_model.path, remote_name) else: gm.checkout(self.item_model.path, remote_name, args=["-b", local_name]) - self.branch_changed.emit(local_name) + self.branch_changed.emit(self.current_ref, local_name) class ChangeBranchDialogModel(QtCore.QAbstractTableModel): From 4c1f94f6c25c4d429ab702bb5409321a6e1e929b Mon Sep 17 00:00:00 2001 From: hasecilu Date: Thu, 19 Sep 2024 13:10:19 -0600 Subject: [PATCH 020/161] Addon Manager: Show repository URL if it exists on the metadata Fix: #14777 --- ...ddonmanager_widget_package_details_view.py | 19 +++++++++++++++++++ src/Mod/AddonManager/addonmanager_metadata.py | 6 ++++++ ...addonmanager_package_details_controller.py | 6 +++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py index fbe892cbb5fe..0927fde4ccc9 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_package_details_view.py @@ -92,6 +92,7 @@ def __init__(self, parent: QtWidgets.QWidget = None): self.readme_browser = None self.message_label = None self.location_label = None + self.url_label = None self.installed = False self.disabled = False self.update_info = UpdateInformation() @@ -108,10 +109,13 @@ def _setup_ui(self): self.readme_browser = WidgetReadmeBrowser(self) self.message_label = QtWidgets.QLabel(self) self.location_label = QtWidgets.QLabel(self) + self.url_label = QtWidgets.QLabel(self) + self.url_label.setOpenExternalLinks(True) self.location_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) self.vertical_layout.addWidget(self.button_bar) self.vertical_layout.addWidget(self.message_label) self.vertical_layout.addWidget(self.location_label) + self.vertical_layout.addWidget(self.url_label) self.vertical_layout.addWidget(self.readme_browser) self.button_bar.hide() # Start with no bar @@ -127,6 +131,21 @@ def set_location(self, location: Optional[str]): else: self.location_label.hide() + def set_url(self, url: Optional[str]): + if url is not None: + text = ( + translate("AddonsInstaller", "Repository URL") + + ': ' + + url + + "" + ) + self.url_label.setText(text) + self.url_label.show() + else: + self.url_label.hide() + def set_installed( self, installed: bool, diff --git a/src/Mod/AddonManager/addonmanager_metadata.py b/src/Mod/AddonManager/addonmanager_metadata.py index 1afb7334548a..debe1bac278c 100644 --- a/src/Mod/AddonManager/addonmanager_metadata.py +++ b/src/Mod/AddonManager/addonmanager_metadata.py @@ -244,6 +244,12 @@ def get_branch_from_metadata(metadata: Metadata) -> str: return "master" # Legacy default +def get_repo_url_from_metadata(metadata: Metadata) -> str: + for url in metadata.url: + if url.type == UrlType.repository: + return url.location + + class MetadataReader: """Read metadata XML data and construct a Metadata object""" diff --git a/src/Mod/AddonManager/addonmanager_package_details_controller.py b/src/Mod/AddonManager/addonmanager_package_details_controller.py index cfcc7860b663..e13d6a006bc1 100644 --- a/src/Mod/AddonManager/addonmanager_package_details_controller.py +++ b/src/Mod/AddonManager/addonmanager_package_details_controller.py @@ -35,6 +35,7 @@ Version, get_first_supported_freecad_version, get_branch_from_metadata, + get_repo_url_from_metadata, ) from addonmanager_workers_startup import GetMacroDetailsWorker, CheckSingleUpdateWorker from addonmanager_git import GitManager, NoGitFound @@ -98,6 +99,10 @@ def show_repo(self, repo: Addon) -> None: installed = self.addon.status() != Addon.Status.NOT_INSTALLED self.ui.set_installed(installed) + if repo.metadata is not None: + self.ui.set_url(get_repo_url_from_metadata(repo.metadata)) + else: + self.ui.set_url(None) # to reset it and hide it update_info = UpdateInformation() if installed: update_info.unchecked = self.addon.status() == Addon.Status.UNCHECKED @@ -110,7 +115,6 @@ def show_repo(self, repo: Addon) -> None: update_info.version = repo.macro.version self.ui.set_update_available(update_info) self.ui.set_location(os.path.join(self.addon.mod_directory, self.addon.name)) - self.ui.set_location(os.path.join(self.addon.mod_directory, self.addon.name)) self.ui.set_disabled(self.addon.is_disabled()) self.ui.allow_running(repo.repo_type == Addon.Kind.MACRO) self.ui.allow_disabling(repo.repo_type != Addon.Kind.MACRO) From d8d35f133dc910ce4c9cbf3328b3254548b346d2 Mon Sep 17 00:00:00 2001 From: bgbsww Date: Thu, 26 Sep 2024 11:36:35 -0400 Subject: [PATCH 021/161] Contribute helper files for CLion debugging --- contrib/clion/GetCLionDebugPort.FCMacro | 12 ++++++++++++ contrib/clion/attach_pydevd.py.patch | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 contrib/clion/GetCLionDebugPort.FCMacro create mode 100644 contrib/clion/attach_pydevd.py.patch diff --git a/contrib/clion/GetCLionDebugPort.FCMacro b/contrib/clion/GetCLionDebugPort.FCMacro new file mode 100644 index 000000000000..9689afd84fd2 --- /dev/null +++ b/contrib/clion/GetCLionDebugPort.FCMacro @@ -0,0 +1,12 @@ +import pydevd +from multiprocessing.connection import Listener + +print("CLion debugger macro running. Starting listener to get port") +listen = Listener(('localhost', 39998), backlog=1) +link = listen.accept() +port = link.recv() +link.close() +listen.close() +print("Port", port, "received, starting debugger. Check CLion to see if a breakpoint has been hit and continue") +pydevd.settrace(port=port) +print("Debugger operating, leaving macro.") \ No newline at end of file diff --git a/contrib/clion/attach_pydevd.py.patch b/contrib/clion/attach_pydevd.py.patch new file mode 100644 index 000000000000..cc5dc173b445 --- /dev/null +++ b/contrib/clion/attach_pydevd.py.patch @@ -0,0 +1,18 @@ +--- attach_pydevd.py.orig 2024-09-26 10:36:47.131066345 -0400 ++++ attach_pydevd.py 2024-09-26 10:16:48.687714133 -0400 +@@ -48,6 +48,15 @@ + import add_code_to_python_process + show_debug_info_on_target_process = 0 + ++ print("attach_pydevd is trying to relay the port",setup['port']) ++ try: ++ from multiprocessing.connection import Client ++ link = Client(('localhost',39998)) ++ link.send(setup['port']) ++ link.close() ++ except ConnectionError as ce: ++ pass ++ + pydevd_dirname = os.path.dirname(os.path.dirname(__file__)) + + if sys.platform == 'win32': From 3875c306ac7e4f66333e803ac31ee5aa2cb81dff Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Wed, 4 Sep 2024 19:41:15 +0200 Subject: [PATCH 022/161] Spreadsheet: Double click separator to resize to content Qt handles resize to content on double clicking the separator in the header, by default. However this does not work in FreeCAD. There are no comments on why this was done and is therefore treated as bug instead of feature. Manual testing has been performed after the change and: * Scaling by double clicking separator in header works * Sizes are correctly stored in sheet when resizing to content --- src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp | 8 -------- src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h | 2 -- 2 files changed, 10 deletions(-) diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp index f0ae0de07970..b86cbb44c7eb 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.cpp @@ -92,14 +92,6 @@ void SpreadsheetDelegate::onEditorFinishedWithKey(int key, Qt::KeyboardModifiers Q_EMIT finishedWithKey(key, modifiers); } -QSize SpreadsheetDelegate::sizeHint(const QStyleOptionViewItem& option, - const QModelIndex& index) const -{ - Q_UNUSED(option); - Q_UNUSED(index); - return {}; -} - static inline void drawBorder(QPainter* painter, const QStyleOptionViewItem& option, unsigned flags, diff --git a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h index 7036ffd3e5f8..7ae2fe0338eb 100644 --- a/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h +++ b/src/Mod/Spreadsheet/Gui/SpreadsheetDelegate.h @@ -47,8 +47,6 @@ class SpreadsheetDelegate: public QStyledItemDelegate void setModelData(QWidget* editor, QAbstractItemModel* model, 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; From a049641771a92e9d9a7c4b45e0c349d1bbed8fe2 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 18 Nov 2024 14:15:48 +0100 Subject: [PATCH 023/161] Assembly: Store DocumentObject instead of mbdPart for the dragged parts. Fixing the bug where doDragStep was 50% of time failing to find the correct DocumentObject due to bundling. --- src/Mod/Assembly/App/AssemblyObject.cpp | 41 ++++++++++++++++--------- src/Mod/Assembly/App/AssemblyObject.h | 2 +- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp index cf74c3f83038..510b34e31fc9 100644 --- a/src/Mod/Assembly/App/AssemblyObject.cpp +++ b/src/Mod/Assembly/App/AssemblyObject.cpp @@ -194,12 +194,30 @@ void AssemblyObject::preDrag(std::vector dragParts) solve(); bundleFixed = false; - dragMbdParts.clear(); + draggedParts.clear(); for (auto part : dragParts) { - auto mbdPart = getMbDPart(part); - if (std::find(dragMbdParts.begin(), dragMbdParts.end(), mbdPart) == dragMbdParts.end()) { - dragMbdParts.push_back(mbdPart); + // make sure no duplicate + if (std::find(draggedParts.begin(), draggedParts.end(), part) != draggedParts.end()) { + continue; } + + // Some objects have been bundled, we don't want to add these to dragged parts + Base::Placement plc; + for (auto& pair : objectPartMap) { + App::DocumentObject* parti = pair.first; + if (parti != part) { + continue; + } + plc = pair.second.offsetPlc; + } + if (!plc.isIdentity()) { + // If not identity, then it's a bundled object. Some bundled objects may + // have identity placement if they have the same position as the main object of + // the bundle. But they're not going to be a problem. + continue; + } + + draggedParts.push_back(part); } mbdAssembly->runPreDrag(); @@ -208,21 +226,16 @@ void AssemblyObject::preDrag(std::vector dragParts) void AssemblyObject::doDragStep() { try { - for (auto& mbdPart : dragMbdParts) { - App::DocumentObject* part = nullptr; - - // Find the corresponding DocumentObject for the mbdPart - for (auto& pair : objectPartMap) { - if (pair.second.part == mbdPart) { - part = pair.first; - break; - } - } + std::vector> dragMbdParts; + for (auto& part : draggedParts) { if (!part) { continue; } + auto mbdPart = getMbDPart(part); + dragMbdParts.push_back(mbdPart); + // Update the MBD part's position Base::Placement plc = getPlacementFromProp(part, "Placement"); Base::Vector3d pos = plc.getPosition(); diff --git a/src/Mod/Assembly/App/AssemblyObject.h b/src/Mod/Assembly/App/AssemblyObject.h index b2a083767fed..a51968058ee1 100644 --- a/src/Mod/Assembly/App/AssemblyObject.h +++ b/src/Mod/Assembly/App/AssemblyObject.h @@ -250,7 +250,7 @@ class AssemblyExport AssemblyObject: public App::Part std::unordered_map objectPartMap; std::vector> objMasses; - std::vector> dragMbdParts; + std::vector draggedParts; std::vector> previousPositions; From 71f0104bb2e88670f20b9889148999f8e684461a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20M=C3=A1cha?= Date: Thu, 14 Nov 2024 22:28:37 +0100 Subject: [PATCH 024/161] Assembly: fixed defect in the migrationScript4 function The old CAD model created by the development version of FreeCAD (in which the Assembly workbench was used) contained joints that, for some reason, had an empty Joint Connector 1 reference (Reference1). This was causing an exception and a crash of the Python function called migrationScript4. The FreeCAD Report view contained: 23:28:29 pyException: Traceback (most recent call last): File "/FreeCAD/Mod/Assembly/JointObject.py", line 175, in onDocumentRestored self.createProperties(joint) File "/FreeCAD/Mod/Assembly/JointObject.py", line 181, in createProperties self.migrationScript4(joint) File "/FreeCAD/Mod/Assembly/JointObject.py", line 514, in migrationScript4 if hasattr(joint, "Reference1") and joint.Reference1[0] is not None: ~~~~~~~~~~~~~~~~^^^ : 'NoneType' object is not subscriptable This patch attempts to avoid such exceptions by validating the type of the property variable before accessing it. --- src/Mod/Assembly/JointObject.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Mod/Assembly/JointObject.py b/src/Mod/Assembly/JointObject.py index b31a9588bd0e..ba4405901b4a 100644 --- a/src/Mod/Assembly/JointObject.py +++ b/src/Mod/Assembly/JointObject.py @@ -28,6 +28,7 @@ from PySide import QtCore from PySide.QtCore import QT_TRANSLATE_NOOP +from collections.abc import Sequence if App.GuiUp: import FreeCADGui as Gui @@ -511,7 +512,11 @@ def migrationScript3(self, joint): joint.Offset2 = App.Placement(current_offset, App.Rotation(current_rotation, 0, 0)) def migrationScript4(self, joint): - if hasattr(joint, "Reference1") and joint.Reference1[0] is not None: + if ( + hasattr(joint, "Reference1") + and isinstance(joint.Reference1, Sequence) + and joint.Reference1[0] is not None + ): doc_name = joint.Reference1[0].Document.Name sub1 = joint.Reference1[1][0] sub1 = UtilsAssembly.fixBodyExtraFeatureInSub(doc_name, sub1) @@ -521,7 +526,11 @@ def migrationScript4(self, joint): if sub1 != joint.Reference1[1][0] or sub2 != joint.Reference1[1][1]: joint.Reference1 = (joint.Reference1[0], [sub1, sub2]) - if hasattr(joint, "Reference2") and joint.Reference2[0] is not None: + if ( + hasattr(joint, "Reference2") + and isinstance(joint.Reference2, Sequence) + and joint.Reference2[0] is not None + ): doc_name = joint.Reference2[0].Document.Name sub1 = joint.Reference2[1][0] sub1 = UtilsAssembly.fixBodyExtraFeatureInSub(doc_name, sub1) From 2f6329d6e79a86c0d7f2ea85327cf50eb2fe99ad Mon Sep 17 00:00:00 2001 From: Kris Slyka Date: Mon, 18 Nov 2024 17:52:16 +0100 Subject: [PATCH 025/161] [tools] fcinfo: fix syntax warnings and improve output for git diffs (#16312) * Fix syntax warnings about invalid escape sequences Backspaces in regular expressions were not escaped properly leading to warnings on every invocation of the program. * Improve formatting of fcinfo output * Printing of part BREP file properties (hash and size) has been made optional since these values often change without explicit user action making git diffs almost unreadable by hiding actual changes behind a flood of changed hashes because a base feature further up the history was changed. There is a new option (-p) to re-enable the printing of these file properties. * Unformatted float outputs have been replaced with proper formatting using f-strings which round the values to a sensible number of places. * Colors are printed in their native 0-255 range. Printing them as float brings no benefit here. * Most string concatenation for output has been replaced with f-strings * Fix printing of color properties --- src/Tools/fcinfo | 88 +++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/src/Tools/fcinfo b/src/Tools/fcinfo index 79fda42a1b44..23598065ac74 100755 --- a/src/Tools/fcinfo +++ b/src/Tools/fcinfo @@ -51,6 +51,7 @@ Options: This is sufficient to see if a file has changed, as its SHA1 code and timestamp will show it. But won't show details of what has changed. + -p --partinfo: Print size and hash of internal BREP part files -g --gui: Adds visual properties too (if not using -s or -vs) Git usage: @@ -112,17 +113,18 @@ class FreeCADFileHandler(xml.sax.ContentHandler): self.obj = self.clean(attributes["name"]) elif tag == "Part": - if self.obj: + if self.obj and partinfo: + file = self.clean(attributes["file"]) r = self.zfile.read(attributes["file"]) s = r.__sizeof__() if s < 1024: - s = str(s) + "B" + s = f"{s:g}B" elif s > 1048576: - s = str(s / 1048576) + "M" + s = f"{s / 1048576:.3g}M" else: - s = str(s / 1024) + "K" - s += " " + str(hashlib.sha1(r).hexdigest()[:12]) - self.contents[self.obj] += " (" + s + ")" + s = f"{s / 1024:.3g}K" + d = str(hashlib.sha1(r).hexdigest()[:12]) + self.contents[self.obj] += f" ({file},{s},{d})" elif tag == "Property": self.prop = None @@ -154,58 +156,41 @@ class FreeCADFileHandler(xml.sax.ContentHandler): self.contents[self.prop] = attributes["value"] elif self.short == 0: if tag == "Float": - self.contents[self.obj + "00000000::" + self.prop] = str( - float(attributes["value"]) - ) + val = float(attributes["value"]) + self.contents[self.obj + "00000000::" + self.prop] = f"{val:g}" else: self.contents[self.obj + "00000000::" + self.prop] = attributes["value"] elif tag in ["PropertyVector"]: if self.prop and self.obj and (self.short == 0): - val = ( - "(" - + str(float(attributes["valueX"])) - + "," - + str(float(attributes["valueY"])) - + "," - + str(float(attributes["valueZ"])) - + ")" - ) + vx = float(attributes["valueX"]) + vy = float(attributes["valueY"]) + vz = float(attributes["valueZ"]) + val = f"({vx:g},{vy:g},{vz:g})" self.contents[self.obj + "00000000::" + self.prop] = val elif tag in ["PropertyPlacement"]: if self.prop and self.obj and (self.short == 0): - val = ( - "(" - + str(float(attributes["Px"])) - + "," - + str(float(attributes["Py"])) - + "," - + str(float(attributes["Pz"])) - + ")" - ) - val += ( - " (" - + str(round(float(attributes["Q0"]), 4)) - + "," - + str(round(float(attributes["Q1"]), 4)) - + "," - ) - val += ( - str(round(float(attributes["Q2"]), 4)) - + "," - + str(round(float(attributes["Q3"]), 4)) - + ")" - ) + px = float(attributes["Px"]) + py = float(attributes["Py"]) + pz = float(attributes["Pz"]) + + q0 = float(attributes["Q0"]) + q1 = float(attributes["Q1"]) + q2 = float(attributes["Q2"]) + q3 = float(attributes["Q3"]) + + val = f"({px:g},{py:g},{pz:g})" + val += f"({q0:.3g},{q1:.3g},{q2:.3g},{q3:.3g})" self.contents[self.obj + "00000000::" + self.prop] = val elif tag in ["PropertyColor"]: if self.prop and self.obj and (self.short == 0): c = int(attributes["value"]) - r = float((c >> 24) & 0xFF) / 255.0 - g = float((c >> 16) & 0xFF) / 255.0 - b = float((c >> 8) & 0xFF) / 255.0 - val = str((r, g, b)) + r = (c >> 24) & 0xFF + g = (c >> 16) & 0xFF + b = (c >> 8) & 0xFF + val = f"({r},{g},{b})" self.contents[self.obj + "00000000::" + self.prop] = val elif tag == "Objects": @@ -218,8 +203,8 @@ class FreeCADFileHandler(xml.sax.ContentHandler): for key, value in items: key = self.clean(key) value = self.clean(value) - print(" " + key + " : " + value) - print(" Objects: (" + self.count + ")") + print(f" {key} : {value}") + print(f" Objects: ({self.count})") self.contents = {} def endElement(self, tag): @@ -233,7 +218,7 @@ class FreeCADFileHandler(xml.sax.ContentHandler): key = " " + key.split("00000000::")[1] value = self.clean(value) if value: - print(" " + key + " : " + value) + print(f" {key} : {value}") def clean(self, value): @@ -263,6 +248,11 @@ if __name__ == "__main__": else: short = 0 + if ("-p" in sys.argv[1:]) or ("--partinfo" in sys.argv[1:]): + partinfo = True + else: + partinfo = False + if ("-g" in sys.argv[1:]) or ("--gui" in sys.argv[1:]): gui = True else: @@ -275,10 +265,10 @@ if __name__ == "__main__": doc = zfile.read("Document.xml") if gui and "GuiDocument.xml" in zfile.namelist(): guidoc = zfile.read("GuiDocument.xml") - guidoc = re.sub(b"<\?xml.*?-->", b" ", guidoc, flags=re.MULTILINE | re.DOTALL) + guidoc = re.sub(b"<\\?xml.*?-->", b" ", guidoc, flags=re.MULTILINE | re.DOTALL) # a valid xml doc can have only one root element. So we need to insert # all the contents of the GUiDocument tag into the main one - doc = re.sub(b"<\/Document>", b"", doc, flags=re.MULTILINE | re.DOTALL) + doc = re.sub(b"<\\/Document>", b"", doc, flags=re.MULTILINE | re.DOTALL) guidoc = re.sub(b"", b" ", guidoc, flags=re.MULTILINE | re.DOTALL) doc += guidoc s = os.path.getsize(sys.argv[-1]) From 8f0e61bffd38eca0e3df6910bc78b94a9025c977 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Fri, 13 Sep 2024 14:58:25 +0200 Subject: [PATCH 026/161] [Mod] clean FemMesh.cpp Removed dead code --- src/Mod/Fem/App/FemMesh.cpp | 244 ------------------------------------ 1 file changed, 244 deletions(-) diff --git a/src/Mod/Fem/App/FemMesh.cpp b/src/Mod/Fem/App/FemMesh.cpp index f5d7128321a7..2f1f8b0cc324 100644 --- a/src/Mod/Fem/App/FemMesh.cpp +++ b/src/Mod/Fem/App/FemMesh.cpp @@ -139,9 +139,6 @@ void FemMesh::copyMeshData(const FemMesh& mesh) { _Mtrx = mesh._Mtrx; - // See file SMESH_I/SMESH_Gen_i.cxx in the git repo of smesh at - // https://git.salome-platform.org -#if 1 // 1. Get source mesh SMESHDS_Mesh* srcMeshDS = mesh.myMesh->GetMeshDS(); @@ -263,247 +260,6 @@ void FemMesh::copyMeshData(const FemMesh& mesh) } newMeshDS->Modified(); - -#else - SMESHDS_Mesh* meshds = this->myMesh->GetMeshDS(); - - // Some further information is still not copied: - // https://forum.freecad.org/viewtopic.php?f=18&t=18982#p148114 - SMDS_NodeIteratorPtr aNodeIter = mesh.myMesh->GetMeshDS()->nodesIterator(); - for (; aNodeIter->more();) { - const SMDS_MeshNode* aNode = aNodeIter->next(); - double temp[3]; - aNode->GetXYZ(temp); - meshds->AddNodeWithID(temp[0], temp[1], temp[2], aNode->GetID()); - } - SMDS_EdgeIteratorPtr aEdgeIter = mesh.myMesh->GetMeshDS()->edgesIterator(); - for (; aEdgeIter->more();) { - const SMDS_MeshEdge* aEdge = aEdgeIter->next(); - meshds->AddEdgeWithID(aEdge->GetNode(0), aEdge->GetNode(1), aEdge->GetID()); - } - - SMDS_FaceIteratorPtr aFaceIter = mesh.myMesh->GetMeshDS()->facesIterator(); - for (; aFaceIter->more();) { - const SMDS_MeshFace* aFace = aFaceIter->next(); - switch (aFace->NbNodes()) { - case 3: - meshds->AddFaceWithID(aFace->GetNode(0), - aFace->GetNode(1), - aFace->GetNode(2), - aFace->GetID()); - break; - case 4: - meshds->AddFaceWithID(aFace->GetNode(0), - aFace->GetNode(1), - aFace->GetNode(2), - aFace->GetNode(3), - aFace->GetID()); - break; - case 6: - meshds->AddFaceWithID(aFace->GetNode(0), - aFace->GetNode(1), - aFace->GetNode(2), - aFace->GetNode(3), - aFace->GetNode(4), - aFace->GetNode(5), - aFace->GetID()); - break; - case 8: - meshds->AddFaceWithID(aFace->GetNode(0), - aFace->GetNode(1), - aFace->GetNode(2), - aFace->GetNode(3), - aFace->GetNode(4), - aFace->GetNode(5), - aFace->GetNode(6), - aFace->GetNode(7), - aFace->GetID()); - break; - default: { - std::vector aNodes; - for (int i = 0; aFace->NbNodes(); i++) { - aNodes.push_back(aFace->GetNode(0)); - } - meshds->AddPolygonalFaceWithID(aNodes, aFace->GetID()); - } break; - } - } - - SMDS_VolumeIteratorPtr aVolIter = mesh.myMesh->GetMeshDS()->volumesIterator(); - for (; aVolIter->more();) { - const SMDS_MeshVolume* aVol = aVolIter->next(); - switch (aVol->NbNodes()) { - case 4: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetID()); - break; - case 5: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetID()); - break; - case 6: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetID()); - break; - case 8: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetNode(6), - aVol->GetNode(7), - aVol->GetID()); - break; - case 10: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetNode(6), - aVol->GetNode(7), - aVol->GetNode(8), - aVol->GetNode(9), - aVol->GetID()); - break; - case 13: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetNode(6), - aVol->GetNode(7), - aVol->GetNode(8), - aVol->GetNode(9), - aVol->GetNode(10), - aVol->GetNode(11), - aVol->GetNode(12), - aVol->GetID()); - break; - case 15: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetNode(6), - aVol->GetNode(7), - aVol->GetNode(8), - aVol->GetNode(9), - aVol->GetNode(10), - aVol->GetNode(11), - aVol->GetNode(12), - aVol->GetNode(13), - aVol->GetNode(14), - aVol->GetID()); - break; - case 20: - meshds->AddVolumeWithID(aVol->GetNode(0), - aVol->GetNode(1), - aVol->GetNode(2), - aVol->GetNode(3), - aVol->GetNode(4), - aVol->GetNode(5), - aVol->GetNode(6), - aVol->GetNode(7), - aVol->GetNode(8), - aVol->GetNode(9), - aVol->GetNode(10), - aVol->GetNode(11), - aVol->GetNode(12), - aVol->GetNode(13), - aVol->GetNode(14), - aVol->GetNode(15), - aVol->GetNode(16), - aVol->GetNode(17), - aVol->GetNode(18), - aVol->GetNode(19), - aVol->GetID()); - break; - default: { - if (aVol->IsPoly()) { - const SMDS_PolyhedralVolumeOfNodes* aPolyVol = - dynamic_cast(aVol); - if (!aPolyVol) { - break; - } - std::vector aNodes; - for (int i = 0; i < aPolyVol->NbNodes(); i++) { - aNodes.push_back(aPolyVol->GetNode(i)); - } - meshds->AddPolyhedralVolumeWithID(aNodes, - aPolyVol->GetQuanities(), - aPolyVol->GetID()); - } - } break; - } - } - - // Copy groups - std::list grpIds = mesh.myMesh->GetGroupIds(); - for (auto it : grpIds) { - // group of source mesh - SMESH_Group* sourceGroup = mesh.myMesh->GetGroup(it); - SMESHDS_GroupBase* sourceGroupDS = sourceGroup->GetGroupDS(); - - int aId; - if (sourceGroupDS->GetType() == SMDSAbs_Node) { - SMESH_Group* targetGroup = - this->myMesh->AddGroup(SMDSAbs_Node, sourceGroupDS->GetStoreName(), aId); - if (targetGroup) { - SMESHDS_Group* targetGroupDS = - dynamic_cast(targetGroup->GetGroupDS()); - if (targetGroupDS) { - SMDS_ElemIteratorPtr aIter = sourceGroupDS->GetElements(); - while (aIter->more()) { - const SMDS_MeshElement* aElem = aIter->next(); - const SMDS_MeshNode* aNode = meshds->FindNode(aElem->GetID()); - if (aNode) { - targetGroupDS->SMDSGroup().Add(aNode); - } - } - } - } - } - else { - SMESH_Group* targetGroup = this->myMesh->AddGroup(sourceGroupDS->GetType(), - sourceGroupDS->GetStoreName(), - aId); - if (targetGroup) { - SMESHDS_Group* targetGroupDS = - dynamic_cast(targetGroup->GetGroupDS()); - if (targetGroupDS) { - SMDS_ElemIteratorPtr aIter = sourceGroupDS->GetElements(); - while (aIter->more()) { - const SMDS_MeshElement* aElem = aIter->next(); - const SMDS_MeshElement* aElement = meshds->FindElement(aElem->GetID()); - if (aElement) { - targetGroupDS->SMDSGroup().Add(aElement); - } - } - } - } - } - } -#endif } const SMESH_Mesh* FemMesh::getSMesh() const From 0fee326c54a0df942a3182d1edfd87d50302ab1a Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Thu, 3 Oct 2024 22:47:57 +0200 Subject: [PATCH 027/161] [cmake] clean InitializeFreeCADBuildOptions.cmake cmake version is always greater than 3.4.3 The verification is done in the cmakefile in the root folder --- cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake index e9aa47fd6e30..e589951030d7 100644 --- a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake +++ b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake @@ -184,12 +184,6 @@ macro(InitializeFreeCADBuildOptions) set(BUILD_SMESH ON ) endif() - # for Windows the minimum required cmake version is 3.4.3 to build the CAM module - if(WIN32 AND CMAKE_VERSION VERSION_LESS 3.4.3) - message(WARNING "Disable CAM, requires cmake >= 3.4.3 in order to build this module") - set(BUILD_CAM OFF ) - endif() - # force build directory to be different to source directory if (BUILD_FORCE_DIRECTORY) if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) From f9ba94c70b139ece6ba5ffba47632d91b5c9c645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pinkava?= Date: Thu, 3 Oct 2024 21:10:35 +0200 Subject: [PATCH 028/161] Sketcher: refactor, drop return in void returning functions --- src/Mod/Sketcher/App/GeometryFacade.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Sketcher/App/GeometryFacade.cpp b/src/Mod/Sketcher/App/GeometryFacade.cpp index 4dd4cf0577a7..f9f93fc2701d 100644 --- a/src/Mod/Sketcher/App/GeometryFacade.cpp +++ b/src/Mod/Sketcher/App/GeometryFacade.cpp @@ -155,7 +155,7 @@ int GeometryFacade::getId(const Part::Geometry* geometry) void GeometryFacade::setId(Part::Geometry* geometry, int id) { auto gf = GeometryFacade::getFacade(geometry); - return gf->setId(id); + gf->setId(id); } bool GeometryFacade::getConstruction(const Part::Geometry* geometry) @@ -171,7 +171,7 @@ void GeometryFacade::setConstruction(Part::Geometry* geometry, bool construction throwOnNullPtr(geometry); auto gf = GeometryFacade::getFacade(geometry); - return gf->setConstruction(construction); + gf->setConstruction(construction); } bool GeometryFacade::isInternalType(const Part::Geometry* geometry, InternalType::InternalType type) From cdb92768fe4f33d900664415c613f9eced5b8927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Br=C3=A6strup=20Sayoc?= Date: Mon, 18 Nov 2024 20:14:47 +0100 Subject: [PATCH 029/161] [TechDraw] Return logic simplification (#16504) * [TechDraw] AppTechDrawPy.cpp return logic simplification * [TechDraw] CosmeticExtension.cpp return logic simplification * [TechDraw] DrawBrokenView.cpp return logic simplification * [TechDraw] HatchLine.cpp return logic simplification * [TechDraw] LineGenerator.cpp return logic simplification * [TechDraw] Preferences.cpp return logic simplification * [TechDraw] ShapeExtractor.cpp return logic simplification * [TechDraw] MDIViewPage.cpp return logic simplification * [TechDraw] QGILeaderLine.cpp return logic simplification * [TechDraw] QGIRichAnno.cpp return logic simplification * [TechDraw] QGTracker.cpp return logic simplification --- src/Mod/TechDraw/App/AppTechDrawPy.cpp | 3 +-- src/Mod/TechDraw/App/CosmeticExtension.cpp | 3 +-- src/Mod/TechDraw/App/DrawBrokenView.cpp | 5 +---- src/Mod/TechDraw/App/HatchLine.cpp | 16 ++++++---------- src/Mod/TechDraw/App/LineGenerator.cpp | 22 +++++++--------------- src/Mod/TechDraw/App/Preferences.cpp | 15 +++++---------- src/Mod/TechDraw/App/ShapeExtractor.cpp | 11 +++++------ src/Mod/TechDraw/Gui/MDIViewPage.cpp | 4 +--- src/Mod/TechDraw/Gui/QGILeaderLine.cpp | 8 +++----- src/Mod/TechDraw/Gui/QGIRichAnno.cpp | 4 +--- src/Mod/TechDraw/Gui/QGTracker.cpp | 5 +---- 11 files changed, 32 insertions(+), 64 deletions(-) diff --git a/src/Mod/TechDraw/App/AppTechDrawPy.cpp b/src/Mod/TechDraw/App/AppTechDrawPy.cpp index 4bb3fc72546d..05c3a7f9190e 100644 --- a/src/Mod/TechDraw/App/AppTechDrawPy.cpp +++ b/src/Mod/TechDraw/App/AppTechDrawPy.cpp @@ -835,8 +835,7 @@ class Module : public Py::ExtensionModule const TopoDS_Shape& shape = pShape->getTopoShapePtr()->getShape(); Base::Vector3d dir = static_cast(pcObjDir)->value(); Base::Vector3d centroid = ShapeUtils::findCentroidVec(shape, dir); - PyObject* result = nullptr; - result = new Base::VectorPy(new Base::Vector3d(centroid)); + PyObject* result = new Base::VectorPy(new Base::Vector3d(centroid)); return Py::asObject(result); } diff --git a/src/Mod/TechDraw/App/CosmeticExtension.cpp b/src/Mod/TechDraw/App/CosmeticExtension.cpp index 48c40af539b7..3bf122c2f5c2 100644 --- a/src/Mod/TechDraw/App/CosmeticExtension.cpp +++ b/src/Mod/TechDraw/App/CosmeticExtension.cpp @@ -205,8 +205,7 @@ std::string CosmeticExtension::addCosmeticVertex(const Base::Vector3d& pos, bool TechDraw::CosmeticVertex* cv = new TechDraw::CosmeticVertex(tempPos); verts.push_back(cv); CosmeticVertexes.setValues(verts); - std::string result = cv->getTagAsString(); - return result; + return cv->getTagAsString(); } /// retrieve a cosmetic vertex by unique id diff --git a/src/Mod/TechDraw/App/DrawBrokenView.cpp b/src/Mod/TechDraw/App/DrawBrokenView.cpp index 117510df5662..840bfdf4b8d6 100644 --- a/src/Mod/TechDraw/App/DrawBrokenView.cpp +++ b/src/Mod/TechDraw/App/DrawBrokenView.cpp @@ -240,11 +240,8 @@ TopoDS_Shape DrawBrokenView::apply1Break(const App::DocumentObject& breakObj, co TopoDS_Shape DrawBrokenView::compressShape(const TopoDS_Shape& shapeToCompress) const { // Base::Console().Message("DBV::compressShape()\n"); - TopoDS_Shape result; TopoDS_Shape compressed = compressHorizontal(shapeToCompress); - result = compressVertical(compressed); - - return result; + return compressVertical(compressed); } //! move the broken pieces in the input shape "right" to close up the removed areas. diff --git a/src/Mod/TechDraw/App/HatchLine.cpp b/src/Mod/TechDraw/App/HatchLine.cpp index 56ca50faec62..88b004174664 100644 --- a/src/Mod/TechDraw/App/HatchLine.cpp +++ b/src/Mod/TechDraw/App/HatchLine.cpp @@ -79,21 +79,19 @@ bool LineSet::isDashed() //! calculates the apparent start point (ie start of overlay line) for dashed lines Base::Vector3d LineSet::calcApparentStart(TechDraw::BaseGeomPtr g) { - Base::Vector3d result; Base::Vector3d start(g->getStartPoint().x, g->getStartPoint().y, 0.0); double angle = getPATLineSpec().getAngle(); if (angle == 0.0) { //horizontal - result = Base::Vector3d(getMinX(), start.y, 0.0); + return Base::Vector3d(getMinX(), start.y, 0.0); } else if ((angle == 90.0) || (angle == -90.0)) { //vertical - result = Base::Vector3d(start.x, getMinY(), 0.0); + return Base::Vector3d(start.x, getMinY(), 0.0); } else { double slope = getPATLineSpec().getSlope(); double y = getMinY(); double x = ((y - start.y) / slope) + start.x; - result = Base::Vector3d(x, y,0); + return Base::Vector3d(x, y,0); } - return result; } Base::Vector3d LineSet::getUnitDir() @@ -132,20 +130,18 @@ Base::Vector3d LineSet::getUnitOrtho() Base::Vector3d LineSet::findAtomStart() { - Base::Vector3d result; Base::Vector3d origin = getOrigin(); double angle = getAngle(); if (angle == 0.0) { - result = Base::Vector3d(getMinX(), origin.y, 0.0); + return Base::Vector3d(getMinX(), origin.y, 0.0); } else if ( (angle == 90.0) || (angle == -90.0) ) { - result = Base::Vector3d(origin.x, getMinY(), 0.0); + return Base::Vector3d(origin.x, getMinY(), 0.0); } else { double minY = getMinY(); double x = origin.x - (origin.y - minY)/getSlope(); - result = Base::Vector3d(x, minY, 0.0); + return Base::Vector3d(x, minY, 0.0); } - return result; } Base::Vector3d LineSet::getPatternStartPoint(TechDraw::BaseGeomPtr g, double &offset, double scale) diff --git a/src/Mod/TechDraw/App/LineGenerator.cpp b/src/Mod/TechDraw/App/LineGenerator.cpp index 8770c137f186..d793cee635a7 100644 --- a/src/Mod/TechDraw/App/LineGenerator.cpp +++ b/src/Mod/TechDraw/App/LineGenerator.cpp @@ -177,7 +177,6 @@ int LineGenerator::fromQtStyle(Qt::PenStyle style) { // Base::Console().Message("DLG::fromQtStyle(%d)\n", style); - int result { 0 }; // the 4 standard Qt::PenStyles and ISO128 equivalents int dashed = 2; int dotted = 7; @@ -199,29 +198,22 @@ int LineGenerator::fromQtStyle(Qt::PenStyle style) switch (style) { case Qt::NoPen: case Qt::SolidLine: - result = 1; - break; + return 1; case Qt::DashLine: - result = dashed; - break; + return dashed; case Qt::DotLine: - result = dotted; - break; + return dotted; case Qt::DashDotLine: - result = dashDot; - break; + return dashDot; case Qt::DashDotDotLine: - result = dashDotDot; - break; + return dashDotDot; case Qt::CustomDashLine: // not sure what to do here. we would have to match the custom pattern // to the patterns of the ISO lines and set the dash pattern accordingly. - result = 2; - break; + return 2; default: - result = 0; + return 0; } - return result; } diff --git a/src/Mod/TechDraw/App/Preferences.cpp b/src/Mod/TechDraw/App/Preferences.cpp index ef8f72e4f052..56cf903583b4 100644 --- a/src/Mod/TechDraw/App/Preferences.cpp +++ b/src/Mod/TechDraw/App/Preferences.cpp @@ -549,21 +549,16 @@ std::string Preferences::currentElementDefFile() int Preferences::LineCapStyle() { int currentIndex = LineCapIndex(); - int result{0x20}; - switch (currentIndex) { + switch (currentIndex) { case 0: - result = static_cast(0x20); //round; - break; + return static_cast(0x20); //round; case 1: - result = static_cast(0x10); //square; - break; + return static_cast(0x10); //square; case 2: - result = static_cast(0x00); //flat - break; + return static_cast(0x00); //flat default: - result = static_cast(0x20); + return static_cast(0x20); } - return result; } //! returns the line cap index without conversion to a Qt::PenCapStyle diff --git a/src/Mod/TechDraw/App/ShapeExtractor.cpp b/src/Mod/TechDraw/App/ShapeExtractor.cpp index 277d054ccc5c..99b74df52187 100644 --- a/src/Mod/TechDraw/App/ShapeExtractor.cpp +++ b/src/Mod/TechDraw/App/ShapeExtractor.cpp @@ -421,18 +421,17 @@ bool ShapeExtractor::is2dObject(const App::DocumentObject* obj) // just these for now bool ShapeExtractor::isEdgeType(const App::DocumentObject* obj) { - bool result = false; Base::Type t = obj->getTypeId(); if (t.isDerivedFrom(Part::Line::getClassTypeId()) ) { - result = true; + return true; } else if (t.isDerivedFrom(Part::Circle::getClassTypeId())) { - result = true; + return true; } else if (t.isDerivedFrom(Part::Ellipse::getClassTypeId())) { - result = true; + return true; } else if (t.isDerivedFrom(Part::RegularPolygon::getClassTypeId())) { - result = true; + return true; } - return result; + return false; } bool ShapeExtractor::isPointType(const App::DocumentObject* obj) diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index 3e344c9d21b9..e87c38a5a492 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -1061,8 +1061,6 @@ void MDIViewPage::removeUnselectedTreeSelection(QList sceneSelec bool MDIViewPage::compareSelections(std::vector treeSel, QList sceneSel) { - bool result = true; - if (treeSel.empty() && sceneSel.empty()) { return true; } @@ -1141,7 +1139,7 @@ bool MDIViewPage::compareSelections(std::vector treeSel, return false; } - return result; + return true; } ///////////////////end Selection Routines ////////////////////// diff --git a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp index 3e1a0c58c391..2b31f9b3614d 100644 --- a/src/Mod/TechDraw/Gui/QGILeaderLine.cpp +++ b/src/Mod/TechDraw/Gui/QGILeaderLine.cpp @@ -596,8 +596,7 @@ double QGILeaderLine::getLineWidth() TechDraw::DrawLeaderLine* QGILeaderLine::getLeaderFeature() { - TechDraw::DrawLeaderLine* result = static_cast(getViewObject()); - return result; + return static_cast(getViewObject()); } double QGILeaderLine::getEdgeFuzz() const @@ -637,12 +636,11 @@ void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt bool QGILeaderLine::useOldCoords() const { - bool result = false; auto vp = dynamic_cast(getViewProvider(getViewObject())); if (vp) { - result = vp->UseOldCoords.getValue(); + return vp->UseOldCoords.getValue(); } - return result; + return false; } diff --git a/src/Mod/TechDraw/Gui/QGIRichAnno.cpp b/src/Mod/TechDraw/Gui/QGIRichAnno.cpp index 77c698f2869b..494326b6237f 100644 --- a/src/Mod/TechDraw/Gui/QGIRichAnno.cpp +++ b/src/Mod/TechDraw/Gui/QGIRichAnno.cpp @@ -279,9 +279,7 @@ QString QGIRichAnno::convertTextSizes(const QString& inHtml) const TechDraw::DrawRichAnno* QGIRichAnno::getFeature() { - TechDraw::DrawRichAnno* result = - static_cast(getViewObject()); - return result; + return static_cast(getViewObject()); } diff --git a/src/Mod/TechDraw/Gui/QGTracker.cpp b/src/Mod/TechDraw/Gui/QGTracker.cpp index e0bd82671565..c32eb668846d 100644 --- a/src/Mod/TechDraw/Gui/QGTracker.cpp +++ b/src/Mod/TechDraw/Gui/QGTracker.cpp @@ -483,10 +483,7 @@ QColor QGTracker::getTrackerColor() double QGTracker::getTrackerWeight() { - double result = 1.0; - result = Preferences::getPreferenceGroup("Tracker")->GetFloat("TrackerWeight", 4.0); - - return result; + return Preferences::getPreferenceGroup("Tracker")->GetFloat("TrackerWeight", 4.0); } #include From 22782e53f31b0dee38e61203594d365cbd25c721 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 15 Nov 2024 12:24:20 +0100 Subject: [PATCH 030/161] Core: Add method ProjectFile::containsFile --- src/App/ProjectFile.cpp | 7 +++++++ src/App/ProjectFile.h | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/App/ProjectFile.cpp b/src/App/ProjectFile.cpp index b87fa0394f3d..28269368bc31 100644 --- a/src/App/ProjectFile.cpp +++ b/src/App/ProjectFile.cpp @@ -461,6 +461,13 @@ void ProjectFile::findFiles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, } } +bool ProjectFile::containsFile(const std::string& name) const +{ + zipios::ZipFile project(stdFile); + auto entry = project.getEntry(name); + return entry != nullptr; +} + std::list ProjectFile::getInputFiles(const std::string& name) const { // diff --git a/src/App/ProjectFile.h b/src/App/ProjectFile.h index f2423f7d08ec..597ccc72c89a 100644 --- a/src/App/ProjectFile.h +++ b/src/App/ProjectFile.h @@ -148,6 +148,11 @@ class AppExport ProjectFile * @see getInputFiles(). */ std::list getPropertyFiles(const std::string& name) const; + /** + * If the project file contains the file \a name true is returned and + * false otherwise + */ + bool containsFile(const std::string& name) const; /** * Retrieves a list of input file names referenced to the given object name. * This method does the same as @ref getPropertyFiles() unless that it only From 2819ca438e3776fdb675fbe061b95019b70940d4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 15 Nov 2024 12:39:49 +0100 Subject: [PATCH 031/161] Start: fixes #17857: Icon-files of the startup screen are not removed from /tmp It's basically a port of #10951 to the new start page implementation. Note: Icon files are not removed but re-used instead. The commit adds some new functions: * getThumbnailsImage() Returns the name of the PNG inside a project file * getThumbnailsName() Returns the directory name containing the image files * getThumnailsParentDir() Returns the parent directory of the directory containing the image files * getThumbnailsDir() Returns the path to the thumbnail directory. There is no need to always create a unique directory after each restart because it doesn't harm if the thumbnail directoy contains deprecated files. * createThumbnailsDir() Creates the thumbnail directoy if it doesn't exist yet. * getSha1Hash Helper function to compute a SHA-1 hash of a given path. If the same path is passed then the hash value will be the same. This way it can be avoided to create a different image file from a project file after each restart. * getUniquePNG Computes the path of a PNG image file for a given project file. It's also possible to pass an arbitrary string as argument. * useCachedPNG If the PNG image exists and if it's newer than the project file True is returned and False otherwise. For a given project file it is checked if the thumbnail directory already contains a cached image. If it's newer than the project file it will used, otherwise it will be re-created. Fix freecadCanOpen() abd DisplayedFilesModel::addFile() to also check for lower-case file extensions. --- src/Mod/Start/App/DisplayedFilesModel.cpp | 107 +++++++++++++++++++--- src/Mod/Start/App/PreCompiled.h | 6 ++ 2 files changed, 102 insertions(+), 11 deletions(-) diff --git a/src/Mod/Start/App/DisplayedFilesModel.cpp b/src/Mod/Start/App/DisplayedFilesModel.cpp index 85ef1ff3a60b..90fb26eeacca 100644 --- a/src/Mod/Start/App/DisplayedFilesModel.cpp +++ b/src/Mod/Start/App/DisplayedFilesModel.cpp @@ -23,7 +23,11 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include +#include +#include +#include #include #include #endif @@ -31,6 +35,8 @@ #include "DisplayedFilesModel.h" #include #include +#include +#include using namespace Start; @@ -80,6 +86,68 @@ FileStats fileInfoFromFreeCADFile(const std::string& path) return result; } +std::string getThumbnailsImage() +{ + return "thumbnails/Thumbnail.png"; +} + +QString getThumbnailsName() +{ + return QString::fromLatin1("FreeCADStartThumbnails"); +} + +QDir getThumnailsParentDir() +{ + return QDir::temp(); +} + +QString getThumbnailsDir() +{ + QDir dir = getThumnailsParentDir(); + return dir.absoluteFilePath(getThumbnailsName()); +} + +void createThumbnailsDir() +{ + QString name = getThumbnailsName(); + QDir dir(getThumnailsParentDir()); + if (!dir.exists(name)) { + dir.mkpath(name); + } +} + +QString getSha1Hash(const std::string& path) +{ + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(path.c_str(), static_cast(path.size())); + QByteArray ba1 = hash.result().toHex(); + hash.reset(); + hash.addData(ba1); + QByteArray ba2 = hash.result().toHex(); + return QString::fromLatin1(ba2); +} + +QString getUniquePNG(const std::string& path) +{ + QDir dir = getThumbnailsDir(); + QString sha1 = getSha1Hash(path) + QLatin1String(".png"); + return dir.absoluteFilePath(sha1); +} + +bool useCachedPNG(const std::string& image, const std::string& project) +{ + Base::FileInfo f1(image); + Base::FileInfo f2(project); + if (!f1.exists()) { + return false; + } + if (!f2.exists()) { + return false; + } + + return f1.lastModified() > f2.lastModified(); +} + /// Load the thumbnail image data (if any) that is stored in an FCStd file. /// \returns The image bytes, or an empty QByteArray (if no thumbnail was stored) QByteArray loadFCStdThumbnail(const std::string& pathToFCStdFile) @@ -87,9 +155,20 @@ QByteArray loadFCStdThumbnail(const std::string& pathToFCStdFile) App::ProjectFile proj(pathToFCStdFile); if (proj.loadDocument()) { try { - std::string thumbnailFile = proj.extractInputFile("thumbnails/Thumbnail.png"); - if (!thumbnailFile.empty()) { - auto inputFile = QFile(QString::fromStdString(thumbnailFile)); + std::string thumbnailFile = getUniquePNG(pathToFCStdFile).toStdString(); + if (!useCachedPNG(thumbnailFile, pathToFCStdFile)) { + static std::string thumb = getThumbnailsImage(); + if (proj.containsFile(thumb)) { + createThumbnailsDir(); + Base::FileInfo fi(thumbnailFile); + Base::ofstream str(fi); + proj.readInputFileDirect(thumb, str); + str.close(); + } + } + + auto inputFile = QFile(QString::fromStdString(thumbnailFile)); + if (inputFile.exists()) { inputFile.open(QIODevice::OpenModeFlag::ReadOnly); return inputFile.readAll(); } @@ -115,6 +194,19 @@ FileStats getFileInfo(const std::string& path) result.insert(std::make_pair(DisplayedFilesModelRoles::baseName, file.fileName())); return result; } + +bool freecadCanOpen(const QString& extension) +{ + std::string ext = extension.toStdString(); + auto importTypes = App::GetApplication().getImportTypes(); + return std::find_if(importTypes.begin(), + importTypes.end(), + [&ext](const auto& item) { + return boost::iequals(item, ext); + }) + != importTypes.end(); +} + } // namespace DisplayedFilesModel::DisplayedFilesModel(QObject* parent) @@ -177,13 +269,6 @@ QVariant DisplayedFilesModel::data(const QModelIndex& index, int roleAsInt) cons return {}; } -bool freecadCanOpen(const QString& extension) -{ - auto importTypes = App::GetApplication().getImportTypes(); - return std::find(importTypes.begin(), importTypes.end(), extension.toStdString()) - != importTypes.end(); -} - void DisplayedFilesModel::addFile(const QString& filePath) { QFileInfo qfi(filePath); @@ -194,7 +279,7 @@ void DisplayedFilesModel::addFile(const QString& filePath) return; } _fileInfoCache.emplace_back(getFileInfo(filePath.toStdString())); - if (qfi.completeSuffix() == QLatin1String("FCStd")) { + if (qfi.completeSuffix().toLower() == QLatin1String("fcstd")) { auto thumbnail = loadFCStdThumbnail(filePath.toStdString()); if (!thumbnail.isEmpty()) { _imageCache.insert(filePath, thumbnail); diff --git a/src/Mod/Start/App/PreCompiled.h b/src/Mod/Start/App/PreCompiled.h index acbd41c9450e..7359854941bb 100644 --- a/src/Mod/Start/App/PreCompiled.h +++ b/src/Mod/Start/App/PreCompiled.h @@ -42,7 +42,13 @@ #include #include +// boost +#include + // Qt (should never include GUI files, only QtCore) +#include +#include +#include #include #include #include From ee18317e0883f86b6c3498d68c2b37b6b6febfcd Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 19 Nov 2024 22:46:17 +0100 Subject: [PATCH 032/161] Part: Expose Geometry::isSame() to Python --- src/Mod/Part/App/GeometryPy.xml | 8 ++++++++ src/Mod/Part/App/GeometryPyImp.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Mod/Part/App/GeometryPy.xml b/src/Mod/Part/App/GeometryPy.xml index b8d5cc425f49..d2596606888c 100644 --- a/src/Mod/Part/App/GeometryPy.xml +++ b/src/Mod/Part/App/GeometryPy.xml @@ -53,6 +53,14 @@ It describes the common behavior of these objects when: Create a clone of this geometry with the same Tag + + + + isSame(geom, tol, angulartol) -> boolean + + Compare this geometry to another one + + Returns a boolean indicating whether a geometry extension of the type indicated as a string exists. diff --git a/src/Mod/Part/App/GeometryPyImp.cpp b/src/Mod/Part/App/GeometryPyImp.cpp index 095ef90d54c6..8cc3b907438a 100644 --- a/src/Mod/Part/App/GeometryPyImp.cpp +++ b/src/Mod/Part/App/GeometryPyImp.cpp @@ -203,6 +203,20 @@ PyObject* GeometryPy::clone(PyObject *args) return cpy; } +PyObject* GeometryPy::isSame(PyObject *args) +{ + PyObject* other {}; + double tol {}; + double angular {}; + if (!PyArg_ParseTuple(args, "O!dd", &GeometryPy::Type, &other, &tol, &angular)) { + return nullptr; + } + + Part::Geometry* geom = this->getGeometryPtr(); + bool same = geom->isSame(*static_cast(other)->getGeometryPtr(), tol, angular); + return Py::new_reference_to(Py::Boolean(same)); +} + PyObject* GeometryPy::setExtension(PyObject *args) { PyObject* o; From 4e82a0af4863363dd9e31e9660fb66ae7383bc23 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 15 Nov 2024 17:43:49 +0100 Subject: [PATCH 033/161] App: Apply clang format (part 1) --- src/App/Annotation.cpp | 2 +- src/App/Annotation.h | 14 +- src/App/ApplicationPy.cpp | 765 ++++++++++++++-------- src/App/AutoTransaction.cpp | 187 +++--- src/App/AutoTransaction.h | 29 +- src/App/Branding.cpp | 17 +- src/App/Branding.h | 9 +- src/App/CleanupProcess.cpp | 2 +- src/App/CleanupProcess.h | 2 +- src/App/ComplexGeoDataPyImp.cpp | 132 ++-- src/App/DocumentObjectExtension.cpp | 54 +- src/App/DocumentObjectExtension.h | 66 +- src/App/DocumentObjectExtensionPy.xml | 16 +- src/App/DocumentObjectExtensionPyImp.cpp | 4 +- src/App/DocumentObjectFileIncluded.cpp | 7 +- src/App/DocumentObjectFileIncluded.h | 10 +- src/App/DocumentObjectGroup.cpp | 28 +- src/App/DocumentObjectGroup.h | 12 +- src/App/DocumentObjectGroupPy.xml | 16 +- src/App/DocumentObjectGroupPyImp.cpp | 3 +- src/App/DocumentObjectPy.xml | 26 +- src/App/DocumentObjectPyImp.cpp | 544 +++++++++------ src/App/DocumentObserver.cpp | 437 ++++++------ src/App/DocumentObserver.h | 137 ++-- src/App/DocumentObserverPython.cpp | 193 +++--- src/App/DocumentObserverPython.h | 20 +- src/App/DocumentPyImp.cpp | 561 ++++++++++------ src/App/DynamicProperty.cpp | 247 ++++--- src/App/DynamicProperty.h | 128 ++-- src/App/ElementMap.cpp | 165 +++-- src/App/ElementMap.h | 76 ++- src/App/ElementNamingUtils.cpp | 107 +-- src/App/ElementNamingUtils.h | 12 +- src/App/Enumeration.cpp | 117 ++-- src/App/Enumeration.h | 310 ++++----- src/App/Extension.cpp | 138 ++-- src/App/ExtensionContainer.cpp | 334 ++++++---- src/App/ExtensionContainer.h | 140 ++-- src/App/ExtensionContainerPy.xml | 16 +- src/App/ExtensionContainerPyImp.cpp | 114 ++-- src/App/ExtensionPy.xml | 16 +- src/App/ExtensionPyImp.cpp | 4 +- src/App/ExtensionPython.h | 113 ++-- src/App/FeatureCustom.h | 40 +- src/App/FeaturePython.cpp | 338 +++++----- src/App/FeaturePython.h | 353 +++++----- src/App/FreeCADTest.py | 49 +- src/App/GeoFeatureGroupExtension.cpp | 360 ++++++---- src/App/GeoFeatureGroupExtension.h | 102 +-- src/App/GeoFeatureGroupExtensionPyImp.cpp | 4 +- src/App/GeoFeaturePyImp.cpp | 30 +- src/App/Graphviz.cpp | 396 ++++++----- src/App/GroupExtension.cpp | 315 +++++---- src/App/GroupExtension.h | 95 +-- src/App/GroupExtensionPy.xml | 16 +- src/App/GroupExtensionPyImp.cpp | 148 +++-- src/App/ImagePlane.cpp | 6 +- src/App/ImagePlane.h | 17 +- src/App/IndexedName.cpp | 33 +- src/App/IndexedName.h | 106 +-- src/App/InventorObject.cpp | 14 +- src/App/InventorObject.h | 14 +- src/App/License.h | 4 +- src/App/MappedElement.cpp | 13 +- src/App/MappedElement.h | 28 +- src/App/MappedName.cpp | 46 +- src/App/MappedName.h | 24 +- src/App/MaterialObject.cpp | 12 +- src/App/MaterialObject.h | 10 +- src/App/MeasureManager.cpp | 283 ++++---- src/App/MeasureManager.h | 46 +- src/App/MeasureManagerPyImp.cpp | 12 +- src/App/MergeDocuments.cpp | 56 +- src/App/MergeDocuments.h | 49 +- src/App/Metadata.cpp | 115 ++-- src/App/Metadata.h | 327 ++++----- src/App/MetadataPyImp.cpp | 579 +++++++++------- src/App/Origin.cpp | 198 +++--- src/App/Origin.h | 82 ++- src/App/OriginFeature.cpp | 24 +- src/App/OriginFeature.h | 19 +- src/App/OriginGroupExtension.cpp | 237 ++++--- src/App/OriginGroupExtension.h | 36 +- src/App/OriginGroupExtensionPy.xml | 1 - src/App/OriginGroupExtensionPyImp.cpp | 4 +- src/App/Part.cpp | 69 +- src/App/Part.h | 43 +- src/App/PartPyImp.cpp | 3 +- src/App/Path.cpp | 7 +- src/App/Path.h | 11 +- src/App/Placement.cpp | 16 +- src/App/Placement.h | 21 +- src/App/PreCompiled.cpp | 1 - src/App/PreCompiled.h | 29 +- src/App/ProgramOptionsUtilities.h | 57 +- src/App/ProjectFile.cpp | 57 +- src/App/ProjectFile.h | 9 +- src/App/Range.cpp | 137 ++-- src/App/Range.h | 180 +++-- src/App/Resources/translations/App_hr.ts | 2 +- src/App/Resources/translations/App_tr.ts | 2 +- src/App/SafeMode.cpp | 13 +- src/App/SafeMode.h | 11 +- src/App/StringHasher.cpp | 18 +- src/App/StringHasher.h | 47 +- src/App/StringHasherPy.xml | 19 +- src/App/StringHasherPyImp.cpp | 77 +-- src/App/StringIDPy.xml | 17 +- src/App/StringIDPyImp.cpp | 54 +- src/App/SuppressibleExtension.cpp | 18 +- src/App/SuppressibleExtension.h | 17 +- src/App/SuppressibleExtensionPyImp.cpp | 2 +- src/App/TextDocument.cpp | 14 +- src/App/TextDocument.h | 12 +- src/App/TransactionalObject.cpp | 3 +- src/App/TransactionalObject.h | 9 +- src/App/Transactions.cpp | 201 +++--- src/App/Transactions.h | 80 +-- src/App/VRMLObject.cpp | 43 +- src/App/VRMLObject.h | 28 +- src/App/VarSet.cpp | 1 - src/App/VarSet.h | 9 +- src/App/core-app.dox | 1 - src/App/private/DocumentP.h | 90 +-- 124 files changed, 6623 insertions(+), 4776 deletions(-) diff --git a/src/App/Annotation.cpp b/src/App/Annotation.cpp index ad5ac9134a35..fc620feb68ef 100644 --- a/src/App/Annotation.cpp +++ b/src/App/Annotation.cpp @@ -45,7 +45,7 @@ PROPERTY_SOURCE(App::AnnotationLabel, App::DocumentObject) AnnotationLabel::AnnotationLabel() { - ADD_PROPERTY_TYPE(LabelText, (""), "Label",Prop_Output, "Text label of the annotation"); + ADD_PROPERTY_TYPE(LabelText, (""), "Label", Prop_Output, "Text label of the annotation"); ADD_PROPERTY_TYPE(BasePosition, (Base::Vector3d()), "Label", Prop_Output, "Base position"); ADD_PROPERTY_TYPE(TextPosition, (Base::Vector3d()), "Label", Prop_Output, "Text position"); } diff --git a/src/App/Annotation.h b/src/App/Annotation.h index 4595ae0b5836..7fabb50fea15 100644 --- a/src/App/Annotation.h +++ b/src/App/Annotation.h @@ -32,7 +32,7 @@ namespace App { -class AppExport Annotation : public DocumentObject +class AppExport Annotation: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::Annotation); @@ -45,12 +45,13 @@ class AppExport Annotation : public DocumentObject App::PropertyVector Position; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderAnnotation"; } }; -class AppExport AnnotationLabel : public DocumentObject +class AppExport AnnotationLabel: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::AnnotationLabel); @@ -64,12 +65,13 @@ class AppExport AnnotationLabel : public DocumentObject App::PropertyVector TextPosition; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderAnnotationLabel"; } }; -} //namespace App +} // namespace App -#endif // APP_ANNOTATION_H +#endif // APP_ANNOTATION_H diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index cfa9621103aa..7303d7e56c15 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -38,7 +38,7 @@ #include "DocumentObjectPy.h" -//using Base::GetConsole; +// using Base::GetConsole; using namespace Base; using namespace App; @@ -48,118 +48,191 @@ using namespace App; // Application methods structure PyMethodDef Application::Methods[] = { - {"ParamGet", (PyCFunction) Application::sGetParam, METH_VARARGS, - "Get parameters by path"}, - {"saveParameter", (PyCFunction) Application::sSaveParameter, METH_VARARGS, + {"ParamGet", (PyCFunction)Application::sGetParam, METH_VARARGS, "Get parameters by path"}, + {"saveParameter", + (PyCFunction)Application::sSaveParameter, + METH_VARARGS, "saveParameter(config='User parameter') -> None\n" "Save parameter set to file. The default set is 'User parameter'"}, - {"Version", (PyCFunction) Application::sGetVersion, METH_VARARGS, + {"Version", + (PyCFunction)Application::sGetVersion, + METH_VARARGS, "Print the version to the output."}, - {"ConfigGet", (PyCFunction) Application::sGetConfig, METH_VARARGS, + {"ConfigGet", + (PyCFunction)Application::sGetConfig, + METH_VARARGS, "ConfigGet(string) -- Get the value for the given key."}, - {"ConfigSet", (PyCFunction) Application::sSetConfig, METH_VARARGS, + {"ConfigSet", + (PyCFunction)Application::sSetConfig, + METH_VARARGS, "ConfigSet(string, string) -- Set the given key to the given value."}, - {"ConfigDump", (PyCFunction) Application::sDumpConfig, METH_VARARGS, + {"ConfigDump", + (PyCFunction)Application::sDumpConfig, + METH_VARARGS, "Dump the configuration to the output."}, - {"addImportType", (PyCFunction) Application::sAddImportType, METH_VARARGS, + {"addImportType", + (PyCFunction)Application::sAddImportType, + METH_VARARGS, "Register filetype for import"}, - {"changeImportModule", (PyCFunction) Application::sChangeImportModule, METH_VARARGS, + {"changeImportModule", + (PyCFunction)Application::sChangeImportModule, + METH_VARARGS, "Change the import module name of a registered filetype"}, - {"getImportType", (PyCFunction) Application::sGetImportType, METH_VARARGS, + {"getImportType", + (PyCFunction)Application::sGetImportType, + METH_VARARGS, "Get the name of the module that can import the filetype"}, - {"addExportType", (PyCFunction) Application::sAddExportType, METH_VARARGS, + {"addExportType", + (PyCFunction)Application::sAddExportType, + METH_VARARGS, "Register filetype for export"}, - {"changeExportModule", (PyCFunction) Application::sChangeExportModule, METH_VARARGS, + {"changeExportModule", + (PyCFunction)Application::sChangeExportModule, + METH_VARARGS, "Change the export module name of a registered filetype"}, - {"getExportType", (PyCFunction) Application::sGetExportType, METH_VARARGS, + {"getExportType", + (PyCFunction)Application::sGetExportType, + METH_VARARGS, "Get the name of the module that can export the filetype"}, - {"getResourceDir", (PyCFunction) Application::sGetResourcePath, METH_VARARGS, + {"getResourceDir", + (PyCFunction)Application::sGetResourcePath, + METH_VARARGS, "Get the root directory of all resources"}, - {"getLibraryDir", (PyCFunction) Application::sGetLibraryPath, METH_VARARGS, + {"getLibraryDir", + (PyCFunction)Application::sGetLibraryPath, + METH_VARARGS, "Get the directory of all extension modules"}, - {"getTempPath", (PyCFunction) Application::sGetTempPath, METH_VARARGS, + {"getTempPath", + (PyCFunction)Application::sGetTempPath, + METH_VARARGS, "Get the root directory of cached files"}, - {"getUserCachePath", (PyCFunction) Application::sGetUserCachePath, METH_VARARGS, + {"getUserCachePath", + (PyCFunction)Application::sGetUserCachePath, + METH_VARARGS, "Get the root path of cached files"}, - {"getUserConfigDir", (PyCFunction) Application::sGetUserConfigPath, METH_VARARGS, + {"getUserConfigDir", + (PyCFunction)Application::sGetUserConfigPath, + METH_VARARGS, "Get the root path of user config files"}, - {"getUserAppDataDir", (PyCFunction) Application::sGetUserAppDataPath, METH_VARARGS, + {"getUserAppDataDir", + (PyCFunction)Application::sGetUserAppDataPath, + METH_VARARGS, "Get the root directory of application data"}, - {"getUserMacroDir", (PyCFunction) Application::sGetUserMacroPath, METH_VARARGS, + {"getUserMacroDir", + (PyCFunction)Application::sGetUserMacroPath, + METH_VARARGS, "getUserMacroDir(bool=False) -> str\n\n" "Get the directory of the user's macro directory\n" "If parameter is False (the default) it returns the standard path in the" "user's home directory, otherwise it returns the user-defined path."}, - {"getHelpDir", (PyCFunction) Application::sGetHelpPath, METH_VARARGS, + {"getHelpDir", + (PyCFunction)Application::sGetHelpPath, + METH_VARARGS, "Get the directory of the documentation"}, - {"getHomePath", (PyCFunction) Application::sGetHomePath, METH_VARARGS, + {"getHomePath", + (PyCFunction)Application::sGetHomePath, + METH_VARARGS, "Get the home path, i.e. the parent directory of the executable"}, - {"loadFile", (PyCFunction) Application::sLoadFile, METH_VARARGS, + {"loadFile", + (PyCFunction)Application::sLoadFile, + METH_VARARGS, "loadFile(string=filename,[string=module]) -> None\n\n" "Loads an arbitrary file by delegating to the given Python module:\n" "* If no module is given it will be determined by the file extension.\n" "* If more than one module can load a file the first one will be taken.\n" "* If no module exists to load the file an exception will be raised."}, - {"open", reinterpret_cast(reinterpret_cast( Application::sOpenDocument )), METH_VARARGS|METH_KEYWORDS, + {"open", + reinterpret_cast(reinterpret_cast(Application::sOpenDocument)), + METH_VARARGS | METH_KEYWORDS, "See openDocument(string)"}, - {"openDocument", reinterpret_cast(reinterpret_cast( Application::sOpenDocument )), METH_VARARGS|METH_KEYWORDS, + {"openDocument", + reinterpret_cast(reinterpret_cast(Application::sOpenDocument)), + METH_VARARGS | METH_KEYWORDS, "openDocument(filepath,hidden=False) -> object\n" "Create a document and load the project file into the document.\n\n" "filepath: file path to an existing file. If the file doesn't exist\n" " or the file cannot be loaded an I/O exception is thrown.\n" " In this case the document is kept alive.\n" "hidden: whether to hide document 3D view."}, -// {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS, -// "saveDocument(string) -- Save the document to a file."}, -// {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS}, - {"newDocument", reinterpret_cast(reinterpret_cast( Application::sNewDocument )), METH_VARARGS|METH_KEYWORDS, + // {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS, + // "saveDocument(string) -- Save the document to a file."}, + // {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS}, + {"newDocument", + reinterpret_cast(reinterpret_cast(Application::sNewDocument)), + METH_VARARGS | METH_KEYWORDS, "newDocument(name, label=None, hidden=False, temp=False) -> object\n" "Create a new document with a given name.\n\n" "name: unique document name which is checked automatically.\n" "label: optional user changeable label for the document.\n" "hidden: whether to hide document 3D view.\n" "temp: mark the document as temporary so that it will not be saved"}, - {"closeDocument", (PyCFunction) Application::sCloseDocument, METH_VARARGS, + {"closeDocument", + (PyCFunction)Application::sCloseDocument, + METH_VARARGS, "closeDocument(string) -> None\n\n" "Close the document with a given name."}, - {"activeDocument", (PyCFunction) Application::sActiveDocument, METH_VARARGS, + {"activeDocument", + (PyCFunction)Application::sActiveDocument, + METH_VARARGS, "activeDocument() -> object or None\n\n" "Return the active document or None if there is no one."}, - {"setActiveDocument", (PyCFunction) Application::sSetActiveDocument, METH_VARARGS, + {"setActiveDocument", + (PyCFunction)Application::sSetActiveDocument, + METH_VARARGS, "setActiveDocement(string) -> None\n\n" "Set the active document by its name."}, - {"getDocument", (PyCFunction) Application::sGetDocument, METH_VARARGS, + {"getDocument", + (PyCFunction)Application::sGetDocument, + METH_VARARGS, "getDocument(string) -> object\n\n" "Get a document by its name or raise an exception\n" "if there is no document with the given name."}, - {"listDocuments", (PyCFunction) Application::sListDocuments, METH_VARARGS, + {"listDocuments", + (PyCFunction)Application::sListDocuments, + METH_VARARGS, "listDocuments(sort=False) -> list\n\n" "Return a list of names of all documents, optionally sort in dependency order."}, - {"addDocumentObserver", (PyCFunction) Application::sAddDocObserver, METH_VARARGS, + {"addDocumentObserver", + (PyCFunction)Application::sAddDocObserver, + METH_VARARGS, "addDocumentObserver() -> None\n\n" "Add an observer to get notified about changes on documents."}, - {"removeDocumentObserver", (PyCFunction) Application::sRemoveDocObserver, METH_VARARGS, + {"removeDocumentObserver", + (PyCFunction)Application::sRemoveDocObserver, + METH_VARARGS, "removeDocumentObserver() -> None\n\n" "Remove an added document observer."}, - {"setLogLevel", (PyCFunction) Application::sSetLogLevel, METH_VARARGS, + {"setLogLevel", + (PyCFunction)Application::sSetLogLevel, + METH_VARARGS, "setLogLevel(tag, level) -- Set the log level for a string tag.\n" "'level' can either be string 'Log', 'Msg', 'Wrn', 'Error', or an integer value"}, - {"getLogLevel", (PyCFunction) Application::sGetLogLevel, METH_VARARGS, + {"getLogLevel", + (PyCFunction)Application::sGetLogLevel, + METH_VARARGS, "getLogLevel(tag) -- Get the log level of a string tag"}, - {"checkLinkDepth", (PyCFunction) Application::sCheckLinkDepth, METH_VARARGS, + {"checkLinkDepth", + (PyCFunction)Application::sCheckLinkDepth, + METH_VARARGS, "checkLinkDepth(depth) -- check link recursion depth"}, - {"getLinksTo", (PyCFunction) Application::sGetLinksTo, METH_VARARGS, + {"getLinksTo", + (PyCFunction)Application::sGetLinksTo, + METH_VARARGS, "getLinksTo(obj,options=0,maxCount=0) -- return the objects linked to 'obj'\n\n" "options: 1: recursive, 2: check link array. Options can combine.\n" "maxCount: to limit the number of links returned\n"}, - {"getDependentObjects", (PyCFunction) Application::sGetDependentObjects, METH_VARARGS, + {"getDependentObjects", + (PyCFunction)Application::sGetDependentObjects, + METH_VARARGS, "getDependentObjects(obj|[obj,...], options=0)\n" "Return a list of dependent objects including the given objects.\n\n" "options: can have the following bit flags,\n" " 1: to sort the list in topological order.\n" " 2: to exclude dependency of Link type object."}, - {"setActiveTransaction", (PyCFunction) Application::sSetActiveTransaction, METH_VARARGS, + {"setActiveTransaction", + (PyCFunction)Application::sSetActiveTransaction, + METH_VARARGS, "setActiveTransaction(name, persist=False) -- setup active transaction with the given name\n\n" "name: the transaction name\n" "persist(False): by default, if the calling code is inside any invocation of a command, it\n" @@ -168,15 +241,23 @@ PyMethodDef Application::Methods[] = { "Returns the transaction ID for the active transaction. An application-wide\n" "active transaction causes any document changes to open a transaction with\n" "the given name and ID."}, - {"getActiveTransaction", (PyCFunction) Application::sGetActiveTransaction, METH_VARARGS, + {"getActiveTransaction", + (PyCFunction)Application::sGetActiveTransaction, + METH_VARARGS, "getActiveTransaction() -> (name,id)\n\n" "return the current active transaction name and ID"}, - {"closeActiveTransaction", (PyCFunction) Application::sCloseActiveTransaction, METH_VARARGS, + {"closeActiveTransaction", + (PyCFunction)Application::sCloseActiveTransaction, + METH_VARARGS, "closeActiveTransaction(abort=False) -- commit or abort current active transaction"}, - {"isRestoring", (PyCFunction) Application::sIsRestoring, METH_VARARGS, + {"isRestoring", + (PyCFunction)Application::sIsRestoring, + METH_VARARGS, "isRestoring() -> bool\n\n" "Test if the application is opening some document"}, - {"checkAbort", (PyCFunction) Application::sCheckAbort, METH_VARARGS, + {"checkAbort", + (PyCFunction)Application::sCheckAbort, + METH_VARARGS, "checkAbort() -- check for user abort in length operation.\n\n" "This only works if there is an active sequencer (or ProgressIndicator in Python).\n" "There is an active sequencer during document restore and recomputation. User may\n" @@ -186,13 +267,14 @@ PyMethodDef Application::Methods[] = { }; -PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args) +PyObject* Application::sLoadFile(PyObject* /*self*/, PyObject* args) { - const char *path; - const char *doc=""; - const char *mod=""; - if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod)) + const char* path; + const char* doc = ""; + const char* mod = ""; + if (!PyArg_ParseTuple(args, "s|ss", &path, &doc, &mod)) { return nullptr; + } try { Base::FileInfo fi(path); if (!fi.isFile() || !fi.exists()) { @@ -215,16 +297,18 @@ PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args) // path could contain characters that need escaping, such as quote signs // therefore use its representation in the Python code string - PyObject *pathObj = PyUnicode_FromString(path); - PyObject *pathReprObj = PyObject_Repr(pathObj); - const char *pathRepr = PyUnicode_AsUTF8(pathReprObj); + PyObject* pathObj = PyUnicode_FromString(path); + PyObject* pathReprObj = PyObject_Repr(pathObj); + const char* pathRepr = PyUnicode_AsUTF8(pathReprObj); std::stringstream str; str << "import " << module << std::endl; - if (fi.hasExtension("FCStd")) + if (fi.hasExtension("FCStd")) { str << module << ".openDocument(" << pathRepr << ")" << std::endl; - else + } + else { str << module << ".insert(" << pathRepr << ",'" << doc << "')" << std::endl; + } Py_DECREF(pathObj); Py_DECREF(pathReprObj); @@ -243,26 +327,36 @@ PyObject* Application::sLoadFile(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sIsRestoring(PyObject * /*self*/, PyObject *args) { - if (!PyArg_ParseTuple(args, "")) +PyObject* Application::sIsRestoring(PyObject* /*self*/, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } return Py::new_reference_to(Py::Boolean(GetApplication().isRestoring())); } -PyObject* Application::sOpenDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd) +PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) { char* Name; - PyObject *hidden = Py_False; - static const std::array kwlist {"name", "hidden", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "et|O!", kwlist, - "utf-8", &Name, &PyBool_Type, &hidden)) { + PyObject* hidden = Py_False; + static const std::array kwlist {"name", "hidden", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "et|O!", + kwlist, + "utf-8", + &Name, + &PyBool_Type, + &hidden)) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); try { // return new document - return (GetApplication().openDocument(EncodedName.c_str(), !Base::asBoolean(hidden))->getPyObject()); + return (GetApplication() + .openDocument(EncodedName.c_str(), !Base::asBoolean(hidden)) + ->getPyObject()); } catch (const Base::Exception& e) { PyErr_SetString(PyExc_IOError, e.what()); @@ -275,31 +369,47 @@ PyObject* Application::sOpenDocument(PyObject * /*self*/, PyObject *args, PyObje } } -PyObject* Application::sNewDocument(PyObject * /*self*/, PyObject *args, PyObject *kwd) +PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) { - char *docName = nullptr; - char *usrName = nullptr; - PyObject *hidden = Py_False; - PyObject *temp = Py_False; - static const std::array kwlist {"name", "label", "hidden", "temp", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|etetO!O!", kwlist, - "utf-8", &docName, "utf-8", &usrName, &PyBool_Type, &hidden, &PyBool_Type, &temp)) { + char* docName = nullptr; + char* usrName = nullptr; + PyObject* hidden = Py_False; + PyObject* temp = Py_False; + static const std::array kwlist {"name", "label", "hidden", "temp", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "|etetO!O!", + kwlist, + "utf-8", + &docName, + "utf-8", + &usrName, + &PyBool_Type, + &hidden, + &PyBool_Type, + &temp)) { return nullptr; } - PY_TRY { - App::Document* doc = GetApplication().newDocument(docName, usrName, !Base::asBoolean(hidden), Base::asBoolean(temp)); + PY_TRY + { + App::Document* doc = GetApplication().newDocument(docName, + usrName, + !Base::asBoolean(hidden), + Base::asBoolean(temp)); PyMem_Free(docName); PyMem_Free(usrName); return doc->getPyObject(); - }PY_CATCH; + } + PY_CATCH; } -PyObject* Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSetActiveDocument(PyObject* /*self*/, PyObject* args) { - char *pstr = nullptr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr = nullptr; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } try { GetApplication().setActiveDocument(pstr); @@ -312,11 +422,12 @@ PyObject* Application::sSetActiveDocument(PyObject * /*self*/, PyObject *args) Py_Return; } -PyObject* Application::sCloseDocument(PyObject * /*self*/, PyObject *args) +PyObject* Application::sCloseDocument(PyObject* /*self*/, PyObject* args) { - char *pstr = nullptr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr = nullptr; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } Document* doc = GetApplication().getDocument(pstr); if (!doc) { @@ -336,14 +447,15 @@ PyObject* Application::sCloseDocument(PyObject * /*self*/, PyObject *args) Py_Return; } -PyObject* Application::sSaveDocument(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSaveDocument(PyObject* /*self*/, PyObject* args) { - char *pDoc; - if (!PyArg_ParseTuple(args, "s", &pDoc)) + char* pDoc; + if (!PyArg_ParseTuple(args, "s", &pDoc)) { return nullptr; + } Document* doc = GetApplication().getDocument(pDoc); - if ( doc ) { + if (doc) { if (!doc->save()) { PyErr_Format(Base::PyExc_FC_GeneralError, "Cannot save document '%s'", pDoc); return nullptr; @@ -357,10 +469,11 @@ PyObject* Application::sSaveDocument(PyObject * /*self*/, PyObject *args) Py_Return; } -PyObject* Application::sActiveDocument(PyObject * /*self*/, PyObject *args) +PyObject* Application::sActiveDocument(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } Document* doc = GetApplication().getActiveDocument(); if (doc) { @@ -372,14 +485,15 @@ PyObject* Application::sActiveDocument(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetDocument(PyObject* /*self*/, PyObject* args) { - char *pstr=nullptr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr = nullptr; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } Document* doc = GetApplication().getDocument(pstr); - if ( !doc ) { + if (!doc) { PyErr_Format(PyExc_NameError, "Unknown document '%s'", pstr); return nullptr; } @@ -387,24 +501,29 @@ PyObject* Application::sGetDocument(PyObject * /*self*/, PyObject *args) return doc->getPyObject(); } -PyObject* Application::sGetParam(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetParam(PyObject* /*self*/, PyObject* args) { - char *pstr=nullptr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr = nullptr; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } - PY_TRY { + PY_TRY + { return GetPyObject(GetApplication().GetParameterGroupByPath(pstr)); - }PY_CATCH; + } + PY_CATCH; } -PyObject* Application::sSaveParameter(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSaveParameter(PyObject* /*self*/, PyObject* args) { - const char *pstr = "User parameter"; - if (!PyArg_ParseTuple(args, "|s", &pstr)) + const char* pstr = "User parameter"; + if (!PyArg_ParseTuple(args, "|s", &pstr)) { return nullptr; + } - PY_TRY { + PY_TRY + { ParameterManager* param = App::GetApplication().GetParameterSet(pstr); if (!param) { std::stringstream str; @@ -422,16 +541,18 @@ PyObject* Application::sSaveParameter(PyObject * /*self*/, PyObject *args) param->SaveDocument(); Py_INCREF(Py_None); return Py_None; - }PY_CATCH; + } + PY_CATCH; } -PyObject* Application::sGetConfig(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetConfig(PyObject* /*self*/, PyObject* args) { - char *pstr; + char* pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } const std::map& Map = GetApplication().Config(); std::map::const_iterator it = Map.find(pstr); @@ -444,24 +565,26 @@ PyObject* Application::sGetConfig(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sDumpConfig(PyObject * /*self*/, PyObject *args) +PyObject* Application::sDumpConfig(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - PyObject *dict = PyDict_New(); - for (const auto & It : GetApplication()._mConfig) { + PyObject* dict = PyDict_New(); + for (const auto& It : GetApplication()._mConfig) { PyDict_SetItemString(dict, It.first.c_str(), PyUnicode_FromString(It.second.c_str())); } return dict; } -PyObject* Application::sSetConfig(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSetConfig(PyObject* /*self*/, PyObject* args) { char *pstr, *pstr2; - if (!PyArg_ParseTuple(args, "ss", &pstr, &pstr2)) + if (!PyArg_ParseTuple(args, "ss", &pstr, &pstr2)) { return nullptr; + } GetApplication()._mConfig[pstr] = pstr2; @@ -469,10 +592,11 @@ PyObject* Application::sSetConfig(PyObject * /*self*/, PyObject *args) return Py_None; } -PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetVersion(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } Py::List list; const std::map& cfg = Application::Config(); @@ -497,51 +621,56 @@ PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args) list.append(Py::String(it != cfg.end() ? it->second : "")); it = cfg.find("BuildRevisionBranch"); - if (it != cfg.end()) + if (it != cfg.end()) { list.append(Py::String(it->second)); + } it = cfg.find("BuildRevisionHash"); - if (it != cfg.end()) + if (it != cfg.end()) { list.append(Py::String(it->second)); + } return Py::new_reference_to(list); } -PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args) +PyObject* Application::sAddImportType(PyObject* /*self*/, PyObject* args) { - char *psKey,*psMod; + char *psKey, *psMod; - if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod)) + if (!PyArg_ParseTuple(args, "ss", &psKey, &psMod)) { return nullptr; + } - GetApplication().addImportType(psKey,psMod); + GetApplication().addImportType(psKey, psMod); Py_Return; } -PyObject* Application::sChangeImportModule(PyObject * /*self*/, PyObject *args) +PyObject* Application::sChangeImportModule(PyObject* /*self*/, PyObject* args) { - char *key,*oldMod,*newMod; + char *key, *oldMod, *newMod; - if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod)) + if (!PyArg_ParseTuple(args, "sss", &key, &oldMod, &newMod)) { return nullptr; + } - GetApplication().changeImportModule(key,oldMod,newMod); + GetApplication().changeImportModule(key, oldMod, newMod); Py_Return; } -PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetImportType(PyObject* /*self*/, PyObject* args) { - char* psKey=nullptr; + char* psKey = nullptr; - if (!PyArg_ParseTuple(args, "|s", &psKey)) + if (!PyArg_ParseTuple(args, "|s", &psKey)) { return nullptr; + } if (psKey) { Py::List list; std::vector modules = GetApplication().getImportModules(psKey); - for (const auto & it : modules) { + for (const auto& it : modules) { list.append(Py::String(it)); } @@ -550,7 +679,7 @@ PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args) else { Py::Dict dict; std::vector types = GetApplication().getImportTypes(); - for (const auto & it : types) { + for (const auto& it : types) { std::vector modules = GetApplication().getImportModules(it.c_str()); if (modules.empty()) { dict.setItem(it.c_str(), Py::None()); @@ -560,7 +689,7 @@ PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args) } else { Py::List list; - for (const auto & jt : modules) { + for (const auto& jt : modules) { list.append(Py::String(jt)); } dict.setItem(it.c_str(), list); @@ -571,41 +700,44 @@ PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sAddExportType(PyObject * /*self*/, PyObject *args) +PyObject* Application::sAddExportType(PyObject* /*self*/, PyObject* args) { - char *psKey,*psMod; + char *psKey, *psMod; - if (!PyArg_ParseTuple(args, "ss", &psKey,&psMod)) + if (!PyArg_ParseTuple(args, "ss", &psKey, &psMod)) { return nullptr; + } - GetApplication().addExportType(psKey,psMod); + GetApplication().addExportType(psKey, psMod); Py_Return; } -PyObject* Application::sChangeExportModule(PyObject * /*self*/, PyObject *args) +PyObject* Application::sChangeExportModule(PyObject* /*self*/, PyObject* args) { - char *key,*oldMod,*newMod; + char *key, *oldMod, *newMod; - if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod)) + if (!PyArg_ParseTuple(args, "sss", &key, &oldMod, &newMod)) { return nullptr; + } - GetApplication().changeExportModule(key,oldMod,newMod); + GetApplication().changeExportModule(key, oldMod, newMod); Py_Return; } -PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetExportType(PyObject* /*self*/, PyObject* args) { - char* psKey=nullptr; + char* psKey = nullptr; - if (!PyArg_ParseTuple(args, "|s", &psKey)) + if (!PyArg_ParseTuple(args, "|s", &psKey)) { return nullptr; + } if (psKey) { Py::List list; std::vector modules = GetApplication().getExportModules(psKey); - for (const auto & it : modules) { + for (const auto& it : modules) { list.append(Py::String(it)); } @@ -614,7 +746,7 @@ PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args) else { Py::Dict dict; std::vector types = GetApplication().getExportTypes(); - for (const auto & it : types) { + for (const auto& it : types) { std::vector modules = GetApplication().getExportModules(it.c_str()); if (modules.empty()) { dict.setItem(it.c_str(), Py::None()); @@ -624,7 +756,7 @@ PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args) } else { Py::List list; - for (const auto & jt : modules) { + for (const auto& jt : modules) { list.append(Py::String(jt)); } dict.setItem(it.c_str(), list); @@ -635,112 +767,125 @@ PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sGetResourcePath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetResourcePath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String datadir(Application::getResourceDir(),"utf-8"); + Py::String datadir(Application::getResourceDir(), "utf-8"); return Py::new_reference_to(datadir); } -PyObject* Application::sGetLibraryPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetLibraryPath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String datadir(Application::getLibraryDir(),"utf-8"); + Py::String datadir(Application::getLibraryDir(), "utf-8"); return Py::new_reference_to(datadir); } -PyObject* Application::sGetTempPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetTempPath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String datadir(Application::getTempPath(),"utf-8"); + Py::String datadir(Application::getTempPath(), "utf-8"); return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserCachePath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetUserCachePath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String datadir(Application::getUserCachePath(),"utf-8"); + Py::String datadir(Application::getUserCachePath(), "utf-8"); return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserConfigPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetUserConfigPath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String datadir(Application::getUserConfigPath(),"utf-8"); + Py::String datadir(Application::getUserConfigPath(), "utf-8"); return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserAppDataPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetUserAppDataPath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String user_data_dir(Application::getUserAppDataDir(),"utf-8"); + Py::String user_data_dir(Application::getUserAppDataDir(), "utf-8"); return Py::new_reference_to(user_data_dir); } -PyObject* Application::sGetUserMacroPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetUserMacroPath(PyObject* /*self*/, PyObject* args) { - PyObject *actual = Py_False; - if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual)) + PyObject* actual = Py_False; + if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual)) { return nullptr; + } std::string macroDir = Application::getUserMacroDir(); if (Base::asBoolean(actual)) { - macroDir = App::GetApplication(). - GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath", macroDir.c_str()); + macroDir = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath", macroDir.c_str()); std::replace(macroDir.begin(), macroDir.end(), '/', PATHSEP); } - Py::String user_macro_dir(macroDir,"utf-8"); + Py::String user_macro_dir(macroDir, "utf-8"); return Py::new_reference_to(user_macro_dir); } -PyObject* Application::sGetHelpPath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetHelpPath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String user_macro_dir(Application::getHelpDir(),"utf-8"); + Py::String user_macro_dir(Application::getHelpDir(), "utf-8"); return Py::new_reference_to(user_macro_dir); } -PyObject* Application::sGetHomePath(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetHomePath(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - Py::String homedir(Application::getHomePath(),"utf-8"); + Py::String homedir(Application::getHomePath(), "utf-8"); return Py::new_reference_to(homedir); } -PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args) +PyObject* Application::sListDocuments(PyObject* /*self*/, PyObject* args) { - PyObject *sort = Py_False; - if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) + PyObject* sort = Py_False; + if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) { return nullptr; - PY_TRY { - PyObject *pDict = PyDict_New(); - PyObject *pKey; + } + PY_TRY + { + PyObject* pDict = PyDict_New(); + PyObject* pKey; Base::PyObjectBase* pValue; - std::vector docs = GetApplication().getDocuments();; - if (Base::asBoolean(sort)) - docs = Document::getDependentDocuments(docs,true); + std::vector docs = GetApplication().getDocuments(); + ; + if (Base::asBoolean(sort)) { + docs = Document::getDependentDocuments(docs, true); + } for (auto doc : docs) { - pKey = PyUnicode_FromString(doc->getName()); + pKey = PyUnicode_FromString(doc->getName()); // GetPyObject() increments pValue = static_cast(doc->getPyObject()); PyDict_SetItem(pDict, pKey, pValue); @@ -749,157 +894,203 @@ PyObject* Application::sListDocuments(PyObject * /*self*/, PyObject *args) } return pDict; - } PY_CATCH; + } + PY_CATCH; } -PyObject* Application::sAddDocObserver(PyObject * /*self*/, PyObject *args) +PyObject* Application::sAddDocObserver(PyObject* /*self*/, PyObject* args) { PyObject* o; - if (!PyArg_ParseTuple(args, "O",&o)) + if (!PyArg_ParseTuple(args, "O", &o)) { return nullptr; - PY_TRY { + } + PY_TRY + { DocumentObserverPython::addObserver(Py::Object(o)); Py_Return; - } PY_CATCH; + } + PY_CATCH; } -PyObject* Application::sRemoveDocObserver(PyObject * /*self*/, PyObject *args) +PyObject* Application::sRemoveDocObserver(PyObject* /*self*/, PyObject* args) { PyObject* o; - if (!PyArg_ParseTuple(args, "O",&o)) + if (!PyArg_ParseTuple(args, "O", &o)) { return nullptr; - PY_TRY { + } + PY_TRY + { DocumentObserverPython::removeObserver(Py::Object(o)); Py_Return; - } PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sSetLogLevel(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSetLogLevel(PyObject* /*self*/, PyObject* args) { - char *tag; - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "sO", &tag, &pcObj)) + char* tag; + PyObject* pcObj; + if (!PyArg_ParseTuple(args, "sO", &tag, &pcObj)) { return nullptr; - PY_TRY{ + } + PY_TRY + { int l; if (PyUnicode_Check(pcObj)) { - const char *pstr = PyUnicode_AsUTF8(pcObj); - if(strcmp(pstr,"Log") == 0) + const char* pstr = PyUnicode_AsUTF8(pcObj); + if (strcmp(pstr, "Log") == 0) { l = FC_LOGLEVEL_LOG; - else if(strcmp(pstr,"Warning") == 0) + } + else if (strcmp(pstr, "Warning") == 0) { l = FC_LOGLEVEL_WARN; - else if(strcmp(pstr,"Message") == 0) + } + else if (strcmp(pstr, "Message") == 0) { l = FC_LOGLEVEL_MSG; - else if(strcmp(pstr,"Error") == 0) + } + else if (strcmp(pstr, "Error") == 0) { l = FC_LOGLEVEL_ERR; - else if(strcmp(pstr,"Trace") == 0) + } + else if (strcmp(pstr, "Trace") == 0) { l = FC_LOGLEVEL_TRACE; - else if(strcmp(pstr,"Default") == 0) + } + else if (strcmp(pstr, "Default") == 0) { l = FC_LOGLEVEL_DEFAULT; + } else { Py_Error(PyExc_ValueError, - "Unknown Log Level (use 'Default', 'Error', 'Warning', 'Message', 'Log', 'Trace' or an integer)"); + "Unknown Log Level (use 'Default', 'Error', 'Warning', 'Message', 'Log', " + "'Trace' or an integer)"); return nullptr; } - }else + } + else { l = PyLong_AsLong(pcObj); - GetApplication().GetParameterGroupByPath("User parameter:BaseApp/LogLevels")->SetInt(tag,l); - if(strcmp(tag,"Default") == 0) { + } + GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/LogLevels") + ->SetInt(tag, l); + if (strcmp(tag, "Default") == 0) { #ifndef FC_DEBUG - if(l>=0) Base::Console().SetDefaultLogLevel(l); + if (l >= 0) { + Base::Console().SetDefaultLogLevel(l); + } #endif - }else if(strcmp(tag,"DebugDefault") == 0) { + } + else if (strcmp(tag, "DebugDefault") == 0) { #ifdef FC_DEBUG - if(l>=0) Base::Console().SetDefaultLogLevel(l); + if (l >= 0) { + Base::Console().SetDefaultLogLevel(l); + } #endif - }else + } + else { *Base::Console().GetLogLevel(tag) = l; + } Py_INCREF(Py_None); return Py_None; - }PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sGetLogLevel(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetLogLevel(PyObject* /*self*/, PyObject* args) { - char *tag; - if (!PyArg_ParseTuple(args, "s", &tag)) + char* tag; + if (!PyArg_ParseTuple(args, "s", &tag)) { return nullptr; + } - PY_TRY{ + PY_TRY + { int l = -1; - if(strcmp(tag,"Default")==0) { + if (strcmp(tag, "Default") == 0) { #ifdef FC_DEBUG - l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1); + l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); #endif - }else if(strcmp(tag,"DebugDefault")==0) { + } + else if (strcmp(tag, "DebugDefault") == 0) { #ifndef FC_DEBUG - l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag,-1); + l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); #endif - }else{ - int *pl = Base::Console().GetLogLevel(tag,false); - l = pl?*pl:-1; + } + else { + int* pl = Base::Console().GetLogLevel(tag, false); + l = pl ? *pl : -1; } // For performance reason, we only output integer value - return Py_BuildValue("i",Base::Console().LogLevel(l)); - } PY_CATCH; + return Py_BuildValue("i", Base::Console().LogLevel(l)); + } + PY_CATCH; } -PyObject *Application::sCheckLinkDepth(PyObject * /*self*/, PyObject *args) +PyObject* Application::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) { short depth = 0; - if (!PyArg_ParseTuple(args, "h", &depth)) + if (!PyArg_ParseTuple(args, "h", &depth)) { return nullptr; + } - PY_TRY { - return Py::new_reference_to(Py::Int(GetApplication().checkLinkDepth(depth, MessageOption::Throw))); - }PY_CATCH; + PY_TRY + { + return Py::new_reference_to( + Py::Int(GetApplication().checkLinkDepth(depth, MessageOption::Throw))); + } + PY_CATCH; } -PyObject *Application::sGetLinksTo(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetLinksTo(PyObject* /*self*/, PyObject* args) { - PyObject *pyobj = Py_None; + PyObject* pyobj = Py_None; int options = 0; short count = 0; - if (!PyArg_ParseTuple(args, "|Oih",&pyobj,&options, &count)) + if (!PyArg_ParseTuple(args, "|Oih", &pyobj, &options, &count)) { return nullptr; + } - PY_TRY { - Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type App.DocumentObject or None"); - DocumentObject *obj = nullptr; - if (pyobj) + PY_TRY + { + Base::PyTypeCheck(&pyobj, + &DocumentObjectPy::Type, + "Expect the first argument of type App.DocumentObject or None"); + DocumentObject* obj = nullptr; + if (pyobj) { obj = static_cast(pyobj)->getDocumentObjectPtr(); + } - auto links = GetApplication().getLinksTo(obj,options,count); + auto links = GetApplication().getLinksTo(obj, options, count); Py::Tuple ret(links.size()); - int i=0; - for(auto o : links) - ret.setItem(i++,Py::Object(o->getPyObject(),true)); + int i = 0; + for (auto o : links) { + ret.setItem(i++, Py::Object(o->getPyObject(), true)); + } return Py::new_reference_to(ret); } PY_CATCH; } -PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetDependentObjects(PyObject* /*self*/, PyObject* args) { - PyObject *obj; + PyObject* obj; int options = 0; - if (!PyArg_ParseTuple(args, "O|i", &obj,&options)) + if (!PyArg_ParseTuple(args, "O|i", &obj, &options)) { return nullptr; + } std::vector objs; if (PySequence_Check(obj)) { Py::Sequence seq(obj); - for (Py_ssize_t i=0;i(seq[i].ptr())->getDocumentObjectPtr()); } } - else if(!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) { - PyErr_SetString(PyExc_TypeError, + else if (!PyObject_TypeCheck(obj, &DocumentObjectPy::Type)) { + PyErr_SetString( + PyExc_TypeError, "Expect first argument to be either a document object or sequence of document objects"); return nullptr; } @@ -907,67 +1098,83 @@ PyObject *Application::sGetDependentObjects(PyObject * /*self*/, PyObject *args) objs.push_back(static_cast(obj)->getDocumentObjectPtr()); } - PY_TRY { - auto ret = App::Document::getDependencyList(objs,options); + PY_TRY + { + auto ret = App::Document::getDependencyList(objs, options); Py::Tuple tuple(ret.size()); - for(size_t i=0;igetPyObject(),true)); + for (size_t i = 0; i < ret.size(); ++i) { + tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true)); + } return Py::new_reference_to(tuple); - } PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sSetActiveTransaction(PyObject * /*self*/, PyObject *args) +PyObject* Application::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) { - char *name; - PyObject *persist = Py_False; - if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist)) + char* name; + PyObject* persist = Py_False; + if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist)) { return nullptr; + } - PY_TRY { + PY_TRY + { Py::Int ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist))); return Py::new_reference_to(ret); - }PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sGetActiveTransaction(PyObject * /*self*/, PyObject *args) +PyObject* Application::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - PY_TRY { + PY_TRY + { int id = 0; - const char *name = GetApplication().getActiveTransaction(&id); - if(!name || id<=0) + const char* name = GetApplication().getActiveTransaction(&id); + if (!name || id <= 0) { Py_Return; + } Py::Tuple ret(2); - ret.setItem(0,Py::String(name)); - ret.setItem(1,Py::Int(id)); + ret.setItem(0, Py::String(name)); + ret.setItem(1, Py::Int(id)); return Py::new_reference_to(ret); - }PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sCloseActiveTransaction(PyObject * /*self*/, PyObject *args) +PyObject* Application::sCloseActiveTransaction(PyObject* /*self*/, PyObject* args) { - PyObject *abort = Py_False; + PyObject* abort = Py_False; int id = 0; - if (!PyArg_ParseTuple(args, "|O!i", &PyBool_Type, &abort,&id)) + if (!PyArg_ParseTuple(args, "|O!i", &PyBool_Type, &abort, &id)) { return nullptr; + } - PY_TRY { + PY_TRY + { GetApplication().closeActiveTransaction(Base::asBoolean(abort), id); Py_Return; - } PY_CATCH; + } + PY_CATCH; } -PyObject *Application::sCheckAbort(PyObject * /*self*/, PyObject *args) +PyObject* Application::sCheckAbort(PyObject* /*self*/, PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - PY_TRY { + PY_TRY + { Base::Sequencer().checkAbort(); Py_Return; - }PY_CATCH + } + PY_CATCH } diff --git a/src/App/AutoTransaction.cpp b/src/App/AutoTransaction.cpp index 6597f7109c35..b70a4d579789 100644 --- a/src/App/AutoTransaction.cpp +++ b/src/App/AutoTransaction.cpp @@ -37,12 +37,11 @@ using namespace App; static int _TransactionLock; static int _TransactionClosed; -AutoTransaction::AutoTransaction(const char *name, bool tmpName) { - auto &app = GetApplication(); - if(name && app._activeTransactionGuard>=0) { - if(!app.getActiveTransaction() - || (!tmpName && app._activeTransactionTmpName)) - { +AutoTransaction::AutoTransaction(const char* name, bool tmpName) +{ + auto& app = GetApplication(); + if (name && app._activeTransactionGuard >= 0) { + if (!app.getActiveTransaction() || (!tmpName && app._activeTransactionTmpName)) { FC_LOG("auto transaction '" << name << "', " << tmpName); tid = app.setActiveTransaction(name); app._activeTransactionTmpName = tmpName; @@ -52,166 +51,206 @@ AutoTransaction::AutoTransaction(const char *name, bool tmpName) { // and any stack below. This is to support user setting active transaction // before having any existing AutoTransaction on stack, or 'persist' // transaction that can out live AutoTransaction. - if(app._activeTransactionGuard<0) + if (app._activeTransactionGuard < 0) { --app._activeTransactionGuard; - else if(tid || app._activeTransactionGuard>0) + } + else if (tid || app._activeTransactionGuard > 0) { ++app._activeTransactionGuard; - else if(app.getActiveTransaction()) { + } + else if (app.getActiveTransaction()) { FC_LOG("auto transaction disabled because of '" << app._activeTransactionName << "'"); --app._activeTransactionGuard; - } else + } + else { ++app._activeTransactionGuard; + } FC_TRACE("construct auto Transaction " << app._activeTransactionGuard); } -AutoTransaction::~AutoTransaction() { - auto &app = GetApplication(); +AutoTransaction::~AutoTransaction() +{ + auto& app = GetApplication(); FC_TRACE("before destruct auto Transaction " << app._activeTransactionGuard); - if(app._activeTransactionGuard<0) + if (app._activeTransactionGuard < 0) { ++app._activeTransactionGuard; - else if(!app._activeTransactionGuard) { + } + else if (!app._activeTransactionGuard) { #ifdef FC_DEBUG FC_ERR("Transaction guard error"); #endif - } else if(--app._activeTransactionGuard == 0) { + } + else if (--app._activeTransactionGuard == 0) { try { // We don't call close() here, because close() only closes // transaction that we opened during construction time. However, // when _activeTransactionGuard reaches zero here, we are supposed // to close any transaction opened. app.closeActiveTransaction(); - } catch(Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); - } catch(...) - {} + } + catch (...) { + } } FC_TRACE("destruct auto Transaction " << app._activeTransactionGuard); } -void AutoTransaction::close(bool abort) { - if(tid || abort) { - GetApplication().closeActiveTransaction(abort,abort?0:tid); +void AutoTransaction::close(bool abort) +{ + if (tid || abort) { + GetApplication().closeActiveTransaction(abort, abort ? 0 : tid); tid = 0; } } -void AutoTransaction::setEnable(bool enable) { - auto &app = GetApplication(); - if(!app._activeTransactionGuard) +void AutoTransaction::setEnable(bool enable) +{ + auto& app = GetApplication(); + if (!app._activeTransactionGuard) { return; - if((enable && app._activeTransactionGuard>0) - || (!enable && app._activeTransactionGuard<0)) + } + if ((enable && app._activeTransactionGuard > 0) + || (!enable && app._activeTransactionGuard < 0)) { return; + } app._activeTransactionGuard = -app._activeTransactionGuard; FC_TRACE("toggle auto Transaction " << app._activeTransactionGuard); - if(!enable && app._activeTransactionTmpName) { + if (!enable && app._activeTransactionTmpName) { bool close = true; - for(auto &v : app.DocMap) { - if(v.second->hasPendingTransaction()) { + for (auto& v : app.DocMap) { + if (v.second->hasPendingTransaction()) { close = false; break; } } - if(close) + if (close) { app.closeActiveTransaction(); + } } } -int Application::setActiveTransaction(const char *name, bool persist) { - if(!name || !name[0]) +int Application::setActiveTransaction(const char* name, bool persist) +{ + if (!name || !name[0]) { name = "Command"; + } - if(_activeTransactionGuard>0 && getActiveTransaction()) { - if(_activeTransactionTmpName) { + if (_activeTransactionGuard > 0 && getActiveTransaction()) { + if (_activeTransactionTmpName) { FC_LOG("transaction rename to '" << name << "'"); - for(auto &v : DocMap) - v.second->renameTransaction(name,_activeTransactionID); - } else { - if(persist) + for (auto& v : DocMap) { + v.second->renameTransaction(name, _activeTransactionID); + } + } + else { + if (persist) { AutoTransaction::setEnable(false); + } return 0; } - } else if (_TransactionLock) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + } + else if (_TransactionLock) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Transaction locked, ignore new transaction '" << name << "'"); + } return 0; - } else { + } + else { FC_LOG("set active transaction '" << name << "'"); _activeTransactionID = 0; - for(auto &v : DocMap) + for (auto& v : DocMap) { v.second->_commitTransaction(); + } _activeTransactionID = Transaction::getNewID(); } _activeTransactionTmpName = false; _activeTransactionName = name; - if(persist) + if (persist) { AutoTransaction::setEnable(false); + } return _activeTransactionID; } -const char *Application::getActiveTransaction(int *id) const { +const char* Application::getActiveTransaction(int* id) const +{ int tid = 0; - if(Transaction::getLastID() == _activeTransactionID) + if (Transaction::getLastID() == _activeTransactionID) { tid = _activeTransactionID; - if (id) + } + if (id) { *id = tid; + } return tid ? _activeTransactionName.c_str() : nullptr; } -void Application::closeActiveTransaction(bool abort, int id) { - if(!id) id = _activeTransactionID; - if(!id) +void Application::closeActiveTransaction(bool abort, int id) +{ + if (!id) { + id = _activeTransactionID; + } + if (!id) { return; + } - if(_activeTransactionGuard>0 && !abort) { + if (_activeTransactionGuard > 0 && !abort) { FC_LOG("ignore close transaction"); return; } - if(_TransactionLock) { - if(_TransactionClosed >= 0) - _TransactionLock = abort?-1:1; - FC_LOG("pending " << (abort?"abort":"close") << " transaction"); + if (_TransactionLock) { + if (_TransactionClosed >= 0) { + _TransactionLock = abort ? -1 : 1; + } + FC_LOG("pending " << (abort ? "abort" : "close") << " transaction"); return; } FC_LOG("close transaction '" << _activeTransactionName << "' " << abort); _activeTransactionID = 0; - TransactionSignaller signaller(abort,false); - for(auto &v : DocMap) { - if(v.second->getTransactionID(true) != id) + TransactionSignaller signaller(abort, false); + for (auto& v : DocMap) { + if (v.second->getTransactionID(true) != id) { continue; - if(abort) + } + if (abort) { v.second->_abortTransaction(); - else + } + else { v.second->_commitTransaction(); + } } } //////////////////////////////////////////////////////////////////////// TransactionLocker::TransactionLocker(bool lock) - :active(lock) + : active(lock) { - if(lock) + if (lock) { ++_TransactionLock; + } } TransactionLocker::~TransactionLocker() { - if(active) { + if (active) { try { activate(false); return; - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); - } catch (Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException e; e.ReportException(); - } catch (std::exception &e) { + } + catch (std::exception& e) { FC_ERR(e.what()); - } catch (...) { + } + catch (...) { } FC_ERR("Exception when unlocking transaction"); } @@ -219,26 +258,28 @@ TransactionLocker::~TransactionLocker() void TransactionLocker::activate(bool enable) { - if(active == enable) + if (active == enable) { return; + } active = enable; - if(active) { + if (active) { ++_TransactionLock; return; } - if(--_TransactionLock != 0) + if (--_TransactionLock != 0) { return; + } - if(_TransactionClosed) { - bool abort = (_TransactionClosed<0); + if (_TransactionClosed) { + bool abort = (_TransactionClosed < 0); _TransactionClosed = 0; GetApplication().closeActiveTransaction(abort); } } -bool TransactionLocker::isLocked() { +bool TransactionLocker::isLocked() +{ return _TransactionLock > 0; } - diff --git a/src/App/AutoTransaction.h b/src/App/AutoTransaction.h index cd44fe7f7032..6318d5c7cfb8 100644 --- a/src/App/AutoTransaction.h +++ b/src/App/AutoTransaction.h @@ -26,15 +26,17 @@ #include #include -namespace App { +namespace App +{ class Application; /// Helper class to manager transaction (i.e. undo/redo) -class AppExport AutoTransaction { +class AppExport AutoTransaction +{ public: /// Private new operator to prevent heap allocation - void* operator new (std::size_t) = delete; + void* operator new(std::size_t) = delete; public: /** Constructor @@ -51,7 +53,7 @@ class AppExport AutoTransaction { * current active transaction until it reaches zero. It does not have any * effect on aborting transaction, though. */ - AutoTransaction(const char *name=nullptr, bool tmpName=false); + AutoTransaction(const char* name = nullptr, bool tmpName = false); /** Destructor * @@ -67,7 +69,7 @@ class AppExport AutoTransaction { * transaction, if the current transaction ID matches the one created inside * the constructor. For aborting, it will abort any current transaction */ - void close(bool abort=false); + void close(bool abort = false); /** Enable/Disable any AutoTransaction instance in the current stack * @@ -90,13 +92,13 @@ class AppExport AutoTransaction { * The helper class is used to protect some critical transaction from being * closed prematurely, e.g. when deleting some object. */ -class AppExport TransactionLocker { +class AppExport TransactionLocker +{ public: - /** Constructor * @param lock: whether to activate the lock */ - TransactionLocker(bool lock=true); + TransactionLocker(bool lock = true); /** Destructor * Unlock the transaction is this locker is active @@ -114,7 +116,10 @@ class AppExport TransactionLocker { void activate(bool enable); /// Check if the locker is active - bool isActive() const {return active;} + bool isActive() const + { + return active; + } /// Check if transaction is being locked static bool isLocked(); @@ -123,12 +128,12 @@ class AppExport TransactionLocker { public: /// Private new operator to prevent heap allocation - void* operator new (std::size_t) = delete; + void* operator new(std::size_t) = delete; private: bool active; }; -} // namespace App +} // namespace App -#endif // APP_AUTOTRANSACTION_H +#endif // APP_AUTOTRANSACTION_H diff --git a/src/App/Branding.cpp b/src/App/Branding.cpp index ef50dc5302df..2be169e8e6dc 100644 --- a/src/App/Branding.cpp +++ b/src/App/Branding.cpp @@ -63,10 +63,12 @@ Branding::Branding() bool Branding::readFile(const QString& fn) { QFile file(fn); - if (!file.open(QFile::ReadOnly)) + if (!file.open(QFile::ReadOnly)) { return false; - if (!evaluateXML(&file, domDocument)) + } + if (!evaluateXML(&file, domDocument)) { return false; + } file.close(); return true; } @@ -81,22 +83,22 @@ Branding::XmlConfig Branding::getUserDefines() const while (!child.isNull()) { std::string name = child.localName().toLatin1().constData(); std::string value = child.text().toUtf8().constData(); - if (std::find(filter.begin(), filter.end(), name) != filter.end()) + if (std::find(filter.begin(), filter.end(), name) != filter.end()) { cfg[name] = value; + } child = child.nextSiblingElement(); } } return cfg; } -bool Branding::evaluateXML(QIODevice *device, QDomDocument& xmlDocument) +bool Branding::evaluateXML(QIODevice* device, QDomDocument& xmlDocument) { QString errorStr; int errorLine; int errorColumn; - if (!xmlDocument.setContent(device, true, &errorStr, &errorLine, - &errorColumn)) { + if (!xmlDocument.setContent(device, true, &errorStr, &errorLine, &errorColumn)) { return false; } @@ -106,8 +108,9 @@ bool Branding::evaluateXML(QIODevice *device, QDomDocument& xmlDocument) } else if (root.hasAttribute(QLatin1String("version"))) { QString attr = root.attribute(QLatin1String("version")); - if (attr != QLatin1String("1.0")) + if (attr != QLatin1String("1.0")) { return false; + } } return true; diff --git a/src/App/Branding.h b/src/App/Branding.h index c0293f3270a6..b8ab7e97e0f2 100644 --- a/src/App/Branding.h +++ b/src/App/Branding.h @@ -33,7 +33,8 @@ class QIODevice; -namespace App { +namespace App +{ class Branding { @@ -46,10 +47,10 @@ class Branding private: QVector filter; - bool evaluateXML(QIODevice *device, QDomDocument& xmlDocument); + bool evaluateXML(QIODevice* device, QDomDocument& xmlDocument); QDomDocument domDocument; }; -} +} // namespace App -#endif // APP_BRANDING_H +#endif // APP_BRANDING_H diff --git a/src/App/CleanupProcess.cpp b/src/App/CleanupProcess.cpp index 30fbd35ae260..038de1abd372 100644 --- a/src/App/CleanupProcess.cpp +++ b/src/App/CleanupProcess.cpp @@ -31,7 +31,7 @@ using namespace App; namespace { - static std::list> cleanup_funcs; // NOLINT +static std::list> cleanup_funcs; // NOLINT } void CleanupProcess::registerCleanup(const std::function& func) diff --git a/src/App/CleanupProcess.h b/src/App/CleanupProcess.h index a5d9281b4f96..fcc263184088 100644 --- a/src/App/CleanupProcess.h +++ b/src/App/CleanupProcess.h @@ -52,6 +52,6 @@ class AppExport CleanupProcess static void callCleanup(); }; -} +} // namespace App #endif // APP_CLEANUPPROCESS_H diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index 1dc12cccddd7..878876d9c487 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "ComplexGeoData.h" @@ -50,10 +50,11 @@ std::string ComplexGeoDataPy::representation() const return {""}; } -PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args) +PyObject* ComplexGeoDataPy::getElementTypes(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } std::vector types = getComplexGeoDataPtr()->getElementTypes(); Py::List list; @@ -63,11 +64,12 @@ PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args) return Py::new_reference_to(list); } -PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) +PyObject* ComplexGeoDataPy::countSubElements(PyObject* args) { - char *type; - if (!PyArg_ParseTuple(args, "s", &type)) + char* type; + if (!PyArg_ParseTuple(args, "s", &type)) { return nullptr; + } try { unsigned long count = getComplexGeoDataPtr()->countSubElements(type); @@ -79,12 +81,13 @@ PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) } } -PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject *args) +PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject* args) { - char *type; + char* type; unsigned long index; - if (!PyArg_ParseTuple(args, "sk", &type, &index)) + if (!PyArg_ParseTuple(args, "sk", &type, &index)) { return nullptr; + } std::vector points; std::vector normals; @@ -100,27 +103,29 @@ PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject *args) Py::Tuple tuple(2); Py::List vertex; - for (const auto & it : points) + for (const auto& it : points) { vertex.append(Py::asObject(new Base::VectorPy(it))); + } tuple.setItem(0, vertex); Py::List facet; - for (const auto & it : facets) { + for (const auto& it : facets) { Py::Tuple f(3); - f.setItem(0,Py::Int(int(it.I1))); - f.setItem(1,Py::Int(int(it.I2))); - f.setItem(2,Py::Int(int(it.I3))); + f.setItem(0, Py::Int(int(it.I1))); + f.setItem(1, Py::Int(int(it.I2))); + f.setItem(2, Py::Int(int(it.I3))); facet.append(f); } tuple.setItem(1, facet); return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject *args) +PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject* args) { - char *type; + char* type; int index; - if (!PyArg_ParseTuple(args, "si", &type, &index)) + if (!PyArg_ParseTuple(args, "si", &type, &index)) { return nullptr; + } std::vector points; std::vector lines; @@ -135,25 +140,27 @@ PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject *args) Py::Tuple tuple(2); Py::List vertex; - for (const auto & it : points) + for (const auto& it : points) { vertex.append(Py::asObject(new Base::VectorPy(it))); + } tuple.setItem(0, vertex); Py::List line; - for (const auto & it : lines) { + for (const auto& it : lines) { Py::Tuple l(2); - l.setItem(0,Py::Int((int)it.I1)); - l.setItem(1,Py::Int((int)it.I2)); + l.setItem(0, Py::Int((int)it.I1)); + l.setItem(1, Py::Int((int)it.I2)); line.append(l); } tuple.setItem(1, line); return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::getPoints(PyObject *args) +PyObject* ComplexGeoDataPy::getPoints(PyObject* args) { double accuracy = 0.05; - if (!PyArg_ParseTuple(args, "d", &accuracy)) + if (!PyArg_ParseTuple(args, "d", &accuracy)) { return nullptr; + } std::vector points; std::vector normals; @@ -167,24 +174,25 @@ PyObject* ComplexGeoDataPy::getPoints(PyObject *args) Py::Tuple tuple(2); Py::List vertex; - for (const auto & it : points) { + for (const auto& it : points) { vertex.append(Py::asObject(new Base::VectorPy(it))); } tuple.setItem(0, vertex); Py::List normal; - for (const auto & it : normals) { + for (const auto& it : normals) { normal.append(Py::asObject(new Base::VectorPy(it))); } tuple.setItem(1, normal); return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::getLines(PyObject *args) +PyObject* ComplexGeoDataPy::getLines(PyObject* args) { double accuracy = 0.05; - if (!PyArg_ParseTuple(args, "d", &accuracy)) + if (!PyArg_ParseTuple(args, "d", &accuracy)) { return nullptr; + } std::vector points; std::vector lines; @@ -198,25 +206,27 @@ PyObject* ComplexGeoDataPy::getLines(PyObject *args) Py::Tuple tuple(2); Py::List vertex; - for (const auto & it : points) + for (const auto& it : points) { vertex.append(Py::asObject(new Base::VectorPy(it))); + } tuple.setItem(0, vertex); Py::List line; - for (const auto & it : lines) { + for (const auto& it : lines) { Py::Tuple l(2); - l.setItem(0,Py::Int((int)it.I1)); - l.setItem(1,Py::Int((int)it.I2)); + l.setItem(0, Py::Int((int)it.I1)); + l.setItem(1, Py::Int((int)it.I2)); line.append(l); } tuple.setItem(1, line); return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::getFaces(PyObject *args) +PyObject* ComplexGeoDataPy::getFaces(PyObject* args) { double accuracy = 0.05; - if (!PyArg_ParseTuple(args, "d", &accuracy)) + if (!PyArg_ParseTuple(args, "d", &accuracy)) { return nullptr; + } std::vector points; std::vector facets; @@ -230,26 +240,28 @@ PyObject* ComplexGeoDataPy::getFaces(PyObject *args) Py::Tuple tuple(2); Py::List vertex; - for (const auto & it : points) + for (const auto& it : points) { vertex.append(Py::asObject(new Base::VectorPy(it))); + } tuple.setItem(0, vertex); Py::List facet; - for (const auto & it : facets) { + for (const auto& it : facets) { Py::Tuple f(3); - f.setItem(0,Py::Int((int)it.I1)); - f.setItem(1,Py::Int((int)it.I2)); - f.setItem(2,Py::Int((int)it.I3)); + f.setItem(0, Py::Int((int)it.I1)); + f.setItem(1, Py::Int((int)it.I2)); + f.setItem(2, Py::Int((int)it.I3)); facet.append(f); } tuple.setItem(1, facet); return Py::new_reference_to(tuple); } -PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args) +PyObject* ComplexGeoDataPy::applyTranslation(PyObject* args) { - PyObject *obj; - if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&obj)) + PyObject* obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &obj)) { return nullptr; + } try { Base::Vector3d move = static_cast(obj)->value(); @@ -262,11 +274,12 @@ PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args) } } -PyObject* ComplexGeoDataPy::applyRotation(PyObject *args) +PyObject* ComplexGeoDataPy::applyRotation(PyObject* args) { - PyObject *obj; - if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type),&obj)) + PyObject* obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type), &obj)) { return nullptr; + } try { Base::Rotation rot = static_cast(obj)->value(); @@ -279,11 +292,12 @@ PyObject* ComplexGeoDataPy::applyRotation(PyObject *args) } } -PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args) +PyObject* ComplexGeoDataPy::transformGeometry(PyObject* args) { - PyObject *obj; - if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&obj)) + PyObject* obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type), &obj)) { return nullptr; + } try { Base::Matrix4D mat = static_cast(obj)->value(); @@ -377,17 +391,18 @@ PyObject* ComplexGeoDataPy::setElementName(PyObject* args, PyObject* kwds) PyObject* pySid = Py_None; PyObject* overwrite = Py_False; - const std::array kwlist = {"element", "name", "postfix", "overwrite", "sid", "tag", nullptr}; + const std::array kwlist = + {"element", "name", "postfix", "overwrite", "sid", "tag", nullptr}; if (!Wrapped_ParseTupleAndKeywords(args, - kwds, - "s|sssOOi", - kwlist, - &element, - &name, - &postfix, - &overwrite, - &pySid, - &tag)) { + kwds, + "s|sssOOi", + kwlist, + &element, + &name, + &postfix, + &overwrite, + &pySid, + &tag)) { return NULL; } ElementIDRefs sids; @@ -529,8 +544,9 @@ Py::Object ComplexGeoDataPy::getBoundBox() const Py::Object ComplexGeoDataPy::getCenterOfGravity() const { Base::Vector3d center; - if (getComplexGeoDataPtr()->getCenterOfGravity(center)) + if (getComplexGeoDataPtr()->getCenterOfGravity(center)) { return Py::Vector(center); + } throw Py::RuntimeError("Cannot get center of gravity"); } diff --git a/src/App/DocumentObjectExtension.cpp b/src/App/DocumentObjectExtension.cpp index 7072b6baea3e..85e392283944 100644 --- a/src/App/DocumentObjectExtension.cpp +++ b/src/App/DocumentObjectExtension.cpp @@ -39,55 +39,60 @@ DocumentObjectExtension::DocumentObjectExtension() DocumentObjectExtension::~DocumentObjectExtension() = default; -short int DocumentObjectExtension::extensionMustExecute() { +short int DocumentObjectExtension::extensionMustExecute() +{ return 0; } -App::DocumentObjectExecReturn* DocumentObjectExtension::extensionExecute() { +App::DocumentObjectExecReturn* DocumentObjectExtension::extensionExecute() +{ return App::DocumentObject::StdReturn; } -void DocumentObjectExtension::onExtendedSettingDocument() { +void DocumentObjectExtension::onExtendedSettingDocument() +{} -} +void DocumentObjectExtension::onExtendedDocumentRestored() +{} -void DocumentObjectExtension::onExtendedDocumentRestored() { +void DocumentObjectExtension::onExtendedSetupObject() +{} -} - -void DocumentObjectExtension::onExtendedSetupObject() { - -} +void DocumentObjectExtension::onExtendedUnsetupObject() +{} -void DocumentObjectExtension::onExtendedUnsetupObject() { - -} - -PyObject* DocumentObjectExtension::getExtensionPyObject() { +PyObject* DocumentObjectExtension::getExtensionPyObject() +{ - if (ExtensionPythonObject.is(Py::_None())){ + if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 - ExtensionPythonObject = Py::Object(new DocumentObjectExtensionPy(this),true); + ExtensionPythonObject = Py::Object(new DocumentObjectExtensionPy(this), true); } return Py::new_reference_to(ExtensionPythonObject); } -const DocumentObject* DocumentObjectExtension::getExtendedObject() const { +const DocumentObject* DocumentObjectExtension::getExtendedObject() const +{ assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId())); return static_cast(getExtendedContainer()); } -DocumentObject* DocumentObjectExtension::getExtendedObject() { +DocumentObject* DocumentObjectExtension::getExtendedObject() +{ assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId())); return static_cast(getExtendedContainer()); } -bool DocumentObjectExtension::extensionGetSubObject(DocumentObject *&, - const char *, PyObject **, Base::Matrix4D *, bool, int) const +bool DocumentObjectExtension::extensionGetSubObject(DocumentObject*&, + const char*, + PyObject**, + Base::Matrix4D*, + bool, + int) const { return false; } @@ -97,8 +102,11 @@ bool DocumentObjectExtension::extensionGetSubObjects(std::vector&, return false; } -bool DocumentObjectExtension::extensionGetLinkedObject( - DocumentObject *&, bool, Base::Matrix4D *, bool, int) const +bool DocumentObjectExtension::extensionGetLinkedObject(DocumentObject*&, + bool, + Base::Matrix4D*, + bool, + int) const { return false; } diff --git a/src/App/DocumentObjectExtension.h b/src/App/DocumentObjectExtension.h index a27b6f680df2..71021cd963fc 100644 --- a/src/App/DocumentObjectExtension.h +++ b/src/App/DocumentObjectExtension.h @@ -26,10 +26,12 @@ #include "Extension.h" -namespace Base { +namespace Base +{ class Matrix4D; } -namespace App { +namespace App +{ class DocumentObject; class DocumentObjectExecReturn; @@ -37,24 +39,23 @@ class DocumentObjectExecReturn; * @brief Extension with special document object calls * */ -class AppExport DocumentObjectExtension : public App::Extension +class AppExport DocumentObjectExtension: public App::Extension { - //The cass does not have properties itself, but it is important to provide the property access - //functions. see cpp file for details + // The cass does not have properties itself, but it is important to provide the property access + // functions. see cpp file for details EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::DocumentObjectExtension); public: + DocumentObjectExtension(); + ~DocumentObjectExtension() override; - DocumentObjectExtension (); - ~DocumentObjectExtension () override; - - App::DocumentObject* getExtendedObject(); + App::DocumentObject* getExtendedObject(); const App::DocumentObject* getExtendedObject() const; - //override if execution is necessary + // override if execution is necessary virtual short extensionMustExecute(); - virtual App::DocumentObjectExecReturn *extensionExecute(); + virtual App::DocumentObjectExecReturn* extensionExecute(); /// get called after setting the document @@ -70,36 +71,55 @@ class AppExport DocumentObjectExtension : public App::Extension /// returns the type name of the ViewProviderExtension which is automatically attached /// to the viewprovider object when it is initiated - virtual const char* getViewProviderExtensionName() const {return "";} + virtual const char* getViewProviderExtensionName() const + { + return ""; + } /** Get the sub object by name * @sa DocumentObject::getSubObject() * * @return Return turn if handled, the sub object is returned in \c ret */ - virtual bool extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const; + virtual bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const; /** Get name references of all sub objects * @sa DocumentObject::getSubObjects() * * @return Return turn if handled, the sub object is returned in \c ret */ - virtual bool extensionGetSubObjects(std::vector &ret, int reason) const; + virtual bool extensionGetSubObjects(std::vector& ret, int reason) const; /** Get the linked object * @sa DocumentObject::getLinkedObject() * * @return Return turn if handled, the linked object is returned in \c ret */ - virtual bool extensionGetLinkedObject(DocumentObject *&ret, bool recursive, - Base::Matrix4D *mat, bool transform, int depth) const; - - virtual int extensionSetElementVisible(const char *, bool) {return -1;} - virtual int extensionIsElementVisible(const char *) {return -1;} - virtual bool extensionHasChildElement() const {return false;} + virtual bool extensionGetLinkedObject(DocumentObject*& ret, + bool recursive, + Base::Matrix4D* mat, + bool transform, + int depth) const; + + virtual int extensionSetElementVisible(const char*, bool) + { + return -1; + } + virtual int extensionIsElementVisible(const char*) + { + return -1; + } + virtual bool extensionHasChildElement() const + { + return false; + } }; -} //App +} // namespace App -#endif // APP_DOCUMENTOBJECTEXTENSION_H +#endif // APP_DOCUMENTOBJECTEXTENSION_H diff --git a/src/App/DocumentObjectExtensionPy.xml b/src/App/DocumentObjectExtensionPy.xml index 858ebc5fc423..214539b25514 100644 --- a/src/App/DocumentObjectExtensionPy.xml +++ b/src/App/DocumentObjectExtensionPy.xml @@ -1,13 +1,13 @@  - diff --git a/src/App/DocumentObjectExtensionPyImp.cpp b/src/App/DocumentObjectExtensionPyImp.cpp index a80f1a160369..16f7ac36b571 100644 --- a/src/App/DocumentObjectExtensionPyImp.cpp +++ b/src/App/DocumentObjectExtensionPyImp.cpp @@ -35,12 +35,12 @@ std::string DocumentObjectExtensionPy::representation() const return {""}; } -PyObject *DocumentObjectExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* DocumentObjectExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } -int DocumentObjectExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/) +int DocumentObjectExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } diff --git a/src/App/DocumentObjectFileIncluded.cpp b/src/App/DocumentObjectFileIncluded.cpp index e3bbafe4aebe..9f10aacd6238 100644 --- a/src/App/DocumentObjectFileIncluded.cpp +++ b/src/App/DocumentObjectFileIncluded.cpp @@ -32,8 +32,11 @@ PROPERTY_SOURCE(App::DocumentObjectFileIncluded, App::DocumentObject) DocumentObjectFileIncluded::DocumentObjectFileIncluded() { - ADD_PROPERTY_TYPE(File,(nullptr),"",(App::PropertyType)(Prop_None),"File to include into Project File"); + ADD_PROPERTY_TYPE(File, + (nullptr), + "", + (App::PropertyType)(Prop_None), + "File to include into Project File"); } DocumentObjectFileIncluded::~DocumentObjectFileIncluded() = default; - diff --git a/src/App/DocumentObjectFileIncluded.h b/src/App/DocumentObjectFileIncluded.h index eb338fedea4a..55711be609bf 100644 --- a/src/App/DocumentObjectFileIncluded.h +++ b/src/App/DocumentObjectFileIncluded.h @@ -31,7 +31,7 @@ namespace App { -class AppExport DocumentObjectFileIncluded : public DocumentObject +class AppExport DocumentObjectFileIncluded: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::DocumentObjectFileIncluded); @@ -42,16 +42,16 @@ class AppExport DocumentObjectFileIncluded : public DocumentObject /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderDocumentObject"; } /// Properties PropertyFileIncluded File; - }; -} //namespace App +} // namespace App -#endif // APP_DOCUMENTOBJECTFILEINCLUDED_H +#endif // APP_DOCUMENTOBJECTFILEINCLUDED_H diff --git a/src/App/DocumentObjectGroup.cpp b/src/App/DocumentObjectGroup.cpp index c4fdd690f254..167d6de627df 100644 --- a/src/App/DocumentObjectGroup.cpp +++ b/src/App/DocumentObjectGroup.cpp @@ -31,19 +31,22 @@ using namespace App; PROPERTY_SOURCE_WITH_EXTENSIONS(App::DocumentObjectGroup, App::DocumentObject) -DocumentObjectGroup::DocumentObjectGroup(): DocumentObject(), GroupExtension() { +DocumentObjectGroup::DocumentObjectGroup() + : DocumentObject() + , GroupExtension() +{ GroupExtension::initExtension(this); - _GroupTouched.setStatus(App::Property::Output,true); + _GroupTouched.setStatus(App::Property::Output, true); } DocumentObjectGroup::~DocumentObjectGroup() = default; -PyObject *DocumentObjectGroup::getPyObject() +PyObject* DocumentObjectGroup::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectGroupPy(this),true); + PythonObject = Py::Object(new DocumentObjectGroupPy(this), true); } return Py::new_reference_to(PythonObject); } @@ -51,17 +54,22 @@ PyObject *DocumentObjectGroup::getPyObject() // Python feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(App::DocumentObjectGroupPython, App::DocumentObjectGroup) -template<> const char* App::DocumentObjectGroupPython::getViewProviderName() const { +template<> +const char* App::DocumentObjectGroupPython::getViewProviderName() const +{ return "Gui::ViewProviderDocumentObjectGroupPython"; } -template<> PyObject* App::DocumentObjectGroupPython::getPyObject() { +template<> +PyObject* App::DocumentObjectGroupPython::getPyObject() +{ if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FeaturePythonPyT(this),true); + PythonObject = Py::Object(new FeaturePythonPyT(this), true); } return Py::new_reference_to(PythonObject); } @@ -69,4 +77,4 @@ template<> PyObject* App::DocumentObjectGroupPython::getPyObject() { // explicit template instantiation template class AppExport FeaturePythonT; -} +} // namespace App diff --git a/src/App/DocumentObjectGroup.h b/src/App/DocumentObjectGroup.h index 2e88e7e94613..0f0e6ff550c8 100644 --- a/src/App/DocumentObjectGroup.h +++ b/src/App/DocumentObjectGroup.h @@ -32,7 +32,8 @@ namespace App { -class AppExport DocumentObjectGroup : public DocumentObject, public GroupExtension { +class AppExport DocumentObjectGroup: public DocumentObject, public GroupExtension +{ PROPERTY_HEADER_WITH_EXTENSIONS(App::DocumentObjectGroup); @@ -42,17 +43,18 @@ class AppExport DocumentObjectGroup : public DocumentObject, public GroupExtensi ~DocumentObjectGroup() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderDocumentObjectGroup"; } - PyObject *getPyObject() override; + PyObject* getPyObject() override; }; using DocumentObjectGroupPython = App::FeaturePythonT; -} //namespace App +} // namespace App -#endif // APP_DOCUMENTOBJECTGROUP_H +#endif // APP_DOCUMENTOBJECTGROUP_H diff --git a/src/App/DocumentObjectGroupPy.xml b/src/App/DocumentObjectGroupPy.xml index 07b37a5cafe6..c548fe03c55e 100644 --- a/src/App/DocumentObjectGroupPy.xml +++ b/src/App/DocumentObjectGroupPy.xml @@ -1,13 +1,13 @@ - diff --git a/src/App/DocumentObjectGroupPyImp.cpp b/src/App/DocumentObjectGroupPyImp.cpp index 4b4c36565f0c..9c32502c6e9c 100644 --- a/src/App/DocumentObjectGroupPyImp.cpp +++ b/src/App/DocumentObjectGroupPyImp.cpp @@ -37,7 +37,7 @@ std::string DocumentObjectGroupPy::representation() const return {""}; } -PyObject *DocumentObjectGroupPy::getCustomAttributes(const char* /*attr*/) const +PyObject* DocumentObjectGroupPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -46,4 +46,3 @@ int DocumentObjectGroupPy::setCustomAttributes(const char* /*attr*/, PyObject* / { return 0; } - diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml index 463c013edf82..cb93c974db94 100644 --- a/src/App/DocumentObjectPy.xml +++ b/src/App/DocumentObjectPy.xml @@ -1,13 +1,13 @@ - @@ -95,7 +95,7 @@ referencing subobject. PyObject: return a python binding object for the (sub)object referenced in each 'subname' The actual type of 'PyObject' is implementation dependent. For Part::Feature compatible objects, this will be of type TopoShapePy and - pre-transformed by accumulated transformation matrix along the object path. + pre-transformed by accumulated transformation matrix along the object path. DocObject: return the document object referenced in subname, if 'matrix' is None. Or, return a tuple (object, matrix) for each 'subname' and 'matrix' is @@ -168,15 +168,15 @@ Return -1 if element visibility is not supported or element not found, 0 if invi - Returns the group the object is in or None if it is not part of a group. - Note that an object can only be in a single group, hence only a single return + Returns the group the object is in or None if it is not part of a group. + Note that an object can only be in a single group, hence only a single return value. - Returns the GeoFeatureGroup, and hence the local coordinate system, the object - is in or None if it is not part of a group. Note that an object can only be + Returns the GeoFeatureGroup, and hence the local coordinate system, the object + is in or None if it is not part of a group. Note that an object can only be in a single group, hence only a single return value. diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index af09d7d9982a..c6e2e32b20be 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -76,7 +76,7 @@ Py::Object DocumentObjectPy::getDocument() const } } -PyObject* DocumentObjectPy::isAttachedToDocument(PyObject *args) +PyObject* DocumentObjectPy::isAttachedToDocument(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -87,27 +87,52 @@ PyObject* DocumentObjectPy::isAttachedToDocument(PyObject *args) return Py::new_reference_to(Py::Boolean(ok)); } -PyObject* DocumentObjectPy::addProperty(PyObject *args, PyObject *kwd) +PyObject* DocumentObjectPy::addProperty(PyObject* args, PyObject* kwd) { - char *sType,*sName=nullptr,*sGroup=nullptr,*sDoc=nullptr; - short attr=0; + char *sType, *sName = nullptr, *sGroup = nullptr, *sDoc = nullptr; + short attr = 0; std::string sDocStr; PyObject *ro = Py_False, *hd = Py_False; PyObject* enumVals = nullptr; - const std::array kwlist {"type","name","group","doc","attr","read_only","hidden","enum_vals",nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords( - args, kwd, "ss|sethO!O!O", kwlist, &sType, &sName, &sGroup, "utf-8", - &sDoc, &attr, &PyBool_Type, &ro, &PyBool_Type, &hd, &enumVals)) + const std::array kwlist {"type", + "name", + "group", + "doc", + "attr", + "read_only", + "hidden", + "enum_vals", + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "ss|sethO!O!O", + kwlist, + &sType, + &sName, + &sGroup, + "utf-8", + &sDoc, + &attr, + &PyBool_Type, + &ro, + &PyBool_Type, + &hd, + &enumVals)) { return nullptr; + } if (sDoc) { sDocStr = sDoc; PyMem_Free(sDoc); } - Property *prop = getDocumentObjectPtr()-> - addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr, - Base::asBoolean(ro), Base::asBoolean(hd)); + Property* prop = getDocumentObjectPtr()->addDynamicProperty(sType, + sName, + sGroup, + sDocStr.c_str(), + attr, + Base::asBoolean(ro), + Base::asBoolean(hd)); // enum support auto* propEnum = dynamic_cast(prop); @@ -118,26 +143,28 @@ PyObject* DocumentObjectPy::addProperty(PyObject *args, PyObject *kwd) return Py::new_reference_to(this); } -PyObject* DocumentObjectPy::removeProperty(PyObject *args) +PyObject* DocumentObjectPy::removeProperty(PyObject* args) { - char *sName; - if (!PyArg_ParseTuple(args, "s", &sName)) + char* sName; + if (!PyArg_ParseTuple(args, "s", &sName)) { return nullptr; + } bool ok = getDocumentObjectPtr()->removeDynamicProperty(sName); return Py_BuildValue("O", (ok ? Py_True : Py_False)); } -PyObject* DocumentObjectPy::supportedProperties(PyObject *args) +PyObject* DocumentObjectPy::supportedProperties(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } std::vector ary; Base::Type::getAllDerivedFrom(App::Property::getClassTypeId(), ary); Py::List res; - for (auto & it : ary) { - Base::BaseClass *data = static_cast(it.createInstance()); + for (auto& it : ary) { + Base::BaseClass* data = static_cast(it.createInstance()); if (data) { delete data; res.append(Py::String(it.getName())); @@ -146,19 +173,21 @@ PyObject* DocumentObjectPy::supportedProperties(PyObject *args) return Py::new_reference_to(res); } -PyObject* DocumentObjectPy::touch(PyObject * args) +PyObject* DocumentObjectPy::touch(PyObject* args) { - char *propName = nullptr; - if (!PyArg_ParseTuple(args, "|s",&propName)) + char* propName = nullptr; + if (!PyArg_ParseTuple(args, "|s", &propName)) { return nullptr; - if(propName) { - if(!propName[0]) { + } + if (propName) { + if (!propName[0]) { getDocumentObjectPtr()->touch(true); Py_Return; } auto prop = getDocumentObjectPtr()->getPropertyByName(propName); - if(!prop) + if (!prop) { throw Py::RuntimeError("Property not found"); + } prop->touch(); Py_Return; } @@ -167,18 +196,20 @@ PyObject* DocumentObjectPy::touch(PyObject * args) Py_Return; } -PyObject* DocumentObjectPy::purgeTouched(PyObject * args) +PyObject* DocumentObjectPy::purgeTouched(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentObjectPtr()->purgeTouched(); Py_Return; } -PyObject* DocumentObjectPy::enforceRecompute(PyObject * args) +PyObject* DocumentObjectPy::enforceRecompute(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentObjectPtr()->enforceRecompute(); Py_Return; } @@ -207,13 +238,13 @@ Py::List DocumentObjectPy::getState() const uptodate = false; list.append(Py::String("Restore")); } - if (object->testStatus(App::Expand)){ + if (object->testStatus(App::Expand)) { list.append(Py::String("Expanded")); } - if (object->testStatus(App::PartialObject)){ + if (object->testStatus(App::PartialObject)) { list.append(Py::String("Partial")); } - if (object->testStatus(App::ObjImporting)){ + if (object->testStatus(App::ObjImporting)) { list.append(Py::String("Importing")); } if (uptodate) { @@ -225,7 +256,7 @@ Py::List DocumentObjectPy::getState() const Py::Object DocumentObjectPy::getViewObject() const { try { - PyObject *dict = PySys_GetObject("modules"); + PyObject* dict = PySys_GetObject("modules"); if (!dict) { return Py::None(); } @@ -237,12 +268,13 @@ Py::Object DocumentObjectPy::getViewObject() const } // double-check that the module doesn't have a null pointer - Py::Module module(PyImport_ImportModule("FreeCADGui"),true); + Py::Module module(PyImport_ImportModule("FreeCADGui"), true); if (module.isNull() || !module.hasAttr("getDocument")) { - // in v0.14+, the GUI module can be loaded in console mode (but doesn't have all its document methods) + // in v0.14+, the GUI module can be loaded in console mode (but doesn't have all its + // document methods) return Py::None(); } - if(!getDocumentObjectPtr()->getDocument()) { + if (!getDocumentObjectPtr()->getDocument()) { throw Py::RuntimeError("Object has no document"); } const char* internalName = getDocumentObjectPtr()->getNameInDocument(); @@ -266,7 +298,7 @@ Py::Object DocumentObjectPy::getViewObject() const return Py::None(); } // FreeCADGui is loaded, so there must be wrong something else - throw; // re-throw + throw; // re-throw } } @@ -275,8 +307,9 @@ Py::List DocumentObjectPy::getInList() const Py::List ret; std::vector list = getDocumentObjectPtr()->getInList(); - for (auto It : list) + for (auto It : list) { ret.append(Py::Object(It->getPyObject(), true)); + } return ret; } @@ -287,8 +320,9 @@ Py::List DocumentObjectPy::getInListRecursive() const try { std::vector list = getDocumentObjectPtr()->getInListRecursive(); - for (auto It : list) + for (auto It : list) { ret.append(Py::Object(It->getPyObject(), true)); + } } catch (const Base::Exception& e) { throw Py::IndexError(e.what()); @@ -301,8 +335,9 @@ Py::List DocumentObjectPy::getOutList() const Py::List ret; std::vector list = getDocumentObjectPtr()->getOutList(); - for (auto It : list) + for (auto It : list) { ret.append(Py::Object(It->getPyObject(), true)); + } return ret; } @@ -314,8 +349,9 @@ Py::List DocumentObjectPy::getOutListRecursive() const std::vector list = getDocumentObjectPtr()->getOutListRecursive(); // create the python list for the output - for (auto It : list) + for (auto It : list) { ret.append(Py::Object(It->getPyObject(), true)); + } } catch (const Base::Exception& e) { throw Py::IndexError(e.what()); @@ -324,14 +360,15 @@ Py::List DocumentObjectPy::getOutListRecursive() const return ret; } -PyObject* DocumentObjectPy::setExpression(PyObject * args) +PyObject* DocumentObjectPy::setExpression(PyObject* args) { - char * path = nullptr; - PyObject * expr; - char * comment = nullptr; + char* path = nullptr; + PyObject* expr; + char* comment = nullptr; - if (!PyArg_ParseTuple(args, "sO|s", &path, &expr, &comment)) + if (!PyArg_ParseTuple(args, "sO|s", &path, &expr, &comment)) { return nullptr; + } App::ObjectIdentifier p(ObjectIdentifier::parse(getDocumentObjectPtr(), path)); @@ -340,10 +377,11 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args) Py_Return; } else if (PyUnicode_Check(expr)) { - const char * exprStr = PyUnicode_AsUTF8(expr); + const char* exprStr = PyUnicode_AsUTF8(expr); std::shared_ptr shared_expr(Expression::parse(getDocumentObjectPtr(), exprStr)); - if (shared_expr && comment) + if (shared_expr && comment) { shared_expr->comment = comment; + } getDocumentObjectPtr()->setExpression(p, shared_expr); Py_Return; @@ -352,22 +390,24 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args) throw Py::TypeError("String or None expected."); } -PyObject* DocumentObjectPy::clearExpression(PyObject * args) +PyObject* DocumentObjectPy::clearExpression(PyObject* args) { - char * path = nullptr; - if (!PyArg_ParseTuple(args, "s", &path)) + char* path = nullptr; + if (!PyArg_ParseTuple(args, "s", &path)) { return nullptr; + } App::ObjectIdentifier p(ObjectIdentifier::parse(getDocumentObjectPtr(), path)); getDocumentObjectPtr()->clearExpression(p); Py_Return; } -PyObject* DocumentObjectPy::evalExpression(PyObject *self, PyObject * args) +PyObject* DocumentObjectPy::evalExpression(PyObject* self, PyObject* args) { - const char *expr; - if (!PyArg_ParseTuple(args, "s", &expr)) + const char* expr; + if (!PyArg_ParseTuple(args, "s", &expr)) { return nullptr; + } // HINT: // The standard behaviour of Python for class methods is to always pass the class @@ -385,19 +425,23 @@ PyObject* DocumentObjectPy::evalExpression(PyObject *self, PyObject * args) obj = static_cast(self)->getDocumentObjectPtr(); } - PY_TRY { + PY_TRY + { std::shared_ptr shared_expr(Expression::parse(obj, expr)); - if (shared_expr) + if (shared_expr) { return Py::new_reference_to(shared_expr->getPyValue()); + } Py_Return; - } PY_CATCH + } + PY_CATCH } -PyObject* DocumentObjectPy::recompute(PyObject *args) +PyObject* DocumentObjectPy::recompute(PyObject* args) { - PyObject *recursive = Py_False; - if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &recursive)) + PyObject* recursive = Py_False; + if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &recursive)) { return nullptr; + } try { bool ok = getDocumentObjectPtr()->recomputeFeature(Base::asBoolean(recursive)); @@ -408,10 +452,11 @@ PyObject* DocumentObjectPy::recompute(PyObject *args) } } -PyObject* DocumentObjectPy::isValid(PyObject *args) +PyObject* DocumentObjectPy::isValid(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { bool ok = getDocumentObjectPtr()->isValid(); @@ -422,10 +467,11 @@ PyObject* DocumentObjectPy::isValid(PyObject *args) } } -PyObject* DocumentObjectPy::getStatusString(PyObject *args) +PyObject* DocumentObjectPy::getStatusString(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { Py::String text(getDocumentObjectPtr()->getStatusString()); @@ -436,9 +482,10 @@ PyObject* DocumentObjectPy::getStatusString(PyObject *args) } } -PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds) +PyObject* DocumentObjectPy::getSubObject(PyObject* args, PyObject* keywds) { - enum class ReturnType { + enum class ReturnType + { PyObject = 0, DocObject = 1, DocAndPyObject = 2, @@ -448,19 +495,33 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds) LinkAndMatrix = 6 }; - PyObject *obj; + PyObject* obj; short retType = 0; - PyObject *pyMat = nullptr; - PyObject *doTransform = Py_True; + PyObject* pyMat = nullptr; + PyObject* doTransform = Py_True; short depth = 0; - static const std::array kwlist {"subname", "retType", "matrix", "transform", "depth", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "O|hO!O!h", kwlist, &obj, &retType, &Base::MatrixPy::Type, - &pyMat, &PyBool_Type, &doTransform, &depth)) { + static const std::array kwlist {"subname", + "retType", + "matrix", + "transform", + "depth", + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "O|hO!O!h", + kwlist, + &obj, + &retType, + &Base::MatrixPy::Type, + &pyMat, + &PyBool_Type, + &doTransform, + &depth)) { return nullptr; } - if (retType < 0 || static_cast (retType) > kwlist.size()) { + if (retType < 0 || static_cast(retType) > kwlist.size()) { PyErr_SetString(PyExc_ValueError, "invalid retType, can only be integer 0~6"); return nullptr; } @@ -493,12 +554,15 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds) bool transform = Base::asBoolean(doTransform); - struct SubInfo { - App::DocumentObject *sobj{nullptr}; + struct SubInfo + { + App::DocumentObject* sobj {nullptr}; Py::Object obj; Py::Object pyObj; Base::Matrix4D mat; - explicit SubInfo(const Base::Matrix4D &mat) : mat(mat){} + explicit SubInfo(const Base::Matrix4D& mat) + : mat(mat) + {} }; Base::Matrix4D mat; @@ -506,50 +570,66 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds) mat = *static_cast(pyMat)->getMatrixPtr(); } - PY_TRY { + PY_TRY + { std::vector ret; - for(const auto &sub : subs) { + for (const auto& sub : subs) { ret.emplace_back(mat); - auto &info = ret.back(); - PyObject *pyObj = nullptr; - - info.sobj = getDocumentObjectPtr()->getSubObject(sub.c_str(), - retEnum != ReturnType::PyObject && - retEnum != ReturnType::DocAndPyObject ? nullptr : &pyObj, - &info.mat, transform, depth); - if (pyObj) + auto& info = ret.back(); + PyObject* pyObj = nullptr; + + info.sobj = getDocumentObjectPtr()->getSubObject( + sub.c_str(), + retEnum != ReturnType::PyObject && retEnum != ReturnType::DocAndPyObject ? nullptr + : &pyObj, + &info.mat, + transform, + depth); + if (pyObj) { info.pyObj = Py::asObject(pyObj); - if (info.sobj) + } + if (info.sobj) { info.obj = Py::asObject(info.sobj->getPyObject()); + } } - if (ret.empty()) + if (ret.empty()) { Py_Return; + } auto getReturnValue = [retEnum, pyMat](SubInfo& ret) -> Py::Object { - if (retEnum == ReturnType::PyObject) + if (retEnum == ReturnType::PyObject) { return ret.pyObj; - else if (retEnum == ReturnType::DocObject && !pyMat) + } + else if (retEnum == ReturnType::DocObject && !pyMat) { return ret.obj; - else if (!ret.sobj) + } + else if (!ret.sobj) { return Py::None(); - else if (retEnum == ReturnType::Placement) + } + else if (retEnum == ReturnType::Placement) { return Py::Placement(Base::Placement(ret.mat)); - else if (retEnum == ReturnType::Matrix) + } + else if (retEnum == ReturnType::Matrix) { return Py::Matrix(ret.mat); - else if (retEnum == ReturnType::LinkAndPlacement || retEnum == ReturnType::LinkAndMatrix) { + } + else if (retEnum == ReturnType::LinkAndPlacement + || retEnum == ReturnType::LinkAndMatrix) { ret.sobj->getLinkedObject(true, &ret.mat, false); - if (retEnum == ReturnType::LinkAndPlacement) + if (retEnum == ReturnType::LinkAndPlacement) { return Py::Placement(Base::Placement(ret.mat)); - else + } + else { return Py::Matrix(ret.mat); + } } else { Py::Tuple rret(retEnum == ReturnType::DocObject ? 2 : 3); rret.setItem(0, ret.obj); rret.setItem(1, Py::asObject(new Base::MatrixPy(ret.mat))); - if (retEnum != ReturnType::DocObject) + if (retEnum != ReturnType::DocObject) { rret.setItem(2, ret.pyObj); + } return rret; } }; @@ -559,7 +639,7 @@ PyObject* DocumentObjectPy::getSubObject(PyObject *args, PyObject *keywds) } Py::Tuple tuple(ret.size()); - for(size_t i=0; igetSubObjectList(subname)) + PY_TRY + { + for (auto o : getDocumentObjectPtr()->getSubObjectList(subname)) { res.append(Py::asObject(o->getPyObject())); + } return Py::new_reference_to(res); - }PY_CATCH + } + PY_CATCH } -PyObject* DocumentObjectPy::getSubObjects(PyObject *args) { +PyObject* DocumentObjectPy::getSubObjects(PyObject* args) +{ int reason = 0; - if (!PyArg_ParseTuple(args, "|i", &reason)) + if (!PyArg_ParseTuple(args, "|i", &reason)) { return nullptr; + } - PY_TRY { + PY_TRY + { auto names = getDocumentObjectPtr()->getSubObjects(reason); Py::Tuple pyObjs(names.size()); - for(size_t i=0;i kwlist {"recursive","matrix","transform","depth", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, "|O!OO!h", kwlist, - &PyBool_Type, &recursive, &pyMat, &PyBool_Type, &transform, &depth)) { + static const std::array kwlist {"recursive", + "matrix", + "transform", + "depth", + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|O!OO!h", + kwlist, + &PyBool_Type, + &recursive, + &pyMat, + &PyBool_Type, + &transform, + &depth)) { return nullptr; } - PY_TRY { - Base::PyTypeCheck(&pyMat, &Base::MatrixPy::Type, "expect argument 'matrix' to be of type Base.Matrix"); + PY_TRY + { + Base::PyTypeCheck(&pyMat, + &Base::MatrixPy::Type, + "expect argument 'matrix' to be of type Base.Matrix"); Base::Matrix4D _mat; - Base::Matrix4D *mat = nullptr; + Base::Matrix4D* mat = nullptr; if (pyMat) { _mat = *static_cast(pyMat)->getMatrixPtr(); mat = &_mat; } - auto linked = getDocumentObjectPtr()->getLinkedObject( - Base::asBoolean(recursive), mat, Base::asBoolean(transform), depth); - if (!linked) + auto linked = getDocumentObjectPtr()->getLinkedObject(Base::asBoolean(recursive), + mat, + Base::asBoolean(transform), + depth); + if (!linked) { linked = getDocumentObjectPtr(); - auto pyObj = Py::Object(linked->getPyObject(),true); + } + auto pyObj = Py::Object(linked->getPyObject(), true); if (mat) { Py::Tuple ret(2); - ret.setItem(0,pyObj); - ret.setItem(1,Py::asObject(new Base::MatrixPy(*mat))); + ret.setItem(0, pyObj); + ret.setItem(1, Py::asObject(new Base::MatrixPy(*mat))); return Py::new_reference_to(ret); } @@ -631,44 +739,56 @@ PyObject* DocumentObjectPy::getLinkedObject(PyObject *args, PyObject *keywds) PY_CATCH; } -PyObject* DocumentObjectPy::isElementVisible(PyObject *args) +PyObject* DocumentObjectPy::isElementVisible(PyObject* args) { - char *element = nullptr; - if (!PyArg_ParseTuple(args, "s", &element)) + char* element = nullptr; + if (!PyArg_ParseTuple(args, "s", &element)) { return nullptr; - PY_TRY { + } + PY_TRY + { return Py_BuildValue("h", getDocumentObjectPtr()->isElementVisible(element)); - } PY_CATCH; + } + PY_CATCH; } -PyObject* DocumentObjectPy::setElementVisible(PyObject *args) +PyObject* DocumentObjectPy::setElementVisible(PyObject* args) { - char *element = nullptr; - PyObject *visible = Py_True; - if (!PyArg_ParseTuple(args, "s|O!", &element, &PyBool_Type, &visible)) + char* element = nullptr; + PyObject* visible = Py_True; + if (!PyArg_ParseTuple(args, "s|O!", &element, &PyBool_Type, &visible)) { return nullptr; - PY_TRY { - return Py_BuildValue("h", getDocumentObjectPtr()->setElementVisible(element, Base::asBoolean(visible))); - } PY_CATCH; + } + PY_TRY + { + return Py_BuildValue( + "h", + getDocumentObjectPtr()->setElementVisible(element, Base::asBoolean(visible))); + } + PY_CATCH; } -PyObject* DocumentObjectPy::hasChildElement(PyObject *args) +PyObject* DocumentObjectPy::hasChildElement(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; - PY_TRY { - return Py_BuildValue("O", getDocumentObjectPtr()->hasChildElement()?Py_True:Py_False); - } PY_CATCH; + } + PY_TRY + { + return Py_BuildValue("O", getDocumentObjectPtr()->hasChildElement() ? Py_True : Py_False); + } + PY_CATCH; } -PyObject* DocumentObjectPy::getParentGroup(PyObject *args) +PyObject* DocumentObjectPy::getParentGroup(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { auto grp = GroupExtension::getGroupOfObject(getDocumentObjectPtr()); - if(!grp) { + if (!grp) { Py_INCREF(Py_None); return Py_None; } @@ -679,14 +799,15 @@ PyObject* DocumentObjectPy::getParentGroup(PyObject *args) } } -PyObject* DocumentObjectPy::getParentGeoFeatureGroup(PyObject *args) +PyObject* DocumentObjectPy::getParentGeoFeatureGroup(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { auto grp = GeoFeatureGroupExtension::getGroupOfObject(getDocumentObjectPtr()); - if(!grp) { + if (!grp) { Py_INCREF(Py_None); return Py_None; } @@ -697,14 +818,15 @@ PyObject* DocumentObjectPy::getParentGeoFeatureGroup(PyObject *args) } } -PyObject* DocumentObjectPy::getParent(PyObject *args) +PyObject* DocumentObjectPy::getParent(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { auto grp = getDocumentObjectPtr()->getFirstParent(); - if(!grp) { + if (!grp) { Py_INCREF(Py_None); return Py_None; } @@ -725,15 +847,15 @@ Py::Boolean DocumentObjectPy::getMustExecute() const } } -PyObject* DocumentObjectPy::getPathsByOutList(PyObject *args) +PyObject* DocumentObjectPy::getPathsByOutList(PyObject* args) { PyObject* o; - if (!PyArg_ParseTuple(args, "O!", &DocumentObjectPy::Type, &o)) + if (!PyArg_ParseTuple(args, "O!", &DocumentObjectPy::Type, &o)) { return nullptr; + } try { - DocumentObject* target = static_cast - (o)->getDocumentObjectPtr(); + DocumentObject* target = static_cast(o)->getDocumentObjectPtr(); auto array = getDocumentObjectPtr()->getPathsByOutList(target); Py::List list; for (const auto& it : array) { @@ -766,100 +888,120 @@ PyObject* DocumentObjectPy::getElementMapVersion(PyObject* args) Py::String(getDocumentObjectPtr()->getElementMapVersion(prop, Base::asBoolean(restored)))); } -PyObject *DocumentObjectPy::getCustomAttributes(const char* ) const +PyObject* DocumentObjectPy::getCustomAttributes(const char*) const { - return nullptr; + return nullptr; } -//remove -int DocumentObjectPy::setCustomAttributes(const char* , PyObject *) +// remove +int DocumentObjectPy::setCustomAttributes(const char*, PyObject*) { return 0; } -Py::Int DocumentObjectPy::getID() const { +Py::Int DocumentObjectPy::getID() const +{ return Py::Int(getDocumentObjectPtr()->getID()); } -Py::Boolean DocumentObjectPy::getRemoving() const { +Py::Boolean DocumentObjectPy::getRemoving() const +{ return {getDocumentObjectPtr()->testStatus(ObjectStatus::Remove)}; } -PyObject *DocumentObjectPy::resolve(PyObject *args) +PyObject* DocumentObjectPy::resolve(PyObject* args) { - const char *subname; - if (!PyArg_ParseTuple(args, "s",&subname)) + const char* subname; + if (!PyArg_ParseTuple(args, "s", &subname)) { return nullptr; + } - PY_TRY { + PY_TRY + { std::string elementName; - const char *subElement = nullptr; - App::DocumentObject *parent = nullptr; - auto obj = getDocumentObjectPtr()->resolve(subname,&parent,&elementName,&subElement); + const char* subElement = nullptr; + App::DocumentObject* parent = nullptr; + auto obj = getDocumentObjectPtr()->resolve(subname, &parent, &elementName, &subElement); Py::Tuple ret(4); - ret.setItem(0,obj?Py::Object(obj->getPyObject(),true):Py::None()); - ret.setItem(1,parent?Py::Object(parent->getPyObject(),true):Py::None()); - ret.setItem(2,Py::String(elementName.c_str())); - ret.setItem(3,Py::String(subElement?subElement:"")); + ret.setItem(0, obj ? Py::Object(obj->getPyObject(), true) : Py::None()); + ret.setItem(1, parent ? Py::Object(parent->getPyObject(), true) : Py::None()); + ret.setItem(2, Py::String(elementName.c_str())); + ret.setItem(3, Py::String(subElement ? subElement : "")); return Py::new_reference_to(ret); - } PY_CATCH; + } + PY_CATCH; Py_Return; } -PyObject *DocumentObjectPy::resolveSubElement(PyObject *args) +PyObject* DocumentObjectPy::resolveSubElement(PyObject* args) { - const char *subname; - PyObject *append = Py_False; + const char* subname; + PyObject* append = Py_False; int type = 0; - if (!PyArg_ParseTuple(args, "s|O!i",&subname,&PyBool_Type,&append,&type)) + if (!PyArg_ParseTuple(args, "s|O!i", &subname, &PyBool_Type, &append, &type)) { return nullptr; + } - PY_TRY { + PY_TRY + { ElementNamePair elementName; - auto obj = GeoFeature::resolveElement(getDocumentObjectPtr(), subname,elementName, - Base::asBoolean(append), static_cast(type)); + auto obj = GeoFeature::resolveElement(getDocumentObjectPtr(), + subname, + elementName, + Base::asBoolean(append), + static_cast(type)); Py::Tuple ret(3); - ret.setItem(0,obj?Py::Object(obj->getPyObject(),true):Py::None()); - ret.setItem(1,Py::String(elementName.newName)); - ret.setItem(2,Py::String(elementName.oldName)); + ret.setItem(0, obj ? Py::Object(obj->getPyObject(), true) : Py::None()); + ret.setItem(1, Py::String(elementName.newName)); + ret.setItem(2, Py::String(elementName.oldName)); return Py::new_reference_to(ret); - } PY_CATCH; + } + PY_CATCH; Py_Return; } -Py::List DocumentObjectPy::getParents() const { +Py::List DocumentObjectPy::getParents() const +{ Py::List ret; - for(auto &v : getDocumentObjectPtr()->getParents()) - ret.append(Py::TupleN(Py::Object(v.first->getPyObject(),true),Py::String(v.second))); + for (auto& v : getDocumentObjectPtr()->getParents()) { + ret.append(Py::TupleN(Py::Object(v.first->getPyObject(), true), Py::String(v.second))); + } return ret; } -PyObject *DocumentObjectPy::adjustRelativeLinks(PyObject *args) { - PyObject *pyobj; - PyObject *recursive = Py_True; - if (!PyArg_ParseTuple(args, "O!|O",&DocumentObjectPy::Type,&pyobj,&recursive)) +PyObject* DocumentObjectPy::adjustRelativeLinks(PyObject* args) +{ + PyObject* pyobj; + PyObject* recursive = Py_True; + if (!PyArg_ParseTuple(args, "O!|O", &DocumentObjectPy::Type, &pyobj, &recursive)) { return nullptr; - PY_TRY { + } + PY_TRY + { auto obj = static_cast(pyobj)->getDocumentObjectPtr(); auto inList = obj->getInListEx(true); inList.insert(obj); - std::set visited; - return Py::new_reference_to(Py::Boolean( - getDocumentObjectPtr()->adjustRelativeLinks(inList, - Base::asBoolean(recursive) ? &visited : nullptr))); - }PY_CATCH + std::set visited; + return Py::new_reference_to(Py::Boolean(getDocumentObjectPtr()->adjustRelativeLinks( + inList, + Base::asBoolean(recursive) ? &visited : nullptr))); + } + PY_CATCH } -Py::String DocumentObjectPy::getOldLabel() const { +Py::String DocumentObjectPy::getOldLabel() const +{ return {getDocumentObjectPtr()->getOldLabel()}; } -Py::Boolean DocumentObjectPy::getNoTouch() const { +Py::Boolean DocumentObjectPy::getNoTouch() const +{ return {getDocumentObjectPtr()->testStatus(ObjectStatus::NoTouch)}; } -void DocumentObjectPy::setNoTouch(Py::Boolean value) { - getDocumentObjectPtr()->setStatus(ObjectStatus::NoTouch,value.isTrue()); +void DocumentObjectPy::setNoTouch(Py::Boolean value) +{ + getDocumentObjectPtr()->setStatus(ObjectStatus::NoTouch, value.isTrue()); } diff --git a/src/App/DocumentObserver.cpp b/src/App/DocumentObserver.cpp index 896f6c1f380b..78b8574302d2 100644 --- a/src/App/DocumentObserver.cpp +++ b/src/App/DocumentObserver.cpp @@ -57,8 +57,9 @@ DocumentT::~DocumentT() = default; void DocumentT::operator=(const DocumentT& doc) { - if (this == &doc) + if (this == &doc) { return; + } document = doc.document; } @@ -77,7 +78,7 @@ Document* DocumentT::getDocument() const return GetApplication().getDocument(document.c_str()); } -const std::string &DocumentT::getDocumentName() const +const std::string& DocumentT::getDocumentName() const { return document; } @@ -93,12 +94,12 @@ std::string DocumentT::getDocumentPython() const DocumentObjectT::DocumentObjectT() = default; -DocumentObjectT::DocumentObjectT(const DocumentObjectT &other) +DocumentObjectT::DocumentObjectT(const DocumentObjectT& other) { *this = other; } -DocumentObjectT::DocumentObjectT(DocumentObjectT &&other) +DocumentObjectT::DocumentObjectT(DocumentObjectT&& other) { *this = std::move(other); } @@ -115,25 +116,29 @@ DocumentObjectT::DocumentObjectT(const Property* prop) DocumentObjectT::DocumentObjectT(const Document* doc, const std::string& objName) { - if (doc && doc->getName()) + if (doc && doc->getName()) { document = doc->getName(); + } object = objName; } -DocumentObjectT::DocumentObjectT(const char *docName, const char *objName) +DocumentObjectT::DocumentObjectT(const char* docName, const char* objName) { - if(docName) + if (docName) { document = docName; - if(objName) + } + if (objName) { object = objName; + } } DocumentObjectT::~DocumentObjectT() = default; -DocumentObjectT &DocumentObjectT::operator=(const DocumentObjectT& obj) +DocumentObjectT& DocumentObjectT::operator=(const DocumentObjectT& obj) { - if (this == &obj) + if (this == &obj) { return *this; + } object = obj.object; label = obj.label; document = obj.document; @@ -141,10 +146,11 @@ DocumentObjectT &DocumentObjectT::operator=(const DocumentObjectT& obj) return *this; } -DocumentObjectT &DocumentObjectT::operator=(DocumentObjectT&& obj) +DocumentObjectT& DocumentObjectT::operator=(DocumentObjectT&& obj) { - if (this == &obj) + if (this == &obj) { return *this; + } object = std::move(obj.object); label = std::move(obj.label); document = std::move(obj.document); @@ -154,12 +160,13 @@ DocumentObjectT &DocumentObjectT::operator=(DocumentObjectT&& obj) void DocumentObjectT::operator=(const DocumentObject* obj) { - if(!obj || !obj->isAttachedToDocument()) { + if (!obj || !obj->isAttachedToDocument()) { object.clear(); label.clear(); document.clear(); property.clear(); - } else { + } + else { object = obj->getNameInDocument(); label = obj->Label.getValue(); document = obj->getDocument()->getName(); @@ -167,16 +174,16 @@ void DocumentObjectT::operator=(const DocumentObject* obj) } } -void DocumentObjectT::operator=(const Property *prop) { - if(!prop || !prop->hasName() - || !prop->getContainer() - || !prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - { +void DocumentObjectT::operator=(const Property* prop) +{ + if (!prop || !prop->hasName() || !prop->getContainer() + || !prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { object.clear(); label.clear(); document.clear(); property.clear(); - } else { + } + else { auto obj = static_cast(prop->getContainer()); object = obj->getNameInDocument(); label = obj->Label.getValue(); @@ -185,10 +192,9 @@ void DocumentObjectT::operator=(const Property *prop) { } } -bool DocumentObjectT::operator==(const DocumentObjectT &other) const { - return document == other.document - && object == other.object - && label == other.label +bool DocumentObjectT::operator==(const DocumentObjectT& other) const +{ + return document == other.document && object == other.object && label == other.label && property == other.property; } @@ -219,12 +225,12 @@ DocumentObject* DocumentObjectT::getObject() const return obj; } -const std::string &DocumentObjectT::getObjectName() const +const std::string& DocumentObjectT::getObjectName() const { return object; } -const std::string &DocumentObjectT::getObjectLabel() const +const std::string& DocumentObjectT::getObjectLabel() const { return label; } @@ -236,7 +242,8 @@ std::string DocumentObjectT::getObjectPython() const return str.str(); } -const std::string &DocumentObjectT::getPropertyName() const { +const std::string& DocumentObjectT::getPropertyName() const +{ return property; } @@ -244,15 +251,18 @@ std::string DocumentObjectT::getPropertyPython() const { std::stringstream str; str << getObjectPython(); - if (!property.empty()) + if (!property.empty()) { str << '.' << property; + } return str.str(); } -Property *DocumentObjectT::getProperty() const { +Property* DocumentObjectT::getProperty() const +{ auto obj = getObject(); - if(obj) + if (obj) { return obj->getPropertyByName(property.c_str()); + } return nullptr; } @@ -260,86 +270,95 @@ Property *DocumentObjectT::getProperty() const { SubObjectT::SubObjectT() = default; -SubObjectT::SubObjectT(const SubObjectT &) = default; +SubObjectT::SubObjectT(const SubObjectT&) = default; -SubObjectT::SubObjectT(SubObjectT &&other) - :DocumentObjectT(std::move(other)), subname(std::move(other.subname)) -{ -} +SubObjectT::SubObjectT(SubObjectT&& other) + : DocumentObjectT(std::move(other)) + , subname(std::move(other.subname)) +{} -SubObjectT::SubObjectT(const DocumentObject *obj, const char *s) - :DocumentObjectT(obj),subname(s?s:"") -{ -} +SubObjectT::SubObjectT(const DocumentObject* obj, const char* s) + : DocumentObjectT(obj) + , subname(s ? s : "") +{} -SubObjectT::SubObjectT(const DocumentObject *obj) - :DocumentObjectT(obj) -{ -} +SubObjectT::SubObjectT(const DocumentObject* obj) + : DocumentObjectT(obj) +{} -SubObjectT::SubObjectT(const DocumentObjectT& obj, const char *s) - :DocumentObjectT(obj),subname(s?s:"") -{ -} +SubObjectT::SubObjectT(const DocumentObjectT& obj, const char* s) + : DocumentObjectT(obj) + , subname(s ? s : "") +{} -SubObjectT::SubObjectT(const char *docName, const char *objName, const char *s) - :DocumentObjectT(docName,objName), subname(s?s:"") -{ -} +SubObjectT::SubObjectT(const char* docName, const char* objName, const char* s) + : DocumentObjectT(docName, objName) + , subname(s ? s : "") +{} -bool SubObjectT::operator<(const SubObjectT &other) const { - if(getDocumentName() < other.getDocumentName()) +bool SubObjectT::operator<(const SubObjectT& other) const +{ + if (getDocumentName() < other.getDocumentName()) { return true; - if(getDocumentName() > other.getDocumentName()) + } + if (getDocumentName() > other.getDocumentName()) { return false; - if(getObjectName() < other.getObjectName()) + } + if (getObjectName() < other.getObjectName()) { return true; - if(getObjectName() > other.getObjectName()) + } + if (getObjectName() > other.getObjectName()) { return false; - if(getSubName() < other.getSubName()) + } + if (getSubName() < other.getSubName()) { return true; - if(getSubName() > other.getSubName()) + } + if (getSubName() > other.getSubName()) { return false; + } return getPropertyName() < other.getPropertyName(); } -SubObjectT &SubObjectT::operator=(const SubObjectT& other) +SubObjectT& SubObjectT::operator=(const SubObjectT& other) { - if (this == &other) + if (this == &other) { return *this; + } static_cast(*this) = other; subname = other.subname; return *this; } -SubObjectT &SubObjectT::operator=(SubObjectT &&other) +SubObjectT& SubObjectT::operator=(SubObjectT&& other) { - if (this == &other) + if (this == &other) { return *this; + } static_cast(*this) = std::move(other); subname = std::move(other.subname); return *this; } -SubObjectT &SubObjectT::operator=(const DocumentObjectT &other) +SubObjectT& SubObjectT::operator=(const DocumentObjectT& other) { - if (this == &other) + if (this == &other) { return *this; + } static_cast(*this) = other; subname.clear(); return *this; } -SubObjectT &SubObjectT::operator=(const DocumentObject *other) +SubObjectT& SubObjectT::operator=(const DocumentObject* other) { static_cast(*this) = other; subname.clear(); return *this; } -bool SubObjectT::operator==(const SubObjectT &other) const { - return static_cast(*this) == other - && subname == other.subname; +bool SubObjectT::operator==(const SubObjectT& other) const +{ + return static_cast(*this) == other && subname == other.subname; } namespace @@ -430,19 +449,23 @@ SubObjectT App::SubObjectT::normalized(NormalizeOptions options) const return res; } -void SubObjectT::setSubName(const char *s) { - subname = s?s:""; +void SubObjectT::setSubName(const char* s) +{ + subname = s ? s : ""; } -const std::string &SubObjectT::getSubName() const { +const std::string& SubObjectT::getSubName() const +{ return subname; } -std::string SubObjectT::getSubNameNoElement() const { +std::string SubObjectT::getSubNameNoElement() const +{ return Data::noElementName(subname.c_str()); } -const char *SubObjectT::getElementName() const { +const char* SubObjectT::getElementName() const +{ return Data::findElementName(subname.c_str()); } @@ -457,90 +480,107 @@ bool SubObjectT::hasSubElement() const return element && (element[0] != '\0'); } -std::string SubObjectT::getNewElementName() const { +std::string SubObjectT::getNewElementName() const +{ ElementNamePair element; auto obj = getObject(); - if(!obj) + if (!obj) { return {}; - GeoFeature::resolveElement(obj,subname.c_str(),element); + } + GeoFeature::resolveElement(obj, subname.c_str(), element); return std::move(element.newName); } -std::string SubObjectT::getOldElementName(int *index) const { +std::string SubObjectT::getOldElementName(int* index) const +{ ElementNamePair element; auto obj = getObject(); - if(!obj) + if (!obj) { return {}; - GeoFeature::resolveElement(obj,subname.c_str(),element); - if(!index) + } + GeoFeature::resolveElement(obj, subname.c_str(), element); + if (!index) { return std::move(element.oldName); + } std::size_t pos = element.oldName.find_first_of("0123456789"); - if(pos == std::string::npos) + if (pos == std::string::npos) { *index = -1; + } else { - *index = std::atoi(element.oldName.c_str()+pos); + *index = std::atoi(element.oldName.c_str() + pos); element.oldName.resize(pos); } return std::move(element.oldName); } -App::DocumentObject *SubObjectT::getSubObject() const { +App::DocumentObject* SubObjectT::getSubObject() const +{ auto obj = getObject(); - if(obj) + if (obj) { return obj->getSubObject(subname.c_str()); + } return nullptr; } -std::string SubObjectT::getSubObjectPython(bool force) const { - if(!force && subname.empty()) +std::string SubObjectT::getSubObjectPython(bool force) const +{ + if (!force && subname.empty()) { return getObjectPython(); + } std::stringstream str; - str << "(" << getObjectPython() << ",u'" - << Base::Tools::escapedUnicodeFromUtf8(subname.c_str()) << "')"; + str << "(" << getObjectPython() << ",u'" << Base::Tools::escapedUnicodeFromUtf8(subname.c_str()) + << "')"; return str.str(); } -std::vector SubObjectT::getSubObjectList() const { +std::vector SubObjectT::getSubObjectList() const +{ auto obj = getObject(); - if(obj) + if (obj) { return obj->getSubObjectList(subname.c_str()); + } return {}; } -std::string SubObjectT::getObjectFullName(const char *docName) const +std::string SubObjectT::getObjectFullName(const char* docName) const { std::ostringstream ss; if (!docName || getDocumentName() != docName) { ss << getDocumentName(); if (auto doc = getDocument()) { - if (doc->Label.getStrValue() != getDocumentName()) + if (doc->Label.getStrValue() != getDocumentName()) { ss << "(" << doc->Label.getValue() << ")"; + } } ss << "#"; } ss << getObjectName(); - if (!getObjectLabel().empty() && getObjectLabel() != getObjectName()) + if (!getObjectLabel().empty() && getObjectLabel() != getObjectName()) { ss << " (" << getObjectLabel() << ")"; + } return ss.str(); } -std::string SubObjectT::getSubObjectFullName(const char *docName) const +std::string SubObjectT::getSubObjectFullName(const char* docName) const { - if (subname.empty()) + if (subname.empty()) { return getObjectFullName(docName); + } std::ostringstream ss; if (!docName || getDocumentName() != docName) { ss << getDocumentName(); if (auto doc = getDocument()) { - if (doc->Label.getStrValue() != getDocumentName()) + if (doc->Label.getStrValue() != getDocumentName()) { ss << "(" << doc->Label.getValue() << ")"; + } } ss << "#"; } ss << getObjectName() << "." << subname; auto sobj = getSubObject(); - if (sobj && sobj->Label.getStrValue() != sobj->getNameInDocument()) + if (sobj && sobj->Label.getStrValue() != sobj->getNameInDocument()) { ss << " (" << sobj->Label.getValue() << ")"; + } return ss.str(); } @@ -548,10 +588,9 @@ std::string SubObjectT::getSubObjectFullName(const char *docName) const PropertyLinkT::PropertyLinkT() : toPython("None") -{ -} +{} -PropertyLinkT::PropertyLinkT(DocumentObject *obj) +PropertyLinkT::PropertyLinkT(DocumentObject* obj) : PropertyLinkT() { if (obj) { @@ -563,15 +602,16 @@ PropertyLinkT::PropertyLinkT(DocumentObject *obj) } } -PropertyLinkT::PropertyLinkT(DocumentObject *obj, const std::vector& subNames) +PropertyLinkT::PropertyLinkT(DocumentObject* obj, const std::vector& subNames) : PropertyLinkT() { if (obj) { std::ostringstream str; DocumentObjectT objT(obj); str << "(" << objT.getObjectPython() << ",["; - for(const auto& it : subNames) + for (const auto& it : subNames) { str << "'" << it << "',"; + } str << "])"; toPython = str.str(); @@ -585,8 +625,9 @@ PropertyLinkT::PropertyLinkT(const std::vector& objs) std::stringstream str; str << "["; for (std::size_t i = 0; i < objs.size(); i++) { - if (i > 0) + if (i > 0) { str << ", "; + } App::DocumentObject* obj = objs[i]; if (obj) { @@ -602,17 +643,20 @@ PropertyLinkT::PropertyLinkT(const std::vector& objs) } } -PropertyLinkT::PropertyLinkT(const std::vector& objs, const std::vector& subNames) +PropertyLinkT::PropertyLinkT(const std::vector& objs, + const std::vector& subNames) : PropertyLinkT() { if (!objs.empty() && objs.size() == subNames.size()) { std::stringstream str; str << "["; for (std::size_t i = 0; i < subNames.size(); i++) { - if (i>0) + if (i > 0) { str << ",("; - else + } + else { str << "("; + } App::DocumentObject* obj = objs[i]; if (obj) { @@ -639,22 +683,28 @@ std::string PropertyLinkT::getPropertyPython() const // ----------------------------------------------------------------------------- -class DocumentWeakPtrT::Private { +class DocumentWeakPtrT::Private +{ public: - explicit Private(App::Document* doc) : _document(doc) { + explicit Private(App::Document* doc) + : _document(doc) + { if (doc) { - //NOLINTBEGIN - connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind - (&Private::deletedDocument, this, sp::_1)); - //NOLINTEND + // NOLINTBEGIN + connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect( + std::bind(&Private::deletedDocument, this, sp::_1)); + // NOLINTEND } } - void deletedDocument(const App::Document& doc) { - if (_document == &doc) + void deletedDocument(const App::Document& doc) + { + if (_document == &doc) { reset(); + } } - void reset() { + void reset() + { connectApplicationDeletedDocument.disconnect(); _document = nullptr; } @@ -665,9 +715,8 @@ class DocumentWeakPtrT::Private { }; DocumentWeakPtrT::DocumentWeakPtrT(App::Document* doc) noexcept - : d(new Private(doc)) -{ -} + : d(new Private(doc)) +{} DocumentWeakPtrT::~DocumentWeakPtrT() = default; @@ -693,56 +742,65 @@ App::Document* DocumentWeakPtrT::operator->() const noexcept // ----------------------------------------------------------------------------- -class DocumentObjectWeakPtrT::Private { +class DocumentObjectWeakPtrT::Private +{ public: - explicit Private(App::DocumentObject* obj) : object(obj) { + explicit Private(App::DocumentObject* obj) + : object(obj) + { set(obj); } - void deletedDocument(const App::Document& doc) { + void deletedDocument(const App::Document& doc) + { // When deleting document then there is no way to undo it if (object && object->getDocument() == &doc) { reset(); } } - void createdObject(const App::DocumentObject& obj) noexcept { + void createdObject(const App::DocumentObject& obj) noexcept + { // When undoing the removal if (object == &obj) { indocument = true; } } - void deletedObject(const App::DocumentObject& obj) noexcept { + void deletedObject(const App::DocumentObject& obj) noexcept + { if (object == &obj) { indocument = false; } } - void reset() { + void reset() + { connectApplicationDeletedDocument.disconnect(); connectDocumentCreatedObject.disconnect(); connectDocumentDeletedObject.disconnect(); object = nullptr; indocument = false; } - void set(App::DocumentObject* obj) { + void set(App::DocumentObject* obj) + { object = obj; if (obj) { - //NOLINTBEGIN + // NOLINTBEGIN indocument = true; - connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind - (&Private::deletedDocument, this, sp::_1)); + connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect( + std::bind(&Private::deletedDocument, this, sp::_1)); App::Document* doc = obj->getDocument(); - connectDocumentCreatedObject = doc->signalNewObject.connect(std::bind - (&Private::createdObject, this, sp::_1)); - connectDocumentDeletedObject = doc->signalDeletedObject.connect(std::bind - (&Private::deletedObject, this, sp::_1)); - //NOLINTEND + connectDocumentCreatedObject = + doc->signalNewObject.connect(std::bind(&Private::createdObject, this, sp::_1)); + connectDocumentDeletedObject = + doc->signalDeletedObject.connect(std::bind(&Private::deletedObject, this, sp::_1)); + // NOLINTEND } } - App::DocumentObject* get() const noexcept { + App::DocumentObject* get() const noexcept + { return indocument ? object : nullptr; } App::DocumentObject* object; - bool indocument{false}; + bool indocument {false}; using Connection = boost::signals2::scoped_connection; Connection connectApplicationDeletedDocument; Connection connectDocumentCreatedObject; @@ -750,9 +808,8 @@ class DocumentObjectWeakPtrT::Private { }; DocumentObjectWeakPtrT::DocumentObjectWeakPtrT(App::DocumentObject* obj) - : d(new Private(obj)) -{ -} + : d(new Private(obj)) +{} DocumentObjectWeakPtrT::~DocumentObjectWeakPtrT() = default; @@ -771,7 +828,7 @@ bool DocumentObjectWeakPtrT::expired() const noexcept return !d->indocument; } -DocumentObjectWeakPtrT& DocumentObjectWeakPtrT::operator= (App::DocumentObject* p) +DocumentObjectWeakPtrT& DocumentObjectWeakPtrT::operator=(App::DocumentObject* p) { d->reset(); d->set(p); @@ -788,31 +845,33 @@ App::DocumentObject* DocumentObjectWeakPtrT::operator->() const noexcept return d->get(); } -bool DocumentObjectWeakPtrT::operator== (const DocumentObjectWeakPtrT& p) const noexcept +bool DocumentObjectWeakPtrT::operator==(const DocumentObjectWeakPtrT& p) const noexcept { return d->get() == p.d->get(); } -bool DocumentObjectWeakPtrT::operator!= (const DocumentObjectWeakPtrT& p) const noexcept +bool DocumentObjectWeakPtrT::operator!=(const DocumentObjectWeakPtrT& p) const noexcept { return d->get() != p.d->get(); } // ----------------------------------------------------------------------------- -DocumentObserver::DocumentObserver() : _document(nullptr) +DocumentObserver::DocumentObserver() + : _document(nullptr) { - //NOLINTBEGIN - this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(std::bind - (&DocumentObserver::slotCreatedDocument, this, sp::_1)); - this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(std::bind - (&DocumentObserver::slotDeletedDocument, this, sp::_1)); - this->connectApplicationActivateDocument = App::GetApplication().signalActiveDocument.connect(std::bind - (&DocumentObserver::slotActivateDocument, this, sp::_1)); - //NOLINTEND + // NOLINTBEGIN + this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect( + std::bind(&DocumentObserver::slotCreatedDocument, this, sp::_1)); + this->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect( + std::bind(&DocumentObserver::slotDeletedDocument, this, sp::_1)); + this->connectApplicationActivateDocument = App::GetApplication().signalActiveDocument.connect( + std::bind(&DocumentObserver::slotActivateDocument, this, sp::_1)); + // NOLINTEND } -DocumentObserver::DocumentObserver(Document* doc) : DocumentObserver() +DocumentObserver::DocumentObserver(Document* doc) + : DocumentObserver() { // Connect to application and given document attachDocument(doc); @@ -838,18 +897,18 @@ void DocumentObserver::attachDocument(Document* doc) detachDocument(); _document = doc; - //NOLINTBEGIN - this->connectDocumentCreatedObject = _document->signalNewObject.connect(std::bind - (&DocumentObserver::slotCreatedObject, this, sp::_1)); - this->connectDocumentDeletedObject = _document->signalDeletedObject.connect(std::bind - (&DocumentObserver::slotDeletedObject, this, sp::_1)); - this->connectDocumentChangedObject = _document->signalChangedObject.connect(std::bind - (&DocumentObserver::slotChangedObject, this, sp::_1, sp::_2)); - this->connectDocumentRecomputedObject = _document->signalRecomputedObject.connect(std::bind - (&DocumentObserver::slotRecomputedObject, this, sp::_1)); - this->connectDocumentRecomputed = _document->signalRecomputed.connect(std::bind - (&DocumentObserver::slotRecomputedDocument, this, sp::_1)); - //NOLINTEND + // NOLINTBEGIN + this->connectDocumentCreatedObject = _document->signalNewObject.connect( + std::bind(&DocumentObserver::slotCreatedObject, this, sp::_1)); + this->connectDocumentDeletedObject = _document->signalDeletedObject.connect( + std::bind(&DocumentObserver::slotDeletedObject, this, sp::_1)); + this->connectDocumentChangedObject = _document->signalChangedObject.connect( + std::bind(&DocumentObserver::slotChangedObject, this, sp::_1, sp::_2)); + this->connectDocumentRecomputedObject = _document->signalRecomputedObject.connect( + std::bind(&DocumentObserver::slotRecomputedObject, this, sp::_1)); + this->connectDocumentRecomputed = _document->signalRecomputed.connect( + std::bind(&DocumentObserver::slotRecomputedDocument, this, sp::_1)); + // NOLINTEND } } @@ -866,36 +925,29 @@ void DocumentObserver::detachDocument() } void DocumentObserver::slotCreatedDocument(const App::Document& /*Doc*/) -{ -} +{} void DocumentObserver::slotDeletedDocument(const App::Document& /*Doc*/) -{ -} +{} void DocumentObserver::slotActivateDocument(const App::Document& /*Doc*/) -{ -} +{} void DocumentObserver::slotCreatedObject(const App::DocumentObject& /*Obj*/) -{ -} +{} void DocumentObserver::slotDeletedObject(const App::DocumentObject& /*Obj*/) -{ -} +{} -void DocumentObserver::slotChangedObject(const App::DocumentObject& /*Obj*/, const App::Property& /*Prop*/) -{ -} +void DocumentObserver::slotChangedObject(const App::DocumentObject& /*Obj*/, + const App::Property& /*Prop*/) +{} void DocumentObserver::slotRecomputedObject(const DocumentObject& /*Obj*/) -{ -} +{} void DocumentObserver::slotRecomputedDocument(const Document& /*doc*/) -{ -} +{} // ----------------------------------------------------------------------------- @@ -925,8 +977,7 @@ void DocumentObjectObserver::removeFromObservation(App::DocumentObject* obj) } void DocumentObjectObserver::slotCreatedDocument(const App::Document&) -{ -} +{} void DocumentObjectObserver::slotDeletedDocument(const App::Document& Doc) { @@ -938,24 +989,22 @@ void DocumentObjectObserver::slotDeletedDocument(const App::Document& Doc) } void DocumentObjectObserver::slotCreatedObject(const App::DocumentObject&) -{ -} +{} void DocumentObjectObserver::slotDeletedObject(const App::DocumentObject& Obj) { - std::set::iterator it = _objects.find - (const_cast(&Obj)); - if (it != _objects.end()) + std::set::iterator it = + _objects.find(const_cast(&Obj)); + if (it != _objects.end()) { _objects.erase(it); - if (_objects.empty()) + } + if (_objects.empty()) { cancelObservation(); + } } -void DocumentObjectObserver::slotChangedObject(const App::DocumentObject&, - const App::Property&) -{ -} +void DocumentObjectObserver::slotChangedObject(const App::DocumentObject&, const App::Property&) +{} void DocumentObjectObserver::cancelObservation() -{ -} +{} diff --git a/src/App/DocumentObserver.h b/src/App/DocumentObserver.h index e9ce51692cc4..87a8b5c97df4 100644 --- a/src/App/DocumentObserver.h +++ b/src/App/DocumentObserver.h @@ -51,7 +51,7 @@ class AppExport DocumentT /*! Constructor */ DocumentT(); /*! Constructor */ - DocumentT(Document*); // explicit bombs + DocumentT(Document*); // explicit bombs /*! Constructor */ explicit DocumentT(const std::string&); /*! Constructor */ @@ -65,18 +65,20 @@ class AppExport DocumentT /*! Assignment operator */ void operator=(const std::string&); - bool operator==(const DocumentT &other) const { + bool operator==(const DocumentT& other) const + { return document == other.document; } - bool operator<(const DocumentT &other) const { + bool operator<(const DocumentT& other) const + { return document < other.document; } /*! Get a pointer to the document or 0 if it doesn't exist any more. */ Document* getDocument() const; /*! Get the name of the document. */ - const std::string &getDocumentName() const; + const std::string& getDocumentName() const; /*! Get the document as Python command. */ std::string getDocumentPython() const; @@ -85,9 +87,9 @@ class AppExport DocumentT }; /** - * The DocumentObjectT class is a helper class to store the names of a document object and its document. - * This can be useful when you cannot rely on that the document or the object still exists when you have to - * access it. + * The DocumentObjectT class is a helper class to store the names of a document object and its + * document. This can be useful when you cannot rely on that the document or the object still exists + * when you have to access it. * * @author Werner Mayer */ @@ -97,23 +99,23 @@ class AppExport DocumentObjectT /*! Constructor */ DocumentObjectT(); /*! Constructor */ - DocumentObjectT(const DocumentObjectT &); + DocumentObjectT(const DocumentObjectT&); /*! Constructor */ - DocumentObjectT(DocumentObjectT &&); + DocumentObjectT(DocumentObjectT&&); /*! Constructor */ explicit DocumentObjectT(const DocumentObject*); /*! Constructor */ DocumentObjectT(const Document*, const std::string& objName); /*! Constructor */ - DocumentObjectT(const char *docName, const char *objName); + DocumentObjectT(const char* docName, const char* objName); /*! Constructor */ explicit DocumentObjectT(const Property*); /*! Destructor */ ~DocumentObjectT(); /*! Assignment operator */ - DocumentObjectT &operator=(const DocumentObjectT&); + DocumentObjectT& operator=(const DocumentObjectT&); /*! Assignment operator */ - DocumentObjectT &operator=(DocumentObjectT &&); + DocumentObjectT& operator=(DocumentObjectT&&); /*! Assignment operator */ void operator=(const DocumentObject*); /*! Assignment operator */ @@ -124,7 +126,7 @@ class AppExport DocumentObjectT /*! Get a pointer to the document or 0 if it doesn't exist any more. */ Document* getDocument() const; /*! Get the name of the document. */ - const std::string &getDocumentName() const; + const std::string& getDocumentName() const; /*! Get the document as Python command. */ std::string getDocumentPython() const; /*! Get a pointer to the document object or 0 if it doesn't exist any more. */ @@ -132,16 +134,17 @@ class AppExport DocumentObjectT /*! Get a pointer to the property or 0 if it doesn't exist any more. */ Property* getProperty() const; /*! Get the name of the document object. */ - const std::string &getObjectName() const; + const std::string& getObjectName() const; /*! Get the label of the document object. */ - const std::string &getObjectLabel() const; + const std::string& getObjectLabel() const; /*! Get the name of the property. */ - const std::string &getPropertyName() const; + const std::string& getPropertyName() const; /*! Get the document object as Python command. */ std::string getObjectPython() const; /*! Get the property as Python command. */ std::string getPropertyPython() const; - /*! Get a pointer to the document or 0 if it doesn't exist any more or the type doesn't match. */ + /*! Get a pointer to the document or 0 if it doesn't exist any more or the type doesn't match. + */ template inline T* getObjectAs() const { @@ -160,72 +163,73 @@ class AppExport DocumentObjectT std::string property; }; -class AppExport SubObjectT : public DocumentObjectT +class AppExport SubObjectT: public DocumentObjectT { public: /*! Constructor */ SubObjectT(); /*! Constructor */ - SubObjectT(const SubObjectT &); + SubObjectT(const SubObjectT&); /*! Constructor */ - SubObjectT(SubObjectT &&); + SubObjectT(SubObjectT&&); /*! Constructor */ - SubObjectT(const DocumentObjectT & obj, const char *subname); + SubObjectT(const DocumentObjectT& obj, const char* subname); /*! Constructor */ - SubObjectT(const DocumentObject*, const char *subname); + SubObjectT(const DocumentObject*, const char* subname); /*! Constructor */ - SubObjectT(const DocumentObject*);// explicit bombs + SubObjectT(const DocumentObject*); // explicit bombs /*! Constructor */ - SubObjectT(const char *docName, const char *objName, const char *subname); + SubObjectT(const char* docName, const char* objName, const char* subname); /*! Assignment operator */ - SubObjectT &operator=(const SubObjectT&); + SubObjectT& operator=(const SubObjectT&); /*! Assignment operator */ - SubObjectT &operator=(SubObjectT &&); + SubObjectT& operator=(SubObjectT&&); /*! Assignment operator */ - SubObjectT &operator=(const DocumentObjectT&); + SubObjectT& operator=(const DocumentObjectT&); /*! Assignment operator */ - SubObjectT &operator=(const App::DocumentObject*); + SubObjectT& operator=(const App::DocumentObject*); /*! Equality operator */ bool operator==(const SubObjectT&) const; /// Set the subname path to the sub-object - void setSubName(const char *subname); + void setSubName(const char* subname); /// Set the subname path to the sub-object - void setSubName(const std::string &subname) { + void setSubName(const std::string& subname) + { setSubName(subname.c_str()); } /// Return the subname path - const std::string &getSubName() const; + const std::string& getSubName() const; /** Return docname#objname (label) * @param docName: optional document name. The document prefix will only be printed * if it is different then the given 'doc'. */ - std::string getObjectFullName(const char *docName=nullptr) const; + std::string getObjectFullName(const char* docName = nullptr) const; /** Return docname#objname.subname (label) * @param doc: optional document name. The document prefix will only be printed * if it is different then the given 'doc'. */ - std::string getSubObjectFullName(const char *docName=nullptr) const; + std::string getSubObjectFullName(const char* docName = nullptr) const; /// Return the subname path without sub-element std::string getSubNameNoElement() const; /// Return the sub-element (Face, Edge, etc) of the subname path - const char *getElementName() const; + const char* getElementName() const; /// Check if there is any sub object reference bool hasSubObject() const; @@ -239,17 +243,17 @@ class AppExport SubObjectT : public DocumentObjectT /** Return the old style sub-element name * @param index: if given, then return the element type, and extract the index */ - std::string getOldElementName(int *index=nullptr) const; + std::string getOldElementName(int* index = nullptr) const; /// Return the sub-object - DocumentObject *getSubObject() const; + DocumentObject* getSubObject() const; /// Return all objects along the subname path - std::vector getSubObjectList() const; + std::vector getSubObjectList() const; - bool operator<(const SubObjectT &other) const; + bool operator<(const SubObjectT& other) const; - std::string getSubObjectPython(bool force=true) const; + std::string getSubObjectPython(bool force = true) const; /// Options used by normalize() enum class NormalizeOption : uint8_t @@ -299,16 +303,17 @@ class AppExport PropertyLinkT PropertyLinkT(); /*! Constructor */ - explicit PropertyLinkT(DocumentObject *obj); + explicit PropertyLinkT(DocumentObject* obj); /*! Constructor */ - PropertyLinkT(DocumentObject *obj, const std::vector& subNames); + PropertyLinkT(DocumentObject* obj, const std::vector& subNames); /*! Constructor */ explicit PropertyLinkT(const std::vector& objs); /*! Constructor */ - PropertyLinkT(const std::vector& objs, const std::vector& subNames); + PropertyLinkT(const std::vector& objs, + const std::vector& subNames); /*! Get the property as Python command. */ std::string getPropertyPython() const; @@ -379,7 +384,7 @@ class AppExport DocumentObjectWeakPtrT * \brief operator = * Assignment operator */ - DocumentObjectWeakPtrT& operator= (App::DocumentObject* p); + DocumentObjectWeakPtrT& operator=(App::DocumentObject* p); /*! * \brief operator * * \return pointer to the document object @@ -394,12 +399,12 @@ class AppExport DocumentObjectWeakPtrT * \brief operator == * \return true if both objects are equal, false otherwise */ - bool operator== (const DocumentObjectWeakPtrT& p) const noexcept; + bool operator==(const DocumentObjectWeakPtrT& p) const noexcept; /*! * \brief operator != * \return true if both objects are inequal, false otherwise */ - bool operator!= (const DocumentObjectWeakPtrT& p) const noexcept; + bool operator!=(const DocumentObjectWeakPtrT& p) const noexcept; /*! Get a pointer to the object or 0 if it doesn't exist any more or the type doesn't match. */ template inline T* get() const noexcept @@ -423,33 +428,37 @@ class AppExport DocumentObjectWeakPtrT /** * @brief The WeakPtrT class */ -template +template class WeakPtrT { public: - explicit WeakPtrT(T* t) : ptr(t) { - } + explicit WeakPtrT(T* t) + : ptr(t) + {} ~WeakPtrT() = default; /*! * \brief reset * Releases the reference to the managed object. After the call *this manages no object. */ - void reset() { + void reset() + { ptr.reset(); } /*! * \brief expired * \return true if the managed object has already been deleted, false otherwise. */ - bool expired() const { + bool expired() const + { return ptr.expired(); } /*! * \brief operator = * Assignment operator */ - WeakPtrT& operator= (T* p) { + WeakPtrT& operator=(T* p) + { ptr = p; return *this; } @@ -457,28 +466,32 @@ class WeakPtrT * \brief operator -> * \return pointer to the document object */ - T* operator*() const { + T* operator*() const + { return ptr.get(); } /*! * \brief operator -> * \return pointer to the document object */ - T* operator->() const { + T* operator->() const + { return ptr.get(); } /*! * \brief operator == * \return true if both objects are equal, false otherwise */ - bool operator== (const WeakPtrT& p) const { + bool operator==(const WeakPtrT& p) const + { return ptr == p.ptr; } /*! * \brief operator != * \return true if both objects are inequal, false otherwise */ - bool operator!= (const WeakPtrT& p) const { + bool operator!=(const WeakPtrT& p) const + { return ptr != p.ptr; } /*! Get a pointer to the object or 0 if it doesn't exist any more. */ @@ -561,7 +574,7 @@ class AppExport DocumentObserver * * @author Werner Mayer */ -class AppExport DocumentObjectObserver : public DocumentObserver +class AppExport DocumentObjectObserver: public DocumentObserver { public: @@ -587,18 +600,18 @@ class AppExport DocumentObjectObserver : public DocumentObserver void slotDeletedObject(const App::DocumentObject& Obj) override; /** The property of an observed object has changed */ void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop) override; - /** This method gets called when all observed objects are deleted or the whole document is deleted. - * This method can be re-implemented to perform an extra step like closing a dialog that observes - * a document. - */ + /** This method gets called when all observed objects are deleted or the whole document is + * deleted. This method can be re-implemented to perform an extra step like closing a dialog + * that observes a document. + */ virtual void cancelObservation(); private: std::set _objects; }; -} //namespace App +} // namespace App ENABLE_BITMASK_OPERATORS(App::SubObjectT::NormalizeOption) -#endif // APP_DOCUMENTOBSERVER_H +#endif // APP_DOCUMENTOBSERVER_H diff --git a/src/App/DocumentObserverPython.cpp b/src/App/DocumentObserverPython.cpp index beb61a1522a3..f36515dd8aa2 100644 --- a/src/App/DocumentObserverPython.cpp +++ b/src/App/DocumentObserverPython.cpp @@ -46,9 +46,10 @@ void DocumentObserverPython::addObserver(const Py::Object& obj) void DocumentObserverPython::removeObserver(const Py::Object& obj) { - DocumentObserverPython* obs=nullptr; - for (std::vector::iterator it = - _instances.begin(); it != _instances.end(); ++it) { + DocumentObserverPython* obs = nullptr; + for (std::vector::iterator it = _instances.begin(); + it != _instances.end(); + ++it) { if ((*it)->inst == obj) { obs = *it; _instances.erase(it); @@ -59,33 +60,34 @@ void DocumentObserverPython::removeObserver(const Py::Object& obj) delete obs; } -DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) : inst(obj) +DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) + : inst(obj) { -#define FC_PY_ELEMENT_ARG0(_name1, _name2) do {\ - FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\ - if (!py##_name1.py.isNone())\ - py##_name1.slot = App::GetApplication().signal##_name2.connect(\ - std::bind(&DocumentObserverPython::slot##_name1, this));\ - }\ - while(0); +#define FC_PY_ELEMENT_ARG0(_name1, _name2) \ + do { \ + FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py); \ + if (!py##_name1.py.isNone()) \ + py##_name1.slot = App::GetApplication().signal##_name2.connect( \ + std::bind(&DocumentObserverPython::slot##_name1, this)); \ + } while (0); -#define FC_PY_ELEMENT_ARG1(_name1, _name2) do {\ - FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\ - if (!py##_name1.py.isNone())\ - py##_name1.slot = App::GetApplication().signal##_name2.connect(\ - std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1));\ - }\ - while(0); +#define FC_PY_ELEMENT_ARG1(_name1, _name2) \ + do { \ + FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py); \ + if (!py##_name1.py.isNone()) \ + py##_name1.slot = App::GetApplication().signal##_name2.connect( \ + std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1)); \ + } while (0); - //NOLINTBEGIN -#define FC_PY_ELEMENT_ARG2(_name1, _name2) do {\ - FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py);\ - if (!py##_name1.py.isNone())\ - py##_name1.slot = App::GetApplication().signal##_name2.connect(\ - std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1, sp::_2));\ - }\ - while(0); + // NOLINTBEGIN +#define FC_PY_ELEMENT_ARG2(_name1, _name2) \ + do { \ + FC_PY_GetCallable(obj.ptr(), "slot" #_name1, py##_name1.py); \ + if (!py##_name1.py.isNone()) \ + py##_name1.slot = App::GetApplication().signal##_name2.connect( \ + std::bind(&DocumentObserverPython::slot##_name1, this, sp::_1, sp::_2)); \ + } while (0); FC_PY_ELEMENT_ARG1(CreatedDocument, NewDocument) FC_PY_ELEMENT_ARG1(DeletedDocument, DeleteDocument) @@ -116,7 +118,7 @@ DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) : inst(obj FC_PY_ELEMENT_ARG2(ChangePropertyEditor, ChangePropertyEditor) FC_PY_ELEMENT_ARG2(BeforeAddingDynamicExtension, BeforeAddingDynamicExtension) FC_PY_ELEMENT_ARG2(AddedDynamicExtension, AddedDynamicExtension) - //NOLINTEND + // NOLINTEND } DocumentObserverPython::~DocumentObserverPython() = default; @@ -127,10 +129,10 @@ void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyCreatedDocument.ptr(),args.ptr()); + Base::pyCall(pyCreatedDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -141,10 +143,10 @@ void DocumentObserverPython::slotDeletedDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyDeletedDocument.ptr(),args.ptr()); + Base::pyCall(pyDeletedDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -155,10 +157,10 @@ void DocumentObserverPython::slotRelabelDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyRelabelDocument.ptr(),args.ptr()); + Base::pyCall(pyRelabelDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -169,10 +171,10 @@ void DocumentObserverPython::slotActivateDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyActivateDocument.ptr(),args.ptr()); + Base::pyCall(pyActivateDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -183,10 +185,10 @@ void DocumentObserverPython::slotUndoDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyUndoDocument.ptr(),args.ptr()); + Base::pyCall(pyUndoDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -198,10 +200,10 @@ void DocumentObserverPython::slotRedoDocument(const App::Document& Doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Doc).getPyObject())); - Base::pyCall(pyRedoDocument.ptr(),args.ptr()); + Base::pyCall(pyRedoDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -213,7 +215,7 @@ void DocumentObserverPython::slotUndo() Base::pyCall(pyUndo.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -225,7 +227,7 @@ void DocumentObserverPython::slotRedo() Base::pyCall(pyRedo.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -236,10 +238,10 @@ void DocumentObserverPython::slotBeforeCloseTransaction(bool abort) try { Py::Tuple args(1); args.setItem(0, Py::Boolean(abort)); - Base::pyCall(pyBeforeCloseTransaction.ptr(),args.ptr()); + Base::pyCall(pyBeforeCloseTransaction.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -250,15 +252,16 @@ void DocumentObserverPython::slotCloseTransaction(bool abort) try { Py::Tuple args(1); args.setItem(0, Py::Boolean(abort)); - Base::pyCall(pyCloseTransaction.ptr(),args.ptr()); + Base::pyCall(pyCloseTransaction.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotBeforeChangeDocument(const App::Document& Doc, const App::Property& Prop) +void DocumentObserverPython::slotBeforeChangeDocument(const App::Document& Doc, + const App::Property& Prop) { Base::PyGILStateLocker lock; try { @@ -269,16 +272,17 @@ void DocumentObserverPython::slotBeforeChangeDocument(const App::Document& Doc, const char* prop_name = Doc.getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyBeforeChangeDocument.ptr(),args.ptr()); + Base::pyCall(pyBeforeChangeDocument.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotChangedDocument(const App::Document& Doc, const App::Property& Prop) +void DocumentObserverPython::slotChangedDocument(const App::Document& Doc, + const App::Property& Prop) { Base::PyGILStateLocker lock; try { @@ -289,11 +293,11 @@ void DocumentObserverPython::slotChangedDocument(const App::Document& Doc, const const char* prop_name = Doc.getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyChangedDocument.ptr(),args.ptr()); + Base::pyCall(pyChangedDocument.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -304,10 +308,10 @@ void DocumentObserverPython::slotCreatedObject(const App::DocumentObject& Obj) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Obj).getPyObject())); - Base::pyCall(pyCreatedObject.ptr(),args.ptr()); + Base::pyCall(pyCreatedObject.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -318,16 +322,16 @@ void DocumentObserverPython::slotDeletedObject(const App::DocumentObject& Obj) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Obj).getPyObject())); - Base::pyCall(pyDeletedObject.ptr(),args.ptr()); + Base::pyCall(pyDeletedObject.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } void DocumentObserverPython::slotBeforeChangeObject(const App::DocumentObject& Obj, - const App::Property& Prop) + const App::Property& Prop) { Base::PyGILStateLocker lock; try { @@ -338,11 +342,11 @@ void DocumentObserverPython::slotBeforeChangeObject(const App::DocumentObject& O const char* prop_name = Obj.getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyBeforeChangeObject.ptr(),args.ptr()); + Base::pyCall(pyBeforeChangeObject.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -359,11 +363,11 @@ void DocumentObserverPython::slotChangedObject(const App::DocumentObject& Obj, const char* prop_name = Obj.getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyChangedObject.ptr(),args.ptr()); + Base::pyCall(pyChangedObject.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -374,10 +378,10 @@ void DocumentObserverPython::slotRecomputedObject(const App::DocumentObject& Obj try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(Obj).getPyObject())); - Base::pyCall(pyRecomputedObject.ptr(),args.ptr()); + Base::pyCall(pyRecomputedObject.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -388,10 +392,10 @@ void DocumentObserverPython::slotRecomputedDocument(const App::Document& doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); - Base::pyCall(pyRecomputedDocument.ptr(),args.ptr()); + Base::pyCall(pyRecomputedDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -402,10 +406,10 @@ void DocumentObserverPython::slotBeforeRecomputeDocument(const App::Document& do try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); - Base::pyCall(pyBeforeRecomputeDocument.ptr(),args.ptr()); + Base::pyCall(pyBeforeRecomputeDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -417,10 +421,10 @@ void DocumentObserverPython::slotOpenTransaction(const App::Document& doc, std:: Py::Tuple args(2); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); args.setItem(1, Py::String(str)); - Base::pyCall(pyOpenTransaction.ptr(),args.ptr()); + Base::pyCall(pyOpenTransaction.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -431,10 +435,10 @@ void DocumentObserverPython::slotCommitTransaction(const App::Document& doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); - Base::pyCall(pyCommitTransaction.ptr(),args.ptr()); + Base::pyCall(pyCommitTransaction.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -445,10 +449,10 @@ void DocumentObserverPython::slotAbortTransaction(const App::Document& doc) try { Py::Tuple args(1); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); - Base::pyCall(pyAbortTransaction.ptr(),args.ptr()); + Base::pyCall(pyAbortTransaction.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -465,11 +469,11 @@ void DocumentObserverPython::slotAppendDynamicProperty(const App::Property& Prop const char* prop_name = container->getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyAppendDynamicProperty.ptr(),args.ptr()); + Base::pyCall(pyAppendDynamicProperty.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -486,16 +490,17 @@ void DocumentObserverPython::slotRemoveDynamicProperty(const App::Property& Prop const char* prop_name = container->getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyRemoveDynamicProperty.ptr(),args.ptr()); + Base::pyCall(pyRemoveDynamicProperty.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotChangePropertyEditor(const App::Document &, const App::Property& Prop) +void DocumentObserverPython::slotChangePropertyEditor(const App::Document&, + const App::Property& Prop) { Base::PyGILStateLocker lock; try { @@ -507,72 +512,76 @@ void DocumentObserverPython::slotChangePropertyEditor(const App::Document &, con const char* prop_name = container->getPropertyName(&Prop); if (prop_name) { args.setItem(1, Py::String(prop_name)); - Base::pyCall(pyChangePropertyEditor.ptr(),args.ptr()); + Base::pyCall(pyChangePropertyEditor.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotStartSaveDocument(const App::Document& doc, const std::string& file) +void DocumentObserverPython::slotStartSaveDocument(const App::Document& doc, + const std::string& file) { Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); args.setItem(1, Py::String(file)); - Base::pyCall(pyStartSaveDocument.ptr(),args.ptr()); + Base::pyCall(pyStartSaveDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotFinishSaveDocument(const App::Document& doc, const std::string& file) +void DocumentObserverPython::slotFinishSaveDocument(const App::Document& doc, + const std::string& file) { Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::asObject(const_cast(doc).getPyObject())); args.setItem(1, Py::String(file)); - Base::pyCall(pyFinishSaveDocument.ptr(),args.ptr()); + Base::pyCall(pyFinishSaveDocument.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotBeforeAddingDynamicExtension(const App::ExtensionContainer& extcont, std::string extension) +void DocumentObserverPython::slotBeforeAddingDynamicExtension( + const App::ExtensionContainer& extcont, + std::string extension) { Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::asObject(const_cast(extcont).getPyObject())); args.setItem(1, Py::String(extension)); - Base::pyCall(pyBeforeAddingDynamicExtension.ptr(),args.ptr()); + Base::pyCall(pyBeforeAddingDynamicExtension.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -void DocumentObserverPython::slotAddedDynamicExtension(const App::ExtensionContainer& extcont, std::string extension) +void DocumentObserverPython::slotAddedDynamicExtension(const App::ExtensionContainer& extcont, + std::string extension) { Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::asObject(const_cast(extcont).getPyObject())); args.setItem(1, Py::String(extension)); - Base::pyCall(pyAddedDynamicExtension.ptr(),args.ptr()); + Base::pyCall(pyAddedDynamicExtension.ptr(), args.ptr()); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } - diff --git a/src/App/DocumentObserverPython.h b/src/App/DocumentObserverPython.h index ce57626ddf20..b0240c6416fa 100644 --- a/src/App/DocumentObserverPython.h +++ b/src/App/DocumentObserverPython.h @@ -106,7 +106,7 @@ class AppExport DocumentObserverPython /** Called when an object gets a dynamic property removed*/ void slotRemoveDynamicProperty(const App::Property& Prop); /** Called when an object property gets a new editor relevant status like hidden or read only*/ - void slotChangePropertyEditor(const App::Document &Doc, const App::Property& Prop); + void slotChangePropertyEditor(const App::Document& Doc, const App::Property& Prop); /** Called when a document is about to be saved*/ void slotStartSaveDocument(const App::Document&, const std::string&); /** Called when an document has been saved*/ @@ -121,12 +121,14 @@ class AppExport DocumentObserverPython Py::Object inst; static std::vector _instances; - using Connection = struct PythonObject { - boost::signals2::scoped_connection slot; - Py::Object py; - PyObject* ptr() { - return py.ptr(); - } + using Connection = struct PythonObject + { + boost::signals2::scoped_connection slot; + Py::Object py; + PyObject* ptr() + { + return py.ptr(); + } }; Connection pyCreatedDocument; @@ -160,6 +162,6 @@ class AppExport DocumentObserverPython Connection pyAddedDynamicExtension; }; -} //namespace App +} // namespace App -#endif // APP_DOCUMENTOBSERVERPYTHON_H +#endif // APP_DOCUMENTOBSERVERPYTHON_H diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 229ba5d7d7a6..ea62adb535c6 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -41,21 +41,40 @@ using namespace App; -PyObject* DocumentPy::addProperty(PyObject *args, PyObject *kwd) +PyObject* DocumentPy::addProperty(PyObject* args, PyObject* kwd) { - char *sType {nullptr}; - char *sName {nullptr}; - char *sGroup {nullptr}; - char *sDoc {nullptr}; - short attr=0; + char* sType {nullptr}; + char* sName {nullptr}; + char* sGroup {nullptr}; + char* sDoc {nullptr}; + short attr = 0; std::string sDocStr; PyObject *ro = Py_False, *hd = Py_False; PyObject* enumVals = nullptr; - static const std::array kwlist{"type", "name", "group", "doc", "attr", - "read_only", "hidden", "enum_vals", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords( - args, kwd, "ss|sethO!O!O", kwlist, &sType, &sName, &sGroup, "utf-8", - &sDoc, &attr, &PyBool_Type, &ro, &PyBool_Type, &hd, &enumVals)) { + static const std::array kwlist {"type", + "name", + "group", + "doc", + "attr", + "read_only", + "hidden", + "enum_vals", + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "ss|sethO!O!O", + kwlist, + &sType, + &sName, + &sGroup, + "utf-8", + &sDoc, + &attr, + &PyBool_Type, + &ro, + &PyBool_Type, + &hd, + &enumVals)) { return nullptr; } @@ -64,9 +83,13 @@ PyObject* DocumentPy::addProperty(PyObject *args, PyObject *kwd) PyMem_Free(sDoc); } - Property *prop = getDocumentPtr()-> - addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr, - Base::asBoolean(ro), Base::asBoolean(hd)); + Property* prop = getDocumentPtr()->addDynamicProperty(sType, + sName, + sGroup, + sDocStr.c_str(), + attr, + Base::asBoolean(ro), + Base::asBoolean(hd)); // enum support auto* propEnum = dynamic_cast(prop); @@ -77,11 +100,12 @@ PyObject* DocumentPy::addProperty(PyObject *args, PyObject *kwd) return Py::new_reference_to(this); } -PyObject* DocumentPy::removeProperty(PyObject *args) +PyObject* DocumentPy::removeProperty(PyObject* args) { - char *sName; - if (!PyArg_ParseTuple(args, "s", &sName)) + char* sName; + if (!PyArg_ParseTuple(args, "s", &sName)) { return nullptr; + } bool ok = getDocumentPtr()->removeDynamicProperty(sName); return Py_BuildValue("O", (ok ? Py_True : Py_False)); @@ -96,17 +120,20 @@ std::string DocumentPy::representation() const return str.str(); } -PyObject* DocumentPy::save(PyObject * args) +PyObject* DocumentPy::save(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - PY_TRY { + PY_TRY + { if (!getDocumentPtr()->save()) { PyErr_SetString(PyExc_ValueError, "Object attribute 'FileName' is not set"); return nullptr; } - } PY_CATCH; + } + PY_CATCH; const char* filename = getDocumentPtr()->FileName.getValue(); Base::FileInfo fi(filename); @@ -118,38 +145,45 @@ PyObject* DocumentPy::save(PyObject * args) Py_Return; } -PyObject* DocumentPy::saveAs(PyObject * args) +PyObject* DocumentPy::saveAs(PyObject* args) { char* fn; - if (!PyArg_ParseTuple(args, "et", "utf-8", &fn)) + if (!PyArg_ParseTuple(args, "et", "utf-8", &fn)) { return nullptr; + } std::string utf8Name = fn; PyMem_Free(fn); - PY_TRY { + PY_TRY + { getDocumentPtr()->saveAs(utf8Name.c_str()); Py_Return; - }PY_CATCH + } + PY_CATCH } -PyObject* DocumentPy::saveCopy(PyObject * args) +PyObject* DocumentPy::saveCopy(PyObject* args) { char* fn; - if (!PyArg_ParseTuple(args, "s", &fn)) + if (!PyArg_ParseTuple(args, "s", &fn)) { return nullptr; + } - PY_TRY { + PY_TRY + { getDocumentPtr()->saveCopy(fn); Py_Return; - }PY_CATCH + } + PY_CATCH } -PyObject* DocumentPy::load(PyObject * args) +PyObject* DocumentPy::load(PyObject* args) { - char* filename=nullptr; - if (!PyArg_ParseTuple(args, "s", &filename)) + char* filename = nullptr; + if (!PyArg_ParseTuple(args, "s", &filename)) { return nullptr; + } if (!filename || *filename == '\0') { PyErr_Format(PyExc_ValueError, "Path is empty"); return nullptr; @@ -163,17 +197,19 @@ PyObject* DocumentPy::load(PyObject * args) } try { getDocumentPtr()->restore(); - } catch (...) { + } + catch (...) { PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename); return nullptr; } Py_Return; } -PyObject* DocumentPy::restore(PyObject * args) +PyObject* DocumentPy::restore(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } const char* filename = getDocumentPtr()->FileName.getValue(); if (!filename || *filename == '\0') { PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set"); @@ -186,7 +222,8 @@ PyObject* DocumentPy::restore(PyObject * args) } try { getDocumentPtr()->restore(); - } catch (...) { + } + catch (...) { PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename); return nullptr; } @@ -195,61 +232,70 @@ PyObject* DocumentPy::restore(PyObject * args) PyObject* DocumentPy::isSaved(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } bool ok = getDocumentPtr()->isSaved(); return Py::new_reference_to(Py::Boolean(ok)); } PyObject* DocumentPy::getProgramVersion(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } const char* version = getDocumentPtr()->getProgramVersion(); return Py::new_reference_to(Py::String(version)); } PyObject* DocumentPy::getFileName(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } const char* fn = getDocumentPtr()->getFileName(); return Py::new_reference_to(Py::String(fn)); } -PyObject* DocumentPy::getUniqueObjectName(PyObject *args) +PyObject* DocumentPy::getUniqueObjectName(PyObject* args) { - char *sName; - if (!PyArg_ParseTuple(args, "s", &sName)) + char* sName; + if (!PyArg_ParseTuple(args, "s", &sName)) { return nullptr; - PY_TRY { - auto newName = getDocumentPtr()->getUniqueObjectName(sName); + } + PY_TRY + { + auto newName = getDocumentPtr()->getUniqueObjectName(sName); return Py::new_reference_to(Py::String(newName)); } PY_CATCH; } -PyObject* DocumentPy::mergeProject(PyObject * args) +PyObject* DocumentPy::mergeProject(PyObject* args) { char* filename; - if (!PyArg_ParseTuple(args, "s", &filename)) + if (!PyArg_ParseTuple(args, "s", &filename)) { return nullptr; + } - PY_TRY { + PY_TRY + { Base::FileInfo fi(filename); Base::ifstream str(fi, std::ios::in | std::ios::binary); App::Document* doc = getDocumentPtr(); MergeDocuments md(doc); md.importObjects(str); Py_Return; - } PY_CATCH; + } + PY_CATCH; } -PyObject* DocumentPy::exportGraphviz(PyObject * args) +PyObject* DocumentPy::exportGraphviz(PyObject* args) { - char* fn=nullptr; - if (!PyArg_ParseTuple(args, "|s",&fn)) + char* fn = nullptr; + if (!PyArg_ParseTuple(args, "|s", &fn)) { return nullptr; + } if (fn) { Base::FileInfo fi(fn); Base::ofstream str(fi); @@ -264,26 +310,36 @@ PyObject* DocumentPy::exportGraphviz(PyObject * args) } } -PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd) +PyObject* DocumentPy::addObject(PyObject* args, PyObject* kwd) { char *sType, *sName = nullptr, *sViewType = nullptr; - PyObject *obj = nullptr; - PyObject *view = nullptr; - PyObject *attach = Py_False; - static const std::array kwlist{"type", "name", "objProxy", "viewProxy", "attach", "viewType", - nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "s|sOOO!s", - kwlist, &sType, &sName, &obj, &view, &PyBool_Type, &attach, &sViewType)) { + PyObject* obj = nullptr; + PyObject* view = nullptr; + PyObject* attach = Py_False; + static const std::array + kwlist {"type", "name", "objProxy", "viewProxy", "attach", "viewType", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "s|sOOO!s", + kwlist, + &sType, + &sName, + &obj, + &view, + &PyBool_Type, + &attach, + &sViewType)) { return nullptr; } - DocumentObject *pcFtr = nullptr; + DocumentObject* pcFtr = nullptr; if (!obj || !Base::asBoolean(attach)) { - pcFtr = getDocumentPtr()->addObject(sType,sName,true,sViewType); + pcFtr = getDocumentPtr()->addObject(sType, sName, true, sViewType); } else { - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; @@ -310,7 +366,7 @@ PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd) pyftr.setAttr("Proxy", pyobj); if (Base::asBoolean(attach)) { - getDocumentPtr()->addObject(pcFtr,sName); + getDocumentPtr()->addObject(pcFtr, sName); try { Py::Callable method(pyobj.getAttr("attach")); @@ -328,10 +384,12 @@ PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd) // if a document class is set we also need a view provider defined which must be // something different to None Py::Object pyvp; - if (view) + if (view) { pyvp = Py::Object(view); - if (pyvp.isNone()) + } + if (pyvp.isNone()) { pyvp = Py::Int(1); + } // 'pyvp' is the python class with the implementation for ViewProvider if (pyvp.hasAttr("__vobject__")) { pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject")); @@ -348,16 +406,17 @@ PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd) return pcFtr->getPyObject(); } -PyObject* DocumentPy::removeObject(PyObject *args) +PyObject* DocumentPy::removeObject(PyObject* args) { - char *sName; - if (!PyArg_ParseTuple(args, "s",&sName)) + char* sName; + if (!PyArg_ParseTuple(args, "s", &sName)) { return nullptr; + } - DocumentObject *pcFtr = getDocumentPtr()->getObject(sName); + DocumentObject* pcFtr = getDocumentPtr()->getObject(sName); if (pcFtr) { - getDocumentPtr()->removeObject( sName ); + getDocumentPtr()->removeObject(sName); Py_Return; } else { @@ -367,26 +426,29 @@ PyObject* DocumentPy::removeObject(PyObject *args) } } -PyObject* DocumentPy::copyObject(PyObject *args) +PyObject* DocumentPy::copyObject(PyObject* args) { - PyObject *obj, *rec=Py_False, *retAll=Py_False; - if (!PyArg_ParseTuple(args, "O|O!O!",&obj,&PyBool_Type,&rec,&PyBool_Type,&retAll)) + PyObject *obj, *rec = Py_False, *retAll = Py_False; + if (!PyArg_ParseTuple(args, "O|O!O!", &obj, &PyBool_Type, &rec, &PyBool_Type, &retAll)) { return nullptr; + } std::vector objs; bool single = false; if (PySequence_Check(obj)) { Py::Sequence seq(obj); - for (Py_ssize_t i=0;i(seq[i].ptr())->getDocumentObjectPtr()); } } - else if (!PyObject_TypeCheck(obj,&DocumentObjectPy::Type)) { - PyErr_SetString(PyExc_TypeError, + else if (!PyObject_TypeCheck(obj, &DocumentObjectPy::Type)) { + PyErr_SetString( + PyExc_TypeError, "Expect first argument to be either a document object or sequence of document objects"); return nullptr; } @@ -395,64 +457,79 @@ PyObject* DocumentPy::copyObject(PyObject *args) single = true; } - PY_TRY { - auto ret = getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll)); - if (ret.size()==1 && single) + PY_TRY + { + auto ret = + getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll)); + if (ret.size() == 1 && single) { return ret[0]->getPyObject(); + } Py::Tuple tuple(ret.size()); - for (size_t i=0;igetPyObject(),true)); + for (size_t i = 0; i < ret.size(); ++i) { + tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true)); + } return Py::new_reference_to(tuple); - } PY_CATCH + } + PY_CATCH } -PyObject* DocumentPy::importLinks(PyObject *args) +PyObject* DocumentPy::importLinks(PyObject* args) { - PyObject *obj = Py_None; - if (!PyArg_ParseTuple(args, "|O",&obj)) + PyObject* obj = Py_None; + if (!PyArg_ParseTuple(args, "|O", &obj)) { return nullptr; + } std::vector objs; if (PySequence_Check(obj)) { Py::Sequence seq(obj); - for (Py_ssize_t i=0;i(seq[i].ptr())->getDocumentObjectPtr()); } } else { - Base::PyTypeCheck(&obj, &DocumentObjectPy::Type, - "Expect first argument to be either a document object, sequence of document objects or None"); - if (obj) + Base::PyTypeCheck(&obj, + &DocumentObjectPy::Type, + "Expect first argument to be either a document object, sequence of " + "document objects or None"); + if (obj) { objs.push_back(static_cast(obj)->getDocumentObjectPtr()); + } } - if (objs.empty()) + if (objs.empty()) { objs = getDocumentPtr()->getObjects(); + } - PY_TRY { + PY_TRY + { auto ret = getDocumentPtr()->importLinks(objs); Py::Tuple tuple(ret.size()); - for (size_t i=0;igetPyObject(),true)); + for (size_t i = 0; i < ret.size(); ++i) { + tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true)); + } return Py::new_reference_to(tuple); } PY_CATCH } -PyObject* DocumentPy::moveObject(PyObject *args) +PyObject* DocumentPy::moveObject(PyObject* args) { - PyObject *obj, *rec=Py_False; - if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec)) + PyObject *obj, *rec = Py_False; + if (!PyArg_ParseTuple(args, "O!|O!", &(DocumentObjectPy::Type), &obj, &PyBool_Type, &rec)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(obj); - DocumentObject* move = getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec)); + DocumentObject* move = + getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec)); if (move) { return move->getPyObject(); } @@ -462,11 +539,12 @@ PyObject* DocumentPy::moveObject(PyObject *args) } } -PyObject* DocumentPy::openTransaction(PyObject *args) +PyObject* DocumentPy::openTransaction(PyObject* args) { - PyObject *value = nullptr; - if (!PyArg_ParseTuple(args, "|O",&value)) + PyObject* value = nullptr; + if (!PyArg_ParseTuple(args, "|O", &value)) { return nullptr; + } std::string cmd; @@ -485,56 +563,65 @@ PyObject* DocumentPy::openTransaction(PyObject *args) Py_Return; } -PyObject* DocumentPy::abortTransaction(PyObject * args) +PyObject* DocumentPy::abortTransaction(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentPtr()->abortTransaction(); Py_Return; } -PyObject* DocumentPy::commitTransaction(PyObject * args) +PyObject* DocumentPy::commitTransaction(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentPtr()->commitTransaction(); Py_Return; } -Py::Boolean DocumentPy::getHasPendingTransaction() const { +Py::Boolean DocumentPy::getHasPendingTransaction() const +{ return {getDocumentPtr()->hasPendingTransaction()}; } -PyObject* DocumentPy::undo(PyObject * args) +PyObject* DocumentPy::undo(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; - if (getDocumentPtr()->getAvailableUndos()) + } + if (getDocumentPtr()->getAvailableUndos()) { getDocumentPtr()->undo(); + } Py_Return; } -PyObject* DocumentPy::redo(PyObject * args) +PyObject* DocumentPy::redo(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; - if (getDocumentPtr()->getAvailableRedos()) + } + if (getDocumentPtr()->getAvailableRedos()) { getDocumentPtr()->redo(); + } Py_Return; } -PyObject* DocumentPy::clearUndos(PyObject * args) +PyObject* DocumentPy::clearUndos(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentPtr()->clearUndos(); Py_Return; } -PyObject* DocumentPy::clearDocument(PyObject * args) +PyObject* DocumentPy::clearDocument(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentPtr()->clearDocument(); Py_Return; } @@ -542,52 +629,65 @@ PyObject* DocumentPy::clearDocument(PyObject * args) PyObject* DocumentPy::setClosable(PyObject* args) { PyObject* close; - if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close)) + if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close)) { return nullptr; + } getDocumentPtr()->setClosable(Base::asBoolean(close)); Py_Return; } PyObject* DocumentPy::isClosable(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } bool ok = getDocumentPtr()->isClosable(); return Py::new_reference_to(Py::Boolean(ok)); } -PyObject* DocumentPy::recompute(PyObject * args) +PyObject* DocumentPy::recompute(PyObject* args) { - PyObject *pyobjs = Py_None; - PyObject *force = Py_False; - PyObject *checkCycle = Py_False; - if (!PyArg_ParseTuple(args, "|OO!O!",&pyobjs, - &PyBool_Type,&force,&PyBool_Type,&checkCycle)) + PyObject* pyobjs = Py_None; + PyObject* force = Py_False; + PyObject* checkCycle = Py_False; + if (!PyArg_ParseTuple(args, + "|OO!O!", + &pyobjs, + &PyBool_Type, + &force, + &PyBool_Type, + &checkCycle)) { return nullptr; + } - PY_TRY { - std::vector objs; - if (pyobjs!=Py_None) { + PY_TRY + { + std::vector objs; + if (pyobjs != Py_None) { if (!PySequence_Check(pyobjs)) { PyErr_SetString(PyExc_TypeError, "expect input of sequence of document objects"); return nullptr; } Py::Sequence seq(pyobjs); - for (Py_ssize_t i=0;i(seq[i].ptr())->getDocumentObjectPtr()); + objs.push_back( + static_cast(seq[i].ptr())->getDocumentObjectPtr()); } } int options = 0; - if (Base::asBoolean(checkCycle)) + if (Base::asBoolean(checkCycle)) { options = Document::DepNoCycle; + } - int objectCount = getDocumentPtr()->recompute(objs, Base::asBoolean(force), nullptr, options); + int objectCount = + getDocumentPtr()->recompute(objs, Base::asBoolean(force), nullptr, options); // Document::recompute() hides possibly raised Python exceptions by its features // So, check if an error is set and return null if yes @@ -596,40 +696,44 @@ PyObject* DocumentPy::recompute(PyObject * args) } return Py::new_reference_to(Py::Int(objectCount)); - } PY_CATCH; + } + PY_CATCH; } PyObject* DocumentPy::mustExecute(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } bool ok = getDocumentPtr()->mustExecute(); return Py::new_reference_to(Py::Boolean(ok)); } PyObject* DocumentPy::isTouched(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } bool ok = getDocumentPtr()->isTouched(); return Py::new_reference_to(Py::Boolean(ok)); } PyObject* DocumentPy::purgeTouched(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getDocumentPtr()->purgeTouched(); Py_Return; } -PyObject* DocumentPy::getObject(PyObject *args) +PyObject* DocumentPy::getObject(PyObject* args) { DocumentObject* obj = nullptr; do { char* name = nullptr; - if (PyArg_ParseTuple(args, "s", &name)) { + if (PyArg_ParseTuple(args, "s", &name)) { obj = getDocumentPtr()->getObject(name); break; } @@ -643,41 +747,44 @@ PyObject* DocumentPy::getObject(PyObject *args) PyErr_SetString(PyExc_TypeError, "a string or integer is required"); return nullptr; - } - while (false); + } while (false); - if (obj) + if (obj) { return obj->getPyObject(); + } Py_Return; } -PyObject* DocumentPy::getObjectsByLabel(PyObject *args) +PyObject* DocumentPy::getObjectsByLabel(PyObject* args) { - char *sName; - if (!PyArg_ParseTuple(args, "s",&sName)) + char* sName; + if (!PyArg_ParseTuple(args, "s", &sName)) { return nullptr; + } Py::List list; std::string name = sName; std::vector objs = getDocumentPtr()->getObjects(); for (auto obj : objs) { - if (name == obj->Label.getValue()) + if (name == obj->Label.getValue()) { list.append(Py::asObject(obj->getPyObject())); + } } return Py::new_reference_to(list); } -PyObject* DocumentPy::findObjects(PyObject *args, PyObject *kwds) +PyObject* DocumentPy::findObjects(PyObject* args, PyObject* kwds) { const char *sType = "App::DocumentObject", *sName = nullptr, *sLabel = nullptr; - static const std::array kwlist{"Type", "Name", "Label", nullptr}; + static const std::array kwlist {"Type", "Name", "Label", nullptr}; if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|sss", kwlist, &sType, &sName, &sLabel)) { return nullptr; } - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; @@ -694,31 +801,36 @@ PyObject* DocumentPy::findObjects(PyObject *args, PyObject *kwds) return nullptr; } - Py_ssize_t index=0; + Py_ssize_t index = 0; PyObject* list = PyList_New((Py_ssize_t)res.size()); - for (std::vector::const_iterator It = res.begin();It != res.end();++It, index++) + for (std::vector::const_iterator It = res.begin(); It != res.end(); + ++It, index++) { PyList_SetItem(list, index, (*It)->getPyObject()); + } return list; } Py::Object DocumentPy::getActiveObject() const { - DocumentObject *pcFtr = getDocumentPtr()->getActiveObject(); - if (pcFtr) + DocumentObject* pcFtr = getDocumentPtr()->getActiveObject(); + if (pcFtr) { return Py::Object(pcFtr->getPyObject(), true); + } return Py::None(); } -PyObject* DocumentPy::supportedTypes(PyObject *args) +PyObject* DocumentPy::supportedTypes(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } std::vector ary; Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary); Py::List res; - for (const auto & it : ary) + for (const auto& it : ary) { res.append(Py::String(it.getName())); + } return Py::new_reference_to(res); } @@ -727,9 +839,11 @@ Py::List DocumentPy::getObjects() const std::vector objs = getDocumentPtr()->getObjects(); Py::List res; - for (auto obj : objs) - //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter + for (auto obj : objs) { + // Note: Here we must force the Py::Object to own this Python object as getPyObject() + // increments the counter res.append(Py::Object(obj->getPyObject(), true)); + } return res; } @@ -739,9 +853,11 @@ Py::List DocumentPy::getTopologicalSortedObjects() const std::vector objs = getDocumentPtr()->topologicalSort(); Py::List res; - for (auto obj : objs) - //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter + for (auto obj : objs) { + // Note: Here we must force the Py::Object to own this Python object as getPyObject() + // increments the counter res.append(Py::Object(obj->getPyObject(), true)); + } return res; } @@ -751,9 +867,11 @@ Py::List DocumentPy::getRootObjects() const std::vector objs = getDocumentPtr()->getRootObjects(); Py::List res; - for (auto obj : objs) - //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter + for (auto obj : objs) { + // Note: Here we must force the Py::Object to own this Python object as getPyObject() + // increments the counter res.append(Py::Object(obj->getPyObject(), true)); + } return res; } @@ -763,9 +881,11 @@ Py::List DocumentPy::getRootObjectsIgnoreLinks() const std::vector objs = getDocumentPtr()->getRootObjectsIgnoreLinks(); Py::List res; - for (auto obj : objs) - //Note: Here we must force the Py::Object to own this Python object as getPyObject() increments the counter + for (auto obj : objs) { + // Note: Here we must force the Py::Object to own this Python object as getPyObject() + // increments the counter res.append(Py::Object(obj->getPyObject(), true)); + } return res; } @@ -775,7 +895,7 @@ Py::Int DocumentPy::getUndoMode() const return Py::Int(getDocumentPtr()->getUndoMode()); } -void DocumentPy::setUndoMode(Py::Int arg) +void DocumentPy::setUndoMode(Py::Int arg) { getDocumentPtr()->setUndoMode(arg); } @@ -801,8 +921,9 @@ Py::List DocumentPy::getUndoNames() const std::vector vList = getDocumentPtr()->getAvailableUndoNames(); Py::List res; - for (const auto & It : vList) + for (const auto& It : vList) { res.append(Py::String(It)); + } return res; } @@ -812,13 +933,14 @@ Py::List DocumentPy::getRedoNames() const std::vector vList = getDocumentPtr()->getAvailableRedoNames(); Py::List res; - for (const auto & It : vList) + for (const auto& It : vList) { res.append(Py::String(It)); + } return res; } -Py::String DocumentPy::getDependencyGraph() const +Py::String DocumentPy::getDependencyGraph() const { std::stringstream out; getDocumentPtr()->exportGraphviz(out); @@ -840,11 +962,12 @@ void DocumentPy::setRecomputesFrozen(Py::Boolean arg) getDocumentPtr()->setStatus(Document::Status::SkipRecompute, arg.isTrue()); } -PyObject* DocumentPy::getTempFileName(PyObject *args) +PyObject* DocumentPy::getTempFileName(PyObject* args) { - PyObject *value; - if (!PyArg_ParseTuple(args, "O",&value)) + PyObject* value; + if (!PyArg_ParseTuple(args, "O", &value)) { return nullptr; + } std::string string; if (PyUnicode_Check(value)) { @@ -857,19 +980,20 @@ PyObject* DocumentPy::getTempFileName(PyObject *args) } // search for a temp file name in the document transient directory - Base::FileInfo fileName(Base::FileInfo::getTempFileName - (string.c_str(),getDocumentPtr()->TransientDir.getValue())); + Base::FileInfo fileName( + Base::FileInfo::getTempFileName(string.c_str(), getDocumentPtr()->TransientDir.getValue())); // delete the created file, we need only the name... fileName.deleteFile(); - PyObject *p = PyUnicode_DecodeUTF8(fileName.filePath().c_str(),fileName.filePath().size(),nullptr); + PyObject* p = + PyUnicode_DecodeUTF8(fileName.filePath().c_str(), fileName.filePath().size(), nullptr); if (!p) { throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()"); } return p; } -PyObject *DocumentPy::getCustomAttributes(const char* attr) const +PyObject* DocumentPy::getCustomAttributes(const char* attr) const { // Note: Here we want to return only a document object if its // name matches 'attr'. However, it is possible to have an object @@ -877,21 +1001,24 @@ PyObject *DocumentPy::getCustomAttributes(const char* attr) const // wise it wouldn't be possible to address this attribute any more. // The object must then be addressed by the getObject() method directly. App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr); - if (prop) + if (prop) { return nullptr; + } if (!this->ob_type->tp_dict) { - if (PyType_Ready(this->ob_type) < 0) + if (PyType_Ready(this->ob_type) < 0) { return nullptr; + } } PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr); - if (item) + if (item) { return nullptr; + } // search for an object with this name DocumentObject* obj = getDocumentPtr()->getObject(attr); return (obj ? obj->getPyObject() : nullptr); } -int DocumentPy::setCustomAttributes(const char* attr, PyObject *) +int DocumentPy::setCustomAttributes(const char* attr, PyObject*) { // Note: Here we want to return only a document object if its // name matches 'attr'. However, it is possible to have an object @@ -899,21 +1026,22 @@ int DocumentPy::setCustomAttributes(const char* attr, PyObject *) // wise it wouldn't be possible to address this attribute any more. // The object must then be addressed by the getObject() method directly. App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr); - if (prop) + if (prop) { return 0; + } if (!this->ob_type->tp_dict) { - if (PyType_Ready(this->ob_type) < 0) + if (PyType_Ready(this->ob_type) < 0) { return 0; + } } PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr); - if (item) + if (item) { return 0; + } DocumentObject* obj = getDocumentPtr()->getObject(attr); - if (obj) - { + if (obj) { std::stringstream str; - str << "'Document' object attribute '" << attr - << "' must not be set this way" << std::ends; + str << "'Document' object attribute '" << attr << "' must not be set this way" << std::ends; PyErr_SetString(PyExc_RuntimeError, str.str().c_str()); return -1; } @@ -921,26 +1049,32 @@ int DocumentPy::setCustomAttributes(const char* attr, PyObject *) return 0; } -PyObject* DocumentPy::getLinksTo(PyObject *args) +PyObject* DocumentPy::getLinksTo(PyObject* args) { - PyObject *pyobj = Py_None; + PyObject* pyobj = Py_None; int options = 0; short count = 0; - if (!PyArg_ParseTuple(args, "|Oih", &pyobj,&options, &count)) + if (!PyArg_ParseTuple(args, "|Oih", &pyobj, &options, &count)) { return nullptr; + } - PY_TRY { - Base::PyTypeCheck(&pyobj, &DocumentObjectPy::Type, "Expect the first argument of type document object"); - DocumentObject *obj = nullptr; - if (pyobj) + PY_TRY + { + Base::PyTypeCheck(&pyobj, + &DocumentObjectPy::Type, + "Expect the first argument of type document object"); + DocumentObject* obj = nullptr; + if (pyobj) { obj = static_cast(pyobj)->getDocumentObjectPtr(); + } - std::set links; - getDocumentPtr()->getLinksTo(links,obj,options,count); + std::set links; + getDocumentPtr()->getLinksTo(links, obj, options, count); Py::Tuple ret(links.size()); - int i=0; - for (auto o : links) - ret.setItem(i++,Py::Object(o->getPyObject(),true)); + int i = 0; + for (auto o : links) { + ret.setItem(i++, Py::Object(o->getPyObject(), true)); + } return Py::new_reference_to(ret); } @@ -951,9 +1085,10 @@ Py::List DocumentPy::getInList() const { Py::List ret; auto lists = PropertyXLink::getDocumentInList(getDocumentPtr()); - if (lists.size()==1) { - for (auto doc : lists.begin()->second) + if (lists.size() == 1) { + for (auto doc : lists.begin()->second) { ret.append(Py::Object(doc->getPyObject(), true)); + } } return ret; } @@ -962,24 +1097,30 @@ Py::List DocumentPy::getOutList() const { Py::List ret; auto lists = PropertyXLink::getDocumentOutList(getDocumentPtr()); - if (lists.size()==1) { - for (auto doc : lists.begin()->second) + if (lists.size() == 1) { + for (auto doc : lists.begin()->second) { ret.append(Py::Object(doc->getPyObject(), true)); + } } return ret; } -PyObject *DocumentPy::getDependentDocuments(PyObject *args) { - PyObject *sort = Py_True; - if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) +PyObject* DocumentPy::getDependentDocuments(PyObject* args) +{ + PyObject* sort = Py_True; + if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) { return nullptr; - PY_TRY { + } + PY_TRY + { auto docs = getDocumentPtr()->getDependentDocuments(Base::asBoolean(sort)); Py::List ret; - for (auto doc : docs) + for (auto doc : docs) { ret.append(Py::Object(doc->getPyObject(), true)); + } return Py::new_reference_to(ret); - } PY_CATCH; + } + PY_CATCH; } Py::Boolean DocumentPy::getRestoring() const diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index cc21764ada2f..f79ecd565098 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -33,7 +33,7 @@ #include "PropertyContainer.h" -FC_LOG_LEVEL_INIT("Property",true,true) +FC_LOG_LEVEL_INIT("Property", true, true) using namespace App; @@ -46,65 +46,75 @@ DynamicProperty::~DynamicProperty() clear(); } -void DynamicProperty::clear() { - auto &index = props.get<0>(); - for(auto &v : index) +void DynamicProperty::clear() +{ + auto& index = props.get<0>(); + for (auto& v : index) { delete v.property; + } index.clear(); } -void DynamicProperty::getPropertyList(std::vector &List) const +void DynamicProperty::getPropertyList(std::vector& List) const { - for (auto &v : props.get<0>()) + for (auto& v : props.get<0>()) { List.push_back(v.property); + } } -void DynamicProperty::getPropertyNamedList(std::vector > &List) const +void DynamicProperty::getPropertyNamedList( + std::vector>& List) const { - for (auto &v : props.get<0>()) - List.emplace_back(v.getName(),v.property); + for (auto& v : props.get<0>()) { + List.emplace_back(v.getName(), v.property); + } } -void DynamicProperty::getPropertyMap(std::map &Map) const +void DynamicProperty::getPropertyMap(std::map& Map) const { - for (auto &v : props.get<0>()) + for (auto& v : props.get<0>()) { Map[v.name] = v.property; + } } -Property *DynamicProperty::getDynamicPropertyByName(const char* name) const +Property* DynamicProperty::getDynamicPropertyByName(const char* name) const { - auto &index = props.get<0>(); + auto& index = props.get<0>(); auto it = index.find(name); - if (it != index.end()) + if (it != index.end()) { return it->property; + } return nullptr; } std::vector DynamicProperty::getDynamicPropertyNames() const { std::vector names; - auto &index = props.get<0>(); + auto& index = props.get<0>(); names.reserve(index.size()); - for(auto &v : index) + for (auto& v : index) { names.push_back(v.name); + } return names; } short DynamicProperty::getPropertyType(const Property* prop) const { - return prop?prop->getType():0; + return prop ? prop->getType() : 0; } -short DynamicProperty::getPropertyType(const char *name) const +short DynamicProperty::getPropertyType(const char* name) const { - auto &index = props.get<0>(); + auto& index = props.get<0>(); auto it = index.find(name); if (it != index.end()) { short attr = it->attr; - if (it->hidden) + if (it->hidden) { attr |= Prop_Hidden; - if (it->readonly) + } + if (it->readonly) { attr |= Prop_ReadOnly; + } return attr; } return 0; @@ -112,92 +122,113 @@ short DynamicProperty::getPropertyType(const char *name) const const char* DynamicProperty::getPropertyGroup(const Property* prop) const { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if(it!=index.end()) + if (it != index.end()) { return it->group.c_str(); + } return nullptr; } -const char* DynamicProperty::getPropertyGroup(const char *name) const +const char* DynamicProperty::getPropertyGroup(const char* name) const { - auto &index = props.get<0>(); + auto& index = props.get<0>(); auto it = index.find(name); - if (it != index.end()) + if (it != index.end()) { return it->group.c_str(); + } return nullptr; } const char* DynamicProperty::getPropertyDocumentation(const Property* prop) const { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if(it!=index.end()) + if (it != index.end()) { return it->doc.c_str(); + } return nullptr; } -const char* DynamicProperty::getPropertyDocumentation(const char *name) const +const char* DynamicProperty::getPropertyDocumentation(const char* name) const { - auto &index = props.get<0>(); + auto& index = props.get<0>(); auto it = index.find(name); - if (it != index.end()) + if (it != index.end()) { return it->doc.c_str(); + } return nullptr; } -Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* type, - const char* name, const char* group, const char* doc, short attr, bool ro, bool hidden) +Property* DynamicProperty::addDynamicProperty(PropertyContainer& pc, + const char* type, + const char* name, + const char* group, + const char* doc, + short attr, + bool ro, + bool hidden) { - if(!type) + if (!type) { type = ""; + } std::string _name; - static ParameterGrp::handle hGrp = GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Document"); - if(hGrp->GetBool("AutoNameDynamicProperty",false)) { - if(!name || !name[0]) + static ParameterGrp::handle hGrp = + GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); + if (hGrp->GetBool("AutoNameDynamicProperty", false)) { + if (!name || !name[0]) { name = type; - _name = getUniquePropertyName(pc,name); - if(_name != name) { - FC_WARN(pc.getFullName() << " rename dynamic property from '" - << name << "' to '" << _name << "'"); + } + _name = getUniquePropertyName(pc, name); + if (_name != name) { + FC_WARN(pc.getFullName() + << " rename dynamic property from '" << name << "' to '" << _name << "'"); } name = _name.c_str(); - } else if(!name) - name = ""; // setting a bad name to trigger exception + } + else if (!name) { + name = ""; // setting a bad name to trigger exception + } auto prop = pc.getPropertyByName(name); - if(prop && prop->getContainer()==&pc) - FC_THROWM(Base::NameError, "Property " << pc.getFullName() << '.' << name << " already exists"); + if (prop && prop->getContainer() == &pc) { + FC_THROWM(Base::NameError, + "Property " << pc.getFullName() << '.' << name << " already exists"); + } - if(Base::Tools::getIdentifier(name) != name) + if (Base::Tools::getIdentifier(name) != name) { FC_THROWM(Base::NameError, "Invalid property name '" << name << "'"); + } - Base::Type propType = Base::Type::getTypeIfDerivedFrom(type, App::Property::getClassTypeId(), true); + Base::Type propType = + Base::Type::getTypeIfDerivedFrom(type, App::Property::getClassTypeId(), true); if (propType.isBad()) { - FC_THROWM(Base::TypeError, "Invalid type " - << type << " for property " << pc.getFullName() << '.' << name); + FC_THROWM(Base::TypeError, + "Invalid type " << type << " for property " << pc.getFullName() << '.' << name); } void* propInstance = propType.createInstance(); if (!propInstance) { - FC_THROWM(Base::RuntimeError, "Failed to create property " - << pc.getFullName() << '.' << name << " of type " << type); + FC_THROWM(Base::RuntimeError, + "Failed to create property " << pc.getFullName() << '.' << name << " of type " + << type); } Property* pcProperty = static_cast(propInstance); - auto res = props.get<0>().emplace(pcProperty,name, nullptr, group, doc, attr, ro, hidden); + auto res = props.get<0>().emplace(pcProperty, name, nullptr, group, doc, attr, ro, hidden); pcProperty->setContainer(&pc); pcProperty->myName = res.first->name.c_str(); - if(ro) + if (ro) { attr |= Prop_ReadOnly; - if(hidden) + } + if (hidden) { attr |= Prop_Hidden; + } pcProperty->syncType(attr); pcProperty->StatusBits.set((size_t)Property::PropDynamic); @@ -207,21 +238,29 @@ Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* return pcProperty; } -bool DynamicProperty::addProperty(Property *prop) +bool DynamicProperty::addProperty(Property* prop) { - if(!prop || !prop->hasName()) + if (!prop || !prop->hasName()) { return false; - auto &index = props.get<0>(); - if(index.count(prop->getName())) + } + auto& index = props.get<0>(); + if (index.count(prop->getName())) { return false; - index.emplace(prop,std::string(),prop->getName(), - prop->getGroup(),prop->getDocumentation(),prop->getType(),false,false); + } + index.emplace(prop, + std::string(), + prop->getName(), + prop->getGroup(), + prop->getDocumentation(), + prop->getType(), + false, + false); return true; } -bool DynamicProperty::removeProperty(const Property *prop) +bool DynamicProperty::removeProperty(const Property* prop) { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); if (it != index.end()) { index.erase(it); @@ -232,14 +271,16 @@ bool DynamicProperty::removeProperty(const Property *prop) bool DynamicProperty::removeDynamicProperty(const char* name) { - auto &index = props.get<0>(); + auto& index = props.get<0>(); auto it = index.find(name); if (it != index.end()) { - if(it->property->testStatus(Property::LockDynamic)) + if (it->property->testStatus(Property::LockDynamic)) { throw Base::RuntimeError("property is locked"); - else if(!it->property->testStatus(Property::PropDynamic)) + } + else if (!it->property->testStatus(Property::PropDynamic)) { throw Base::RuntimeError("property is not dynamic"); - Property *prop = it->property; + } + Property* prop = it->property; GetApplication().signalRemoveDynamicProperty(*prop); // Handle possible recursive calls of removeDynamicProperty @@ -255,12 +296,12 @@ bool DynamicProperty::removeDynamicProperty(const char* name) return false; } -std::string DynamicProperty::getUniquePropertyName(PropertyContainer &pc, const char *Name) const +std::string DynamicProperty::getUniquePropertyName(PropertyContainer& pc, const char* Name) const { std::string CleanName = Base::Tools::getIdentifier(Name); // name in use? - std::map objectProps; + std::map objectProps; pc.getPropertyMap(objectProps); auto pos = objectProps.find(CleanName); @@ -271,38 +312,42 @@ std::string DynamicProperty::getUniquePropertyName(PropertyContainer &pc, const else { std::vector names; names.reserve(objectProps.size()); - for (pos = objectProps.begin();pos != objectProps.end();++pos) { + for (pos = objectProps.begin(); pos != objectProps.end(); ++pos) { names.push_back(pos->first); } return Base::Tools::getUniqueName(CleanName, names); } } -void DynamicProperty::save(const Property *prop, Base::Writer &writer) const +void DynamicProperty::save(const Property* prop, Base::Writer& writer) const { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if(it != index.end()) { - auto &data = *it; + if (it != index.end()) { + auto& data = *it; writer.Stream() << "\" group=\"" << Base::Persistence::encodeAttribute(data.group) << "\" doc=\"" << Base::Persistence::encodeAttribute(data.doc) - << "\" attr=\"" << data.attr << "\" ro=\"" << data.readonly - << "\" hide=\"" << data.hidden; + << "\" attr=\"" << data.attr << "\" ro=\"" << data.readonly << "\" hide=\"" + << data.hidden; } } -Property *DynamicProperty::restore(PropertyContainer &pc, - const char *PropName, const char *TypeName, Base::XMLReader &reader) +Property* DynamicProperty::restore(PropertyContainer& pc, + const char* PropName, + const char* TypeName, + Base::XMLReader& reader) { - if (!reader.hasAttribute("group")) + if (!reader.hasAttribute("group")) { return nullptr; + } short attribute = 0; bool readonly = false, hidden = false; - const char *group=nullptr, *doc=nullptr, *attr=nullptr, *ro=nullptr, *hide=nullptr; + const char *group = nullptr, *doc = nullptr, *attr = nullptr, *ro = nullptr, *hide = nullptr; group = reader.getAttribute("group"); - if (reader.hasAttribute("doc")) + if (reader.hasAttribute("doc")) { doc = reader.getAttribute("doc"); + } if (reader.hasAttribute("attr")) { attr = reader.getAttribute("attr"); if (attr) { @@ -312,42 +357,54 @@ Property *DynamicProperty::restore(PropertyContainer &pc, } if (reader.hasAttribute("ro")) { ro = reader.getAttribute("ro"); - if (ro) readonly = (ro[0]-48) != 0; + if (ro) { + readonly = (ro[0] - 48) != 0; + } } if (reader.hasAttribute("hide")) { hide = reader.getAttribute("hide"); - if (hide) hidden = (hide[0]-48) != 0; + if (hide) { + hidden = (hide[0] - 48) != 0; + } } - return addDynamicProperty(pc,TypeName, PropName, group, doc, attribute, readonly, hidden); + return addDynamicProperty(pc, TypeName, PropName, group, doc, attribute, readonly, hidden); } -DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property *prop) const +DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property* prop) const { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if(it != index.end()) + if (it != index.end()) { return *it; + } return {}; } -bool DynamicProperty::changeDynamicProperty(const Property *prop, const char *group, const char *doc) { - auto &index = props.get<1>(); +bool DynamicProperty::changeDynamicProperty(const Property* prop, + const char* group, + const char* doc) +{ + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if (it == index.end()) + if (it == index.end()) { return false; - if(group) + } + if (group) { it->group = group; - if(doc) + } + if (doc) { it->doc = doc; + } return true; } -const char *DynamicProperty::getPropertyName(const Property *prop) const +const char* DynamicProperty::getPropertyName(const Property* prop) const { - auto &index = props.get<1>(); + auto& index = props.get<1>(); auto it = index.find(const_cast(prop)); - if(it != index.end()) + if (it != index.end()) { return it->getName(); + } return nullptr; } diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index a292f74c8ea6..6a2caf1d1198 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -35,11 +35,12 @@ #include -namespace Base { +namespace Base +{ class Writer; class XMLReader; class XMLWriter; -} +} // namespace Base namespace App { @@ -48,15 +49,24 @@ class PropertyContainer; namespace bmi = boost::multi_index; -struct CStringHasher { - inline std::size_t operator()(const char *s) const { - if(!s) return 0; - return boost::hash_range(s,s+std::strlen(s)); +struct CStringHasher +{ + inline std::size_t operator()(const char* s) const + { + if (!s) { + return 0; + } + return boost::hash_range(s, s + std::strlen(s)); } - inline bool operator()(const char *a, const char *b) const { - if(!a) return !b; - if(!b) return false; - return std::strcmp(a,b)==0; + inline bool operator()(const char* a, const char* b) const + { + if (!a) { + return !b; + } + if (!b) { + return false; + } + return std::strcmp(a, b) == 0; } }; @@ -73,13 +83,13 @@ class AppExport DynamicProperty /** @name Access properties */ //@{ /// Get all properties of the class (including parent) - void getPropertyList(std::vector &List) const; + void getPropertyList(std::vector& List) const; /// get all properties with their names - void getPropertyNamedList(std::vector > &List) const; + void getPropertyNamedList(std::vector>& List) const; /// Get all properties of the class (including parent) - void getPropertyMap(std::map &Map) const; + void getPropertyMap(std::map& Map) const; /// Find a dynamic property by its name - Property *getDynamicPropertyByName(const char* name) const; + Property* getDynamicPropertyByName(const char* name) const; /*! Add a dynamic property of the type @a type and with the name @a name. @a Group gives the grouping name which appears in the property editor and @@ -97,22 +107,28 @@ class AppExport DynamicProperty addDynamicProperty(..., ..., "Base","blah", Prop_None, true, true); @endcode */ - Property* addDynamicProperty(PropertyContainer &pc, const char* type, const char* name=nullptr, const char* group=nullptr, - const char* doc=nullptr, short attr=0, bool ro=false, bool hidden=false); + Property* addDynamicProperty(PropertyContainer& pc, + const char* type, + const char* name = nullptr, + const char* group = nullptr, + const char* doc = nullptr, + short attr = 0, + bool ro = false, + bool hidden = false); /** Add a pre-existing property * * The property is not treated as dynamic, and will not trigger signal. * * @return Return false if there is a property exist with the same name. */ - bool addProperty(Property *prop); + bool addProperty(Property* prop); /*! - Removes a dynamic property by name. Returns true if the property is part of the container, otherwise - false is returned. + Removes a dynamic property by name. Returns true if the property is part of the container, + otherwise false is returned. */ bool removeDynamicProperty(const char* name); /// Remove pre-existing property, which will not be deleted. - bool removeProperty(const Property *prop); + bool removeProperty(const Property* prop); /// Get a list of all dynamic properties. std::vector getDynamicPropertyNames() const; /// Get the name of a property @@ -124,72 +140,86 @@ class AppExport DynamicProperty /// Get the attributes of a property short getPropertyType(const Property* prop) const; /// Get the attributes of a named property - short getPropertyType(const char *name) const; + short getPropertyType(const char* name) const; /// Get the group name of a property const char* getPropertyGroup(const Property* prop) const; /// Get the group name of a named property - const char* getPropertyGroup(const char *name) const; + const char* getPropertyGroup(const char* name) const; /// Get the documentation of a property const char* getPropertyDocumentation(const Property* prop) const; /// Get the documentation of a named property - const char* getPropertyDocumentation(const char *name) const; + const char* getPropertyDocumentation(const char* name) const; //@} /// Remove all properties void clear(); /// Get property count - size_t size() const { return props.size(); } + size_t size() const + { + return props.size(); + } - void save(const Property *prop, Base::Writer &writer) const; + void save(const Property* prop, Base::Writer& writer) const; - Property *restore(PropertyContainer &pc, - const char *PropName, const char *TypeName, Base::XMLReader &reader); + Property* restore(PropertyContainer& pc, + const char* PropName, + const char* TypeName, + Base::XMLReader& reader); - struct PropData { + struct PropData + { Property* property; std::string name; - const char *pName; + const char* pName; mutable std::string group; mutable std::string doc; short attr; bool readonly; bool hidden; - PropData(Property *prop=nullptr, std::string &&n=std::string(), const char *pn=nullptr, - const char *g=nullptr, const char *d=nullptr, short a=0, bool ro=false, bool h=false) - :property(prop),name(std::move(n)),pName(pn) - ,group(g?g:""),doc(d?d:""),attr(a),readonly(ro),hidden(h) + PropData(Property* prop = nullptr, + std::string&& n = std::string(), + const char* pn = nullptr, + const char* g = nullptr, + const char* d = nullptr, + short a = 0, + bool ro = false, + bool h = false) + : property(prop) + , name(std::move(n)) + , pName(pn) + , group(g ? g : "") + , doc(d ? d : "") + , attr(a) + , readonly(ro) + , hidden(h) {} - const char *getName() const { - return pName?pName:name.c_str(); + const char* getName() const + { + return pName ? pName : name.c_str(); } }; PropData getDynamicPropertyData(const Property* prop) const; - bool changeDynamicProperty(const Property *prop, const char *group, const char *doc); + bool changeDynamicProperty(const Property* prop, const char* group, const char* doc); private: - std::string getUniquePropertyName(PropertyContainer &pc, const char *Name) const; + std::string getUniquePropertyName(PropertyContainer& pc, const char* Name) const; private: bmi::multi_index_container< PropData, bmi::indexed_by< - bmi::hashed_unique< - bmi::const_mem_fun, - CStringHasher, - CStringHasher - >, - bmi::hashed_unique< - bmi::member - > - > - > props; + bmi::hashed_unique, + CStringHasher, + CStringHasher>, + bmi::hashed_unique>>> + props; }; -} // namespace App +} // namespace App -#endif // APP_DYNAMICPROPERTY_H +#endif // APP_DYNAMICPROPERTY_H diff --git a/src/App/ElementMap.cpp b/src/App/ElementMap.cpp index 4a2545e38890..9e69c434be9e 100644 --- a/src/App/ElementMap.cpp +++ b/src/App/ElementMap.cpp @@ -18,7 +18,7 @@ #include -FC_LOG_LEVEL_INIT("ElementMap", true, 2);// NOLINT +FC_LOG_LEVEL_INIT("ElementMap", true, 2); // NOLINT namespace Data { @@ -104,7 +104,8 @@ void ElementMap::beforeSave(const ::App::StringHasherRef& hasherRef) const } } -void ElementMap::save(std::ostream& stream, int index, +void ElementMap::save(std::ostream& stream, + int index, const std::map& childMapSet, const std::map& postfixMap) const { @@ -121,7 +122,7 @@ void ElementMap::save(std::ostream& stream, int index, if (child.elementMap) { auto it = childMapSet.find(child.elementMap.get()); if (it == childMapSet.end() || it->second == 0) { - FC_ERR("Invalid child element map");// NOLINT + FC_ERR("Invalid child element map"); // NOLINT } else { mapIndex = it->second; @@ -240,7 +241,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream int count = 0; std::string tmp; if (!(stream >> id >> tmp >> count) || tmp != "PostfixCount") { - FC_THROWM(Base::RuntimeError, msg);// NOLINT + FC_THROWM(Base::RuntimeError, msg); // NOLINT } auto& map = _idToElementMap[id]; @@ -258,7 +259,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream std::vector childMaps; count = 0; if (!(stream >> tmp >> count) || tmp != "MapCount" || count == 0) { - FC_THROWM(Base::RuntimeError, msg);// NOLINT + FC_THROWM(Base::RuntimeError, msg); // NOLINT } childMaps.reserve(count - 1); for (int i = 0; i < count - 1; ++i) { @@ -269,7 +270,8 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream return restore(hasherRef, stream, childMaps, postfixes); } -ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream& stream, +ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, + std::istream& stream, std::vector& childMaps, const std::vector& postfixes) { @@ -281,14 +283,14 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream int typeCount = 0; unsigned id = 0; if (!(stream >> tmp >> index >> id >> typeCount) || tmp != "ElementMap") { - FC_THROWM(Base::RuntimeError, msg);// NOLINT + FC_THROWM(Base::RuntimeError, msg); // NOLINT } auto& map = _idToElementMap[id]; if (map) { while (tmp != "EndMap") { if (!std::getline(stream, tmp)) { - FC_THROWM(Base::RuntimeError, "unexpected end of child element map");// NOLINT + FC_THROWM(Base::RuntimeError, "unexpected end of child element map"); // NOLINT } } return map; @@ -303,12 +305,12 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream for (int i = 0; i < typeCount; ++i) { int outerCount = 0; if (!(stream >> tmp)) { - FC_THROWM(Base::RuntimeError, "missing element type");// NOLINT + FC_THROWM(Base::RuntimeError, "missing element type"); // NOLINT } IndexedName idx(tmp.c_str(), 1); if (!(stream >> tmp >> outerCount) || tmp != "ChildCount") { - FC_THROWM(Base::RuntimeError, "missing element child count");// NOLINT + FC_THROWM(Base::RuntimeError, "missing element child count"); // NOLINT } auto& indices = this->indexedNames[idx.getType()]; @@ -319,16 +321,16 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream long tag = 0; int mapIndex = 0; if (!(stream >> cIndex >> offset >> count >> tag >> mapIndex >> tmp)) { - FC_THROWM(Base::RuntimeError, "Invalid element child");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element child"); // NOLINT } if (cIndex < 0) { - FC_THROWM(Base::RuntimeError, "Invalid element child index");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element child index"); // NOLINT } if (offset < 0) { - FC_THROWM(Base::RuntimeError, "Invalid element child offset");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element child offset"); // NOLINT } if (mapIndex >= index || mapIndex < 0 || mapIndex > (int)childMaps.size()) { - FC_THROWM(Base::RuntimeError, "Invalid element child map index");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element child map index"); // NOLINT } auto& child = indices.children[cIndex + offset + count]; child.indexedName = IndexedName::fromConst(idx.getType(), cIndex); @@ -346,7 +348,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream this->childElementSize += child.count; if (!(stream >> tmp)) { - FC_THROWM(Base::RuntimeError, "Invalid element child string id");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element child string id"); // NOLINT } tokens.clear(); @@ -371,7 +373,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream } if (!(stream >> tmp >> outerCount) || tmp != "NameCount") { - FC_THROWM(Base::RuntimeError, "missing element name outerCount");// NOLINT + FC_THROWM(Base::RuntimeError, "missing element name outerCount"); // NOLINT } boost::io::ios_flags_saver ifs(stream); @@ -384,7 +386,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream int innerCount = 0; while (true) { if (!(stream >> tmp)) { - FC_THROWM(Base::RuntimeError, "Failed to read element name");// NOLINT + FC_THROWM(Base::RuntimeError, "Failed to read element name"); // NOLINT } if (tmp == "0") { break; @@ -396,7 +398,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream tokens.clear(); boost::split(tokens, tmp, boost::is_any_of(".")); if (tokens.size() < 2) { - FC_THROWM(Base::RuntimeError, "Invalid element entry");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element entry"); // NOLINT } int offset = 1; @@ -406,12 +408,12 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream switch (tokens[0][0]) { case ':': { if (tokens.size() < 3) { - FC_THROWM(Base::RuntimeError, "Invalid element entry");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element entry"); // NOLINT } ++offset; long elementNameIndex = strtol(tokens[0].c_str() + 1, nullptr, hexBase); if (elementNameIndex <= 0 || elementNameIndex > (int)postfixes.size()) { - FC_THROWM(Base::RuntimeError, "Invalid element name index");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element name index"); // NOLINT } long elementIndex = strtol(tokens[1].c_str(), nullptr, hexBase); ref->name = MappedName( @@ -427,7 +429,7 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream ref->name = MappedName(tokens[0].c_str() + 1); break; default: - FC_THROWM(Base::RuntimeError, "Invalid element name marker");// NOLINT + FC_THROWM(Base::RuntimeError, "Invalid element name marker"); // NOLINT } if (tokens[offset] != "0") { @@ -473,31 +475,34 @@ ElementMapPtr ElementMap::restore(::App::StringHasherRef hasherRef, std::istream } } if (hasherWarn) { - FC_WARN(hasherWarn);// NOLINT + FC_WARN(hasherWarn); // NOLINT } if (hasherIDWarn) { - FC_WARN(hasherIDWarn);// NOLINT + FC_WARN(hasherIDWarn); // NOLINT } if (postfixWarn) { - FC_WARN(postfixWarn);// NOLINT + FC_WARN(postfixWarn); // NOLINT } if (childSIDWarn) { - FC_WARN(childSIDWarn);// NOLINT + FC_WARN(childSIDWarn); // NOLINT } if (!(stream >> tmp) || tmp != "EndMap") { - FC_THROWM(Base::RuntimeError, "unexpected end of child element map");// NOLINT + FC_THROWM(Base::RuntimeError, "unexpected end of child element map"); // NOLINT } return shared_from_this(); } -MappedName ElementMap::addName(MappedName& name, const IndexedName& idx, const ElementIDRefs& sids, - bool overwrite, IndexedName* existing) +MappedName ElementMap::addName(MappedName& name, + const IndexedName& idx, + const ElementIDRefs& sids, + bool overwrite, + IndexedName* existing) { if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { if (name.find("#") >= 0 && name.findTagInElementName() < 0) { - FC_ERR("missing tag postfix " << name);// NOLINT + FC_ERR("missing tag postfix " << name); // NOLINT } } while (true) { @@ -505,14 +510,14 @@ MappedName ElementMap::addName(MappedName& name, const IndexedName& idx, const E erase(idx); } auto ret = mappedNames.insert(std::make_pair(name, idx)); - if (ret.second) { // element just inserted did not exist yet in the map - ret.first->first.compact();// FIXME see MappedName.cpp + if (ret.second) { // element just inserted did not exist yet in the map + ret.first->first.compact(); // FIXME see MappedName.cpp mappedRef(idx).append(ret.first->first, sids); - FC_TRACE(idx << " -> " << name);// NOLINT + FC_TRACE(idx << " -> " << name); // NOLINT return ret.first->first; } if (ret.first->second == idx) { - FC_TRACE("duplicate " << idx << " -> " << name);// NOLINT + FC_TRACE("duplicate " << idx << " -> " << name); // NOLINT return ret.first->first; } if (!overwrite) { @@ -526,7 +531,8 @@ MappedName ElementMap::addName(MappedName& name, const IndexedName& idx, const E }; } -void ElementMap::addPostfix(const QByteArray& postfix, std::map& postfixMap, +void ElementMap::addPostfix(const QByteArray& postfix, + std::map& postfixMap, std::vector& postfixes) { if (postfix.isEmpty()) { @@ -539,8 +545,11 @@ void ElementMap::addPostfix(const QByteArray& postfix, std::map } } -MappedName ElementMap::setElementName(const IndexedName& element, const MappedName& name, - long masterTag, const ElementIDRefs* sid, bool overwrite) +MappedName ElementMap::setElementName(const IndexedName& element, + const MappedName& name, + long masterTag, + const ElementIDRefs* sid, + bool overwrite) { if (!element) { throw Base::ValueError("Invalid input"); @@ -553,13 +562,13 @@ MappedName ElementMap::setElementName(const IndexedName& element, const MappedNa for (int i = 0, count = name.size(); i < count; ++i) { char check = name[i]; if (check == '.' || (std::isspace((int)check) != 0)) { - FC_THROWM(Base::RuntimeError, "Illegal character in mapped name: " << name);// NOLINT + FC_THROWM(Base::RuntimeError, "Illegal character in mapped name: " << name); // NOLINT } } for (const char* readChar = element.getType(); *readChar != 0; ++readChar) { char check = *readChar; if (check == '.' || (std::isspace((int)check) != 0)) { - FC_THROWM(Base::RuntimeError,// NOLINT + FC_THROWM(Base::RuntimeError, // NOLINT "Illegal character in element name: " << element); } } @@ -586,7 +595,7 @@ MappedName ElementMap::setElementName(const IndexedName& element, const MappedNa } const int maxAttempts {100}; if (++i == maxAttempts) { - FC_ERR("unresolved duplicate element mapping '"// NOLINT + FC_ERR("unresolved duplicate element mapping '" // NOLINT << name << ' ' << element << '/' << existing); return name; } @@ -602,9 +611,14 @@ MappedName ElementMap::setElementName(const IndexedName& element, const MappedNa } // try to hash element name while preserving the source tag -void ElementMap::encodeElementName(char element_type, MappedName& name, std::ostringstream& ss, - ElementIDRefs* sids, long masterTag, const char* postfix, - long tag, bool forceTag) const +void ElementMap::encodeElementName(char element_type, + MappedName& name, + std::ostringstream& ss, + ElementIDRefs* sids, + long masterTag, + const char* postfix, + long tag, + bool forceTag) const { if (postfix && (postfix[0] != 0)) { if (!boost::starts_with(postfix, ELEMENT_MAP_PREFIX)) { @@ -715,26 +729,30 @@ MappedName ElementMap::dehashElementName(const MappedName& name) const auto sid = this->hasher->getID(id); if (!sid) { if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) { - FC_WARN("failed to find hash id " << id);// NOLINT + FC_WARN("failed to find hash id " << id); // NOLINT } else { - FC_LOG("failed to find hash id " << id);// NOLINT + FC_LOG("failed to find hash id " << id); // NOLINT } return name; } if (sid.isHashed()) { - FC_LOG("cannot de-hash id " << id);// NOLINT + FC_LOG("cannot de-hash id " << id); // NOLINT return name; } MappedName ret(sid); -// sid.toString());// FIXME .toString() was missing in original function. is this correct? - FC_TRACE("de-hash " << name << " -> " << ret);// NOLINT + // sid.toString());// FIXME .toString() was missing in original function. is this + // correct? + FC_TRACE("de-hash " << name << " -> " << ret); // NOLINT return ret; } -MappedName ElementMap::renameDuplicateElement(int index, const IndexedName& element, - const IndexedName& element2, const MappedName& name, - ElementIDRefs& sids, long masterTag) const +MappedName ElementMap::renameDuplicateElement(int index, + const IndexedName& element, + const IndexedName& element2, + const MappedName& name, + ElementIDRefs& sids, + long masterTag) const { int idx {0}; #ifdef FC_DEBUG @@ -751,7 +769,7 @@ MappedName ElementMap::renameDuplicateElement(int index, const IndexedName& elem MappedName renamed(name); encodeElementName(element.getType()[0], renamed, ss, &sids, masterTag); if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("duplicate element mapping '"// NOLINT + FC_WARN("duplicate element mapping '" // NOLINT << name << " -> " << renamed << ' ' << element << '/' << element2); } return renamed; @@ -1008,13 +1026,20 @@ void ElementMap::hashChildMaps(long masterTag) .findTagInElementName(&tag, &len, nullptr, nullptr, false, false); // TODO: What is this 10? if (pos > 10) { - MappedName postfix = hashElementName( - MappedName::fromRawData(child.postfix.constData(), pos), child.sids); + MappedName postfix = + hashElementName(MappedName::fromRawData(child.postfix.constData(), pos), + child.sids); ss.str(""); ss << MAPPED_CHILD_ELEMENTS_PREFIX << postfix; MappedName tmp; - encodeElementName( - child.indexedName[0], tmp, ss, nullptr, masterTag, nullptr, child.tag, true); + encodeElementName(child.indexedName[0], + tmp, + ss, + nullptr, + masterTag, + nullptr, + child.tag, + true); this->childElements.remove(child.postfix); child.postfix = tmp.toBytes(); this->childElements[child.postfix].childMap = &child; @@ -1152,7 +1177,7 @@ void ElementMap::addChildElements(long masterTag, const std::vectorchildMap) { - FC_ERR("duplicate mapped child element");// NOLINT + FC_ERR("duplicate mapped child element"); // NOLINT continue; } } auto& indices = this->indexedNames[child.indexedName.getType()]; - auto res = indices.children.emplace( - child.indexedName.getIndex() + child.offset + child.count, child); + auto res = + indices.children.emplace(child.indexedName.getIndex() + child.offset + child.count, + child); if (!res.second) { if (!entry->childMap) { this->childElements.remove(tmp.toBytes()); } - FC_ERR("duplicate mapped child element");// NOLINT + FC_ERR("duplicate mapped child element"); // NOLINT continue; } @@ -1293,7 +1324,9 @@ std::vector ElementMap::getAll() const return ret; } -long ElementMap::getElementHistory(const MappedName& name, long masterTag, MappedName* original, +long ElementMap::getElementHistory(const MappedName& name, + long masterTag, + MappedName* original, std::vector* history) const { long tag = 0; @@ -1321,7 +1354,7 @@ long ElementMap::getElementHistory(const MappedName& name, long masterTag, Mappe while (true) { if ((len == 0) || len > pos) { - FC_WARN("invalid name length " << name);// NOLINT + FC_WARN("invalid name length " << name); // NOLINT return 0; } bool deHashed = false; @@ -1440,4 +1473,4 @@ void ElementMap::traceElement(const MappedName& name, long masterTag, TraceCallb } -}// Namespace Data +} // Namespace Data diff --git a/src/App/ElementMap.h b/src/App/ElementMap.h index 1902210ef915..29c7c2ab9a5c 100644 --- a/src/App/ElementMap.h +++ b/src/App/ElementMap.h @@ -46,17 +46,17 @@ class ElementMap; using ElementMapPtr = std::shared_ptr; /** Element trace callback - * - * The callback has the following call signature - * (const std::string &name, size_t offset, long encodedTag, long tag) -> bool - * - * @param name: the current element name. - * @param offset: the offset skipping the encoded element name for the next iteration. - * @param encodedTag: the tag encoded inside the current element, which is usually the tag - * of the previous step in the shape history. - * @param tag: the tag of the current shape element. - * - * @sa traceElement() + * + * The callback has the following call signature + * (const std::string &name, size_t offset, long encodedTag, long tag) -> bool + * + * @param name: the current element name. + * @param offset: the offset skipping the encoded element name for the next iteration. + * @param encodedTag: the tag encoded inside the current element, which is usually the tag + * of the previous step in the shape history. + * @param tag: the tag of the current shape element. + * + * @sa traceElement() */ typedef std::function TraceCallback; @@ -68,13 +68,14 @@ typedef std::function TraceCallback; * possibly a recursive elementmap * `mappedNames` maps a MappedName to a specific IndexedName. */ -class AppExport ElementMap: public std::enable_shared_from_this //TODO can remove shared_from_this? +class AppExport ElementMap + : public std::enable_shared_from_this // TODO can remove shared_from_this? { public: /** Default constructor: hooks internal functions to \c signalSaveDocument and * \c signalStartRestoreDocument. This is related to the save and restore process * of the map. - */ + */ ElementMap(); /** Ensures that naming is properly assigned. It then marks as "used" all the StringID @@ -82,14 +83,14 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO * as a parameter. Finally do this recursively for all childEelementMaps as well. * * @param hasherRef where all the StringID needed to build the map are stored. - */ + */ // FIXME this should be made part of \c save, to achieve symmetry with the restore method void beforeSave(const ::App::StringHasherRef& hasherRef) const; /** Serialize this map. Calls \c collectChildMaps to get \c childMapSet and * \c postfixMap, then calls the other (private) save function with those parameters. * @param stream: serialized stream - */ + */ void save(std::ostream& stream) const; /** Deserialize and restore this map. This function restores \c childMaps and @@ -97,7 +98,7 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO * parameters. * @param hasherRef: where all the StringIDs are stored * @param stream: stream to deserialize - */ + */ ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream); @@ -196,9 +197,10 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO std::vector getAll() const; - long getElementHistory(const MappedName & name, + long getElementHistory(const MappedName& name, long masterTag, - MappedName *original=nullptr, std::vector *history=nullptr) const; + MappedName* original = nullptr, + std::vector* history = nullptr) const; /** Iterate through the history of the give element name with a given callback * @@ -214,8 +216,10 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO * @param stream: serialized stream * @param childMapSet: where all child element maps are stored * @param postfixMap. where all postfixes are stored - */ - void save(std::ostream& stream, int index, const std::map& childMapSet, + */ + void save(std::ostream& stream, + int index, + const std::map& childMapSet, const std::map& postfixMap) const; /** Deserialize and restore this map. @@ -223,8 +227,9 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO * @param stream: stream to deserialize * @param childMaps: where all child element maps are stored * @param postfixes. where all postfixes are stored - */ - ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream, + */ + ElementMapPtr restore(::App::StringHasherRef hasherRef, + std::istream& stream, std::vector& childMaps, const std::vector& postfixes); @@ -237,20 +242,27 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO * associated with another indexedName, set \c existing to that indexedname * @return the name just added, or an empty name if it wasn't added. */ - MappedName addName(MappedName& name, const IndexedName& idx, const ElementIDRefs& sids, - bool overwrite, IndexedName* existing); + MappedName addName(MappedName& name, + const IndexedName& idx, + const ElementIDRefs& sids, + bool overwrite, + IndexedName* existing); /** Utility function that adds \c postfix to \c postfixMap, and to \c postfixes * if it was not present in the map. - */ - static void addPostfix(const QByteArray& postfix, std::map& postfixMap, + */ + static void addPostfix(const QByteArray& postfix, + std::map& postfixMap, std::vector& postfixes); /* Note: the original proc passed `ComplexGeoData& master` for getting the `Tag`, * now it just passes `long masterTag`.*/ - MappedName renameDuplicateElement(int index, const IndexedName& element, - const IndexedName& element2, const MappedName& name, - ElementIDRefs& sids, long masterTag) const; + MappedName renameDuplicateElement(int index, + const IndexedName& element, + const IndexedName& element2, + const MappedName& name, + ElementIDRefs& sids, + long masterTag) const; /** Convenience method to hash the main element name * @@ -263,7 +275,7 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO /// Reverse hashElementName() MappedName dehashElementName(const MappedName& name) const; - //FIXME duplicate code? as in copy/paste + // FIXME duplicate code? as in copy/paste const MappedNameRef* findMappedRef(const IndexedName& idx) const; MappedNameRef* findMappedRef(const IndexedName& idx); @@ -313,6 +325,6 @@ class AppExport ElementMap: public std::enable_shared_from_this //TO }; -}// namespace Data +} // namespace Data -#endif// DATA_ELEMENTMAP_H +#endif // DATA_ELEMENTMAP_H diff --git a/src/App/ElementNamingUtils.cpp b/src/App/ElementNamingUtils.cpp index 2b6e59d4d897..8d17603219ad 100644 --- a/src/App/ElementNamingUtils.cpp +++ b/src/App/ElementNamingUtils.cpp @@ -4,96 +4,119 @@ #include -const char *Data::isMappedElement(const char *name) { - if(name && boost::starts_with(name, ELEMENT_MAP_PREFIX)) +const char* Data::isMappedElement(const char* name) +{ + if (name && boost::starts_with(name, ELEMENT_MAP_PREFIX)) { return name + ELEMENT_MAP_PREFIX_SIZE; + } return nullptr; } -std::string Data::newElementName(const char *name) { - if(!name) +std::string Data::newElementName(const char* name) +{ + if (!name) { return {}; - const char *dot = strrchr(name,'.'); - if(!dot || dot==name) + } + const char* dot = strrchr(name, '.'); + if (!dot || dot == name) { return name; - const char *c = dot-1; - for(;c!=name;--c) { - if(*c == '.') { + } + const char* c = dot - 1; + for (; c != name; --c) { + if (*c == '.') { ++c; break; } } - if(isMappedElement(c)) - return std::string(name,dot-name); + if (isMappedElement(c)) { + return std::string(name, dot - name); + } return name; } -std::string Data::oldElementName(const char *name) { - if(!name) +std::string Data::oldElementName(const char* name) +{ + if (!name) { return {}; - const char *dot = strrchr(name,'.'); - if(!dot || dot==name) + } + const char* dot = strrchr(name, '.'); + if (!dot || dot == name) { return name; - const char *c = dot-1; - for(;c!=name;--c) { - if(*c == '.') { + } + const char* c = dot - 1; + for (; c != name; --c) { + if (*c == '.') { ++c; break; } } - if(isMappedElement(c)) - return std::string(name,c-name)+(dot+1); + if (isMappedElement(c)) { + return std::string(name, c - name) + (dot + 1); + } return name; } -std::string Data::noElementName(const char *name) { - if(!name) +std::string Data::noElementName(const char* name) +{ + if (!name) { return {}; + } auto element = findElementName(name); - if(element) - return std::string(name,element-name); + if (element) { + return std::string(name, element - name); + } return name; } -const char *Data::findElementName(const char *subname) { +const char* Data::findElementName(const char* subname) +{ // skip leading dots - while(subname && subname[0] == '.') + while (subname && subname[0] == '.') { ++subname; - if(!subname || !subname[0] || isMappedElement(subname)) + } + if (!subname || !subname[0] || isMappedElement(subname)) { return subname; - const char *dot = strrchr(subname,'.'); - if(!dot) + } + const char* dot = strrchr(subname, '.'); + if (!dot) { return subname; - const char *element = dot+1; - if(dot==subname || isMappedElement(element)) + } + const char* element = dot + 1; + if (dot == subname || isMappedElement(element)) { return element; - for(--dot;dot!=subname;--dot) { - if(*dot == '.') { + } + for (--dot; dot != subname; --dot) { + if (*dot == '.') { ++dot; break; } } - if(isMappedElement(dot)) + if (isMappedElement(dot)) { return dot; + } return element; } -bool Data::hasMissingElement(const char *subname) { - if(!subname) +bool Data::hasMissingElement(const char* subname) +{ + if (!subname) { return false; - auto dot = strrchr(subname,'.'); - if(dot) - subname = dot+1; + } + auto dot = strrchr(subname, '.'); + if (dot) { + subname = dot + 1; + } return boost::starts_with(subname, MISSING_PREFIX); } -const char *Data::hasMappedElementName(const char *subname) { +const char* Data::hasMappedElementName(const char* subname) +{ return isMappedElement(findElementName(subname)); } -const std::string Data::indexSuffix(int index, const char *label) +const std::string Data::indexSuffix(int index, const char* label) { - if ( index < 2 ) { // Don't add a suffix for item #1, begin appending at 2 + if (index < 2) { // Don't add a suffix for item #1, begin appending at 2 return {""}; } std::string name(label); diff --git a/src/App/ElementNamingUtils.h b/src/App/ElementNamingUtils.h index cedc2c134280..3ed66ecedd08 100644 --- a/src/App/ElementNamingUtils.h +++ b/src/App/ElementNamingUtils.h @@ -18,10 +18,10 @@ struct ElementNamePair ElementNamePair() = default; - ElementNamePair(std::string newNameStr, std::string oldNameStr) : - newName(std::move(newNameStr)), oldName(std::move(oldNameStr)) - { - } + ElementNamePair(std::string newNameStr, std::string oldNameStr) + : newName(std::move(newNameStr)) + , oldName(std::move(oldNameStr)) + {} bool operator==(const ElementNamePair& other) const { @@ -34,7 +34,7 @@ struct ElementNamePair } }; -} +} // namespace App // clang-format off namespace Data @@ -101,4 +101,4 @@ AppExport const std::string indexSuffix(int index, const char *label=ELEMENT_MAP } // namespace Data // clang-format on -#endif // ELEMENT_NAMING_UTILS_H +#endif // ELEMENT_NAMING_UTILS_H diff --git a/src/App/Enumeration.cpp b/src/App/Enumeration.cpp index 69d302749525..595292f0a189 100644 --- a/src/App/Enumeration.cpp +++ b/src/App/Enumeration.cpp @@ -22,8 +22,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include @@ -32,17 +32,23 @@ using namespace App; -namespace { -struct StringCopy : public Enumeration::Object { - explicit StringCopy(const char* str) : d(str) { - } - const char* data() const override { +namespace +{ +struct StringCopy: public Enumeration::Object +{ + explicit StringCopy(const char* str) + : d(str) + {} + const char* data() const override + { return d.data(); } - bool isEqual(const char* str) const override { + bool isEqual(const char* str) const override + { return d == str; } - bool isCustom() const override { + bool isCustom() const override + { return true; } @@ -50,43 +56,47 @@ struct StringCopy : public Enumeration::Object { std::string d; }; -struct StringView : public Enumeration::Object { - explicit StringView(const char* str) : d(str) { - } - const char* data() const override { +struct StringView: public Enumeration::Object +{ + explicit StringView(const char* str) + : d(str) + {} + const char* data() const override + { return d.data(); } - bool isEqual(const char* str) const override { + bool isEqual(const char* str) const override + { return d == str; } - bool isCustom() const override { + bool isCustom() const override + { return false; } private: std::string_view d; }; -} +} // namespace Enumeration::Enumeration() : _index(0) -{ -} +{} -Enumeration::Enumeration(const Enumeration &other) +Enumeration::Enumeration(const Enumeration& other) { enumArray = other.enumArray; _index = other._index; } -Enumeration::Enumeration(const char *valStr) +Enumeration::Enumeration(const char* valStr) : _index(0) { enumArray.push_back(std::make_shared(valStr)); setValue(valStr); } -Enumeration::Enumeration(const char **list, const char *valStr) +Enumeration::Enumeration(const char** list, const char* valStr) : _index(0) { while (list && *list) { @@ -101,14 +111,15 @@ Enumeration::~Enumeration() enumArray.clear(); } -void Enumeration::setEnums(const char **plEnums) +void Enumeration::setEnums(const char** plEnums) { std::string oldValue; bool preserve = (isValid() && plEnums != nullptr); if (preserve) { const char* str = getCStr(); - if (str) + if (str) { oldValue = str; + } } enumArray.clear(); @@ -118,14 +129,15 @@ void Enumeration::setEnums(const char **plEnums) } // set _index - if (_index < 0) + if (_index < 0) { _index = 0; + } if (preserve) { setValue(oldValue); } } -void Enumeration::setEnums(const std::vector &values) +void Enumeration::setEnums(const std::vector& values) { if (values.empty()) { setEnums(nullptr); @@ -136,24 +148,26 @@ void Enumeration::setEnums(const std::vector &values) bool preserve = isValid(); if (preserve) { const char* str = getCStr(); - if (str) + if (str) { oldValue = str; + } } enumArray.clear(); - for (const auto & it : values) { + for (const auto& it : values) { enumArray.push_back(std::make_shared(it.c_str())); } // set _index - if (_index < 0) + if (_index < 0) { _index = 0; + } if (preserve) { setValue(oldValue); } } -void Enumeration::setValue(const char *value) +void Enumeration::setValue(const char* value) { _index = 0; for (std::size_t i = 0; i < enumArray.size(); i++) { @@ -168,41 +182,45 @@ void Enumeration::setValue(long value, bool checkRange) { if (value >= 0 && value < countItems()) { _index = value; - } else { + } + else { if (checkRange) { throw Base::ValueError("Out of range"); - } else { + } + else { _index = value; } } } -bool Enumeration::isValue(const char *value) const +bool Enumeration::isValue(const char* value) const { int i = getInt(); if (i == -1) { return false; - } else { + } + else { return enumArray[i]->isEqual(value); } } -bool Enumeration::contains(const char *value) const +bool Enumeration::contains(const char* value) const { if (!isValid()) { return false; } for (const auto& it : enumArray) { - if (it->isEqual(value)) + if (it->isEqual(value)) { return true; + } } return false; } -const char * Enumeration::getCStr() const +const char* Enumeration::getCStr() const { if (!isValid() || _index < 0 || _index >= countItems()) { return nullptr; @@ -223,8 +241,9 @@ int Enumeration::getInt() const std::vector Enumeration::getEnumVector() const { std::vector list; - for (const auto& it : enumArray) + for (const auto& it : enumArray) { list.emplace_back(it->data()); + } return list; } @@ -241,24 +260,27 @@ bool Enumeration::isValid() const int Enumeration::maxValue() const { int num = -1; - if (!enumArray.empty()) + if (!enumArray.empty()) { num = static_cast(enumArray.size()) - 1; + } return num; } bool Enumeration::isCustom() const { for (const auto& it : enumArray) { - if (it->isCustom()) + if (it->isCustom()) { return true; + } } return false; } -Enumeration & Enumeration::operator=(const Enumeration &other) +Enumeration& Enumeration::operator=(const Enumeration& other) { - if (this == &other) + if (this == &other) { return *this; + } enumArray = other.enumArray; _index = other._index; @@ -266,23 +288,26 @@ Enumeration & Enumeration::operator=(const Enumeration &other) return *this; } -bool Enumeration::operator==(const Enumeration &other) const +bool Enumeration::operator==(const Enumeration& other) const { if (_index != other._index || enumArray.size() != other.enumArray.size()) { return false; } for (size_t i = 0; i < enumArray.size(); ++i) { - if (enumArray[i]->data() == other.enumArray[i]->data()) + if (enumArray[i]->data() == other.enumArray[i]->data()) { continue; - if (!enumArray[i]->data() || !other.enumArray[i]->data()) + } + if (!enumArray[i]->data() || !other.enumArray[i]->data()) { return false; - if (!enumArray[i]->isEqual(other.enumArray[i]->data())) + } + if (!enumArray[i]->isEqual(other.enumArray[i]->data())) { return false; + } } return true; } -bool Enumeration::operator==(const char *other) const +bool Enumeration::operator==(const char* other) const { if (!getCStr()) { return false; diff --git a/src/App/Enumeration.h b/src/App/Enumeration.h index 64320ac9b430..60fe06328719 100644 --- a/src/App/Enumeration.h +++ b/src/App/Enumeration.h @@ -31,162 +31,166 @@ namespace App { - /// A bidirectional string-integer mapping - /*! - * This is mainly intended for two purposes: working around the difficulty - * in C++ of sharing enumerations between different source files, - * namespaces, etc. and as the data type stored by App::PropertyEnumeration +/// A bidirectional string-integer mapping +/*! + * This is mainly intended for two purposes: working around the difficulty + * in C++ of sharing enumerations between different source files, + * namespaces, etc. and as the data type stored by App::PropertyEnumeration + * + * Internally, Enumeration maintains + * -# Either a const pointer to an array of C-style strings, or a vector + * of C++ std::strings + * -# An integer index into that array/vector representing the string + * representing the instance's value. + * + * If built with FC_DEBUG defined, some boundaries of passed in pointers + * will be checked. Otherwise, the caller has the responsibility of + * checking the limits of given indices. + * + * \todo Implement lazy copy + */ +class AppExport Enumeration +{ +public: + class Object + { + public: + virtual ~Object() = default; + virtual const char* data() const = 0; + virtual bool isEqual(const char*) const = 0; + virtual bool isCustom() const = 0; + }; + +public: + /// Constructs an empty Enumeration object + Enumeration(); + + /// Standard copy constructor + Enumeration(const Enumeration& other); + + /// Constructs an Enumeration with a single element + explicit Enumeration(const char* valStr); + + /// Constructs an Enumeration using val within list + Enumeration(const char** list, const char* valStr); + + /// Standard destructor + ~Enumeration(); + + /** Sets the enumeration string list + * The list is a NULL terminated array of pointers to const + * char* strings. + * \code + * const char enums[] = {"Black","White","Other",NULL} + * \endcode * - * Internally, Enumeration maintains - * -# Either a const pointer to an array of C-style strings, or a vector - * of C++ std::strings - * -# An integer index into that array/vector representing the string - * representing the instance's value. + * If Enumeration was already valid, will attempt to preserve + * the string-representation value of the Enumeration * - * If built with FC_DEBUG defined, some boundaries of passed in pointers - * will be checked. Otherwise, the caller has the responsibility of - * checking the limits of given indices. + * Enumeration does not take ownership of the passed object + */ + void setEnums(const char** plEnums); + + /// Set all enum values as vector of strings + /*! + * This method causes the Enumeration to dynamically allocate + * it's own array of C Strings, which will be deleted by the + * destructor or subsequent calls to setEnums(). So, it is + * important to make sure the Enumeration stays in scope as + * long as values returned by getCStr are in use. * - * \todo Implement lazy copy + * If Enumeration was already valid, will attempt to preserve + * the string-representation value of the Enumeration */ - class AppExport Enumeration + void setEnums(const std::vector& values); + + /// Set the enum using a C string + void setValue(const char* value); + + /// Overload of setValue(const char *value) + void setValue(const std::string& value) { - public: - class Object { - public: - virtual ~Object() = default; - virtual const char* data() const = 0; - virtual bool isEqual(const char*) const = 0; - virtual bool isCustom() const = 0; - }; + setValue(value.c_str()); + } - public: - /// Constructs an empty Enumeration object - Enumeration(); - - /// Standard copy constructor - Enumeration(const Enumeration& other); - - /// Constructs an Enumeration with a single element - explicit Enumeration(const char *valStr); - - /// Constructs an Enumeration using val within list - Enumeration(const char **list, const char *valStr); - - /// Standard destructor - ~Enumeration(); - - /** Sets the enumeration string list - * The list is a NULL terminated array of pointers to const - * char* strings. - * \code - * const char enums[] = {"Black","White","Other",NULL} - * \endcode - * - * If Enumeration was already valid, will attempt to preserve - * the string-representation value of the Enumeration - * - * Enumeration does not take ownership of the passed object - */ - void setEnums(const char **plEnums); - - /// Set all enum values as vector of strings - /*! - * This method causes the Enumeration to dynamically allocate - * it's own array of C Strings, which will be deleted by the - * destructor or subsequent calls to setEnums(). So, it is - * important to make sure the Enumeration stays in scope as - * long as values returned by getCStr are in use. - * - * If Enumeration was already valid, will attempt to preserve - * the string-representation value of the Enumeration - */ - void setEnums(const std::vector &values); - - /// Set the enum using a C string - void setValue(const char *value); - - /// Overload of setValue(const char *value) - void setValue(const std::string &value) {setValue(value.c_str());} - - /// Set the enum using a long - /*! - * if checkRange is set to true, throws Base::ValueError when - * values are set out of range - * - * Checks for boundaries via assert() - */ - void setValue(long value, bool checkRange = false); - - /// Checks if the property is set to a certain string value - bool isValue(const char *value) const; - - /// Checks if a string is included in the enumeration - bool contains(const char *value) const; - - /// Return the value as C string - /*! - * Returns NULL if the enumeration is invalid. - */ - const char * getCStr() const; - - /// Return value as integer - /*! - * Returns -1 if the Enumeration isn't valid - */ - int getInt() const; - - /// get all possible enum values as vector of strings - std::vector getEnumVector() const; - - /// returns true if the enum list is non-empty, false otherwise - bool hasEnums() const; - - /// Returns true if the instance is in a usable state - bool isValid() const; - - /// Returns the highest usable integer value for this enum - /*! - * Returns -1 if the enumeration is not valid according to isValid() - */ - int maxValue() const; - - /// Returns true if any of the items is a user-defined string - bool isCustom() const; - - /// Assignment operator - Enumeration & operator=(const Enumeration &other); - - /// true iff our string representation matches other's - /*! - * Returns false if either Enumeration is not valid. - */ - bool operator==(const Enumeration &other) const; - - /// true iff our string representation matches other - /*! - * Returns false if Enumeration is not valid. - */ - bool operator==(const char *other) const; - protected: - - /// Number of items - int countItems() const; - - private: - /// Handle to C Strings of possible enumeration values - using ObjectPtr = std::shared_ptr; - std::vector enumArray; - - /// Integer value of the enumeration - /*! - * This serves as an index into enumArray to get the string - * representation. - */ - int _index; - - friend class PropertyEnumeration; - }; // class Enumeration -} // namespace App - -#endif // #ifndef BASE_ENUMERATION_H + /// Set the enum using a long + /*! + * if checkRange is set to true, throws Base::ValueError when + * values are set out of range + * + * Checks for boundaries via assert() + */ + void setValue(long value, bool checkRange = false); + + /// Checks if the property is set to a certain string value + bool isValue(const char* value) const; + + /// Checks if a string is included in the enumeration + bool contains(const char* value) const; + + /// Return the value as C string + /*! + * Returns NULL if the enumeration is invalid. + */ + const char* getCStr() const; + + /// Return value as integer + /*! + * Returns -1 if the Enumeration isn't valid + */ + int getInt() const; + + /// get all possible enum values as vector of strings + std::vector getEnumVector() const; + + /// returns true if the enum list is non-empty, false otherwise + bool hasEnums() const; + + /// Returns true if the instance is in a usable state + bool isValid() const; + + /// Returns the highest usable integer value for this enum + /*! + * Returns -1 if the enumeration is not valid according to isValid() + */ + int maxValue() const; + + /// Returns true if any of the items is a user-defined string + bool isCustom() const; + + /// Assignment operator + Enumeration& operator=(const Enumeration& other); + + /// true iff our string representation matches other's + /*! + * Returns false if either Enumeration is not valid. + */ + bool operator==(const Enumeration& other) const; + + /// true iff our string representation matches other + /*! + * Returns false if Enumeration is not valid. + */ + bool operator==(const char* other) const; + +protected: + /// Number of items + int countItems() const; + +private: + /// Handle to C Strings of possible enumeration values + using ObjectPtr = std::shared_ptr; + std::vector enumArray; + + /// Integer value of the enumeration + /*! + * This serves as an index into enumArray to get the string + * representation. + */ + int _index; + + friend class PropertyEnumeration; +}; // class Enumeration +} // namespace App + +#endif // #ifndef BASE_ENUMERATION_H diff --git a/src/App/Extension.cpp b/src/App/Extension.cpp index 8fa6ecc0a145..51ba5fff7cb1 100644 --- a/src/App/Extension.cpp +++ b/src/App/Extension.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -39,167 +39,201 @@ * PropertyData in the extension chain, there is no parent property data. */ EXTENSION_TYPESYSTEM_SOURCE_P(App::Extension) -const App::PropertyData * App::Extension::extensionGetPropertyDataPtr(){return &propertyData;} -const App::PropertyData & App::Extension::extensionGetPropertyData() const{return propertyData;} +const App::PropertyData* App::Extension::extensionGetPropertyDataPtr() +{ + return &propertyData; +} +const App::PropertyData& App::Extension::extensionGetPropertyData() const +{ + return propertyData; +} App::PropertyData App::Extension::propertyData; -void App::Extension::init(){ +void App::Extension::init() +{ assert(Extension::classTypeId == Base::Type::badType() && "don't init() twice!"); /* Set up entry in the type system. */ - Extension::classTypeId = Base::Type::createType(Base::Type::badType(), "App::Extension", - Extension::create); + Extension::classTypeId = + Base::Type::createType(Base::Type::badType(), "App::Extension", Extension::create); } using namespace App; Extension::~Extension() { - if (!ExtensionPythonObject.is(Py::_None())){ + if (!ExtensionPythonObject.is(Py::_None())) { // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed - // Python object or not. In the constructor we forced the wrapper to own the object so we need - // not to dec'ref the Python object any more. - // But we must still invalidate the Python object because it need not to be - // destructed right now because the interpreter can own several references to it. + // Python object or not. In the constructor we forced the wrapper to own the object so we + // need not to dec'ref the Python object any more. But we must still invalidate the Python + // object because it need not to be destructed right now because the interpreter can own + // several references to it. Base::PyObjectBase* obj = static_cast(ExtensionPythonObject.ptr()); // Call before decrementing the reference counter, otherwise a heap error can occur obj->setInvalid(); } } -void Extension::initExtensionType(Base::Type type) { +void Extension::initExtensionType(Base::Type type) +{ m_extensionType = type; - if (m_extensionType.isBad()) + if (m_extensionType.isBad()) { throw Base::RuntimeError("Extension: Extension type not set"); + } } -void Extension::initExtension(ExtensionContainer* obj) { - if (m_extensionType.isBad()) +void Extension::initExtension(ExtensionContainer* obj) +{ + if (m_extensionType.isBad()) { throw Base::RuntimeError("Extension: Extension type not set"); + } - //all properties are initialised without PropertyContainer father. Now that we know it we can - //finally finish the property initialisation + // all properties are initialised without PropertyContainer father. Now that we know it we can + // finally finish the property initialisation std::vector list; extensionGetPropertyData().getPropertyList(this, list); - for(Property* prop : list) + for (Property* prop : list) { prop->setContainer(obj); + } m_base = obj; - m_base->registerExtension( m_extensionType, this ); + m_base->registerExtension(m_extensionType, this); } -PyObject* Extension::getExtensionPyObject() { +PyObject* Extension::getExtensionPyObject() +{ - if (ExtensionPythonObject.is(Py::_None())){ + if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 auto grp = new ExtensionPy(this); - ExtensionPythonObject = Py::Object(grp,true); + ExtensionPythonObject = Py::Object(grp, true); } return Py::new_reference_to(ExtensionPythonObject); } -std::string Extension::name() const { +std::string Extension::name() const +{ - if (m_extensionType.isBad()) + if (m_extensionType.isBad()) { throw Base::RuntimeError("Extension::name: Extension type not set"); + } std::string temp(m_extensionType.getName()); std::string::size_type pos = temp.find_last_of(':'); - if (pos != std::string::npos) - return temp.substr(pos+1); + if (pos != std::string::npos) { + return temp.substr(pos + 1); + } return {}; } -Property* Extension::extensionGetPropertyByName(const char* name) const { +Property* Extension::extensionGetPropertyByName(const char* name) const +{ return extensionGetPropertyData().getPropertyByName(this, name); } -short int Extension::extensionGetPropertyType(const Property* prop) const { +short int Extension::extensionGetPropertyType(const Property* prop) const +{ return extensionGetPropertyData().getType(this, prop); } -short int Extension::extensionGetPropertyType(const char* name) const { +short int Extension::extensionGetPropertyType(const char* name) const +{ return extensionGetPropertyData().getType(this, name); } -const char* Extension::extensionGetPropertyName(const Property* prop) const { +const char* Extension::extensionGetPropertyName(const Property* prop) const +{ - return extensionGetPropertyData().getName(this,prop); + return extensionGetPropertyData().getName(this, prop); } -const char* Extension::extensionGetPropertyGroup(const Property* prop) const { +const char* Extension::extensionGetPropertyGroup(const Property* prop) const +{ - return extensionGetPropertyData().getGroup(this,prop); + return extensionGetPropertyData().getGroup(this, prop); } -const char* Extension::extensionGetPropertyGroup(const char* name) const { +const char* Extension::extensionGetPropertyGroup(const char* name) const +{ - return extensionGetPropertyData().getGroup(this,name); + return extensionGetPropertyData().getGroup(this, name); } -const char* Extension::extensionGetPropertyDocumentation(const Property* prop) const { +const char* Extension::extensionGetPropertyDocumentation(const Property* prop) const +{ return extensionGetPropertyData().getDocumentation(this, prop); } -const char* Extension::extensionGetPropertyDocumentation(const char* name) const { +const char* Extension::extensionGetPropertyDocumentation(const char* name) const +{ return extensionGetPropertyData().getDocumentation(this, name); } -void Extension::extensionGetPropertyList(std::vector< Property* >& List) const { +void Extension::extensionGetPropertyList(std::vector& List) const +{ extensionGetPropertyData().getPropertyList(this, List); } -void Extension::extensionGetPropertyMap(std::map< std::string, Property* >& Map) const { +void Extension::extensionGetPropertyMap(std::map& Map) const +{ extensionGetPropertyData().getPropertyMap(this, Map); } -void Extension::initExtensionSubclass(Base::Type& toInit, const char* ClassName, const char* ParentName, - Base::Type::instantiationMethod method) { +void Extension::initExtensionSubclass(Base::Type& toInit, + const char* ClassName, + const char* ParentName, + Base::Type::instantiationMethod method) +{ // don't init twice! assert(toInit == Base::Type::badType()); // get the parent class Base::Type parentType(Base::Type::fromName(ParentName)); // forgot init parent! - assert(parentType != Base::Type::badType() ); + assert(parentType != Base::Type::badType()); // create the new type toInit = Base::Type::createType(parentType, ClassName, method); } -bool Extension::extensionHandleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) +bool Extension::extensionHandleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) { - (void) reader; - (void) TypeName; - (void) PropName; + (void)reader; + (void)TypeName; + (void)PropName; return false; }; -bool Extension::extensionHandleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop) +bool Extension::extensionHandleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + Property* prop) { - (void) reader; - (void) TypeName; - (void) prop; + (void)reader; + (void)TypeName; + (void)prop; return false; }; -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::ExtensionPython, App::ExtensionPython::Inherited) // explicit template instantiation template class AppExport ExtensionPythonT; -} +} // namespace App diff --git a/src/App/ExtensionContainer.cpp b/src/App/ExtensionContainer.cpp index 6702621ff913..2fd642990d17 100644 --- a/src/App/ExtensionContainer.cpp +++ b/src/App/ExtensionContainer.cpp @@ -38,23 +38,28 @@ TYPESYSTEM_SOURCE(App::ExtensionContainer, App::PropertyContainer) ExtensionContainer::ExtensionContainer() = default; -ExtensionContainer::~ExtensionContainer() { +ExtensionContainer::~ExtensionContainer() +{ - //we need to delete all dynamically added extensions - for(const auto& entry : _extensions) { - if(entry.second->isPythonExtension()) + // we need to delete all dynamically added extensions + for (const auto& entry : _extensions) { + if (entry.second->isPythonExtension()) { delete entry.second; + } } } -void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext) { - if(ext->getExtendedContainer() != this) - throw Base::ValueError("ExtensionContainer::registerExtension: Extension has not this as base object"); +void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext) +{ + if (ext->getExtendedContainer() != this) { + throw Base::ValueError( + "ExtensionContainer::registerExtension: Extension has not this as base object"); + } - //no duplicate extensions (including base classes) - if(hasExtension(extension)) { - for(const auto& entry : _extensions) { - if(entry.first == extension || entry.first.isDerivedFrom(extension)) { + // no duplicate extensions (including base classes) + if (hasExtension(extension)) { + for (const auto& entry : _extensions) { + if (entry.first == extension || entry.first.isDerivedFrom(extension)) { _extensions.erase(entry.first); break; } @@ -64,275 +69,325 @@ void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext) _extensions[extension] = ext; } -bool ExtensionContainer::hasExtension(Base::Type t, bool derived) const { +bool ExtensionContainer::hasExtension(Base::Type t, bool derived) const +{ - //check for the exact type + // check for the exact type bool found = _extensions.find(t) != _extensions.end(); - if(!found && derived) { - //and for types derived from it, as they can be cast to the extension - for(const auto& entry : _extensions) { - if(entry.first.isDerivedFrom(t)) + if (!found && derived) { + // and for types derived from it, as they can be cast to the extension + for (const auto& entry : _extensions) { + if (entry.first.isDerivedFrom(t)) { return true; + } } return false; } return found; } -bool ExtensionContainer::hasExtension(const std::string& name) const { +bool ExtensionContainer::hasExtension(const std::string& name) const +{ - //and for types derived from it, as they can be cast to the extension - for(const auto& entry : _extensions) { - if(entry.second->name() == name) + // and for types derived from it, as they can be cast to the extension + for (const auto& entry : _extensions) { + if (entry.second->name() == name) { return true; + } } return false; } -Extension* ExtensionContainer::getExtension(Base::Type t, bool derived, bool no_except) const { +Extension* ExtensionContainer::getExtension(Base::Type t, bool derived, bool no_except) const +{ auto result = _extensions.find(t); - if((result == _extensions.end()) && derived) { - //we need to check for derived types - for(const auto& entry : _extensions) { - if(entry.first.isDerivedFrom(t)) + if ((result == _extensions.end()) && derived) { + // we need to check for derived types + for (const auto& entry : _extensions) { + if (entry.first.isDerivedFrom(t)) { return entry.second; + } } - if(no_except) + if (no_except) { return nullptr; - //if we arrive here we don't have anything matching - throw Base::TypeError("ExtensionContainer::getExtension: No extension of given type available"); + } + // if we arrive here we don't have anything matching + throw Base::TypeError( + "ExtensionContainer::getExtension: No extension of given type available"); } else if (result != _extensions.end()) { return result->second; } else { - if(no_except) + if (no_except) { return nullptr; - //if we arrive here we don't have anything matching - throw Base::TypeError("ExtensionContainer::getExtension: No extension of given type available"); + } + // if we arrive here we don't have anything matching + throw Base::TypeError( + "ExtensionContainer::getExtension: No extension of given type available"); } } -bool ExtensionContainer::hasExtensions() const { +bool ExtensionContainer::hasExtensions() const +{ return !_extensions.empty(); } -Extension* ExtensionContainer::getExtension(const std::string& name) const { +Extension* ExtensionContainer::getExtension(const std::string& name) const +{ - //and for types derived from it, as they can be cast to the extension - for(const auto& entry : _extensions) { - if(entry.second->name() == name) + // and for types derived from it, as they can be cast to the extension + for (const auto& entry : _extensions) { + if (entry.second->name() == name) { return entry.second; + } } return nullptr; } -std::vector< Extension* > ExtensionContainer::getExtensionsDerivedFrom(Base::Type type) const { +std::vector ExtensionContainer::getExtensionsDerivedFrom(Base::Type type) const +{ std::vector vec; - //and for types derived from it, as they can be cast to the extension - for(const auto& entry : _extensions) { - if(entry.first.isDerivedFrom(type)) + // and for types derived from it, as they can be cast to the extension + for (const auto& entry : _extensions) { + if (entry.first.isDerivedFrom(type)) { vec.push_back(entry.second); + } } return vec; } -void ExtensionContainer::getPropertyList(std::vector< Property* >& List) const { +void ExtensionContainer::getPropertyList(std::vector& List) const +{ App::PropertyContainer::getPropertyList(List); - for(const auto& entry : _extensions) + for (const auto& entry : _extensions) { entry.second->extensionGetPropertyList(List); + } } -void ExtensionContainer::getPropertyMap(std::map< std::string, Property* >& Map) const { +void ExtensionContainer::getPropertyMap(std::map& Map) const +{ App::PropertyContainer::getPropertyMap(Map); - for(const auto& entry : _extensions) + for (const auto& entry : _extensions) { entry.second->extensionGetPropertyMap(Map); + } } -Property* ExtensionContainer::getPropertyByName(const char* name) const { +Property* ExtensionContainer::getPropertyByName(const char* name) const +{ auto prop = App::PropertyContainer::getPropertyByName(name); - if(prop) + if (prop) { return prop; + } - for(const auto& entry : _extensions) { + for (const auto& entry : _extensions) { auto prop = entry.second->extensionGetPropertyByName(name); - if(prop) + if (prop) { return prop; + } } return nullptr; } -short int ExtensionContainer::getPropertyType(const Property* prop) const { +short int ExtensionContainer::getPropertyType(const Property* prop) const +{ short int res = App::PropertyContainer::getPropertyType(prop); - if(res != 0) + if (res != 0) { return res; + } - for(const auto& entry : _extensions) { + for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyType(prop); - if(res != 0) + if (res != 0) { return res; + } } return 0; } -short int ExtensionContainer::getPropertyType(const char* name) const { +short int ExtensionContainer::getPropertyType(const char* name) const +{ short int res = App::PropertyContainer::getPropertyType(name); - if(res != 0) + if (res != 0) { return res; + } - for(const auto& entry : _extensions) { + for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyType(name); - if(res != 0) + if (res != 0) { return res; + } } return 0; } -const char* ExtensionContainer::getPropertyName(const Property* prop) const { +const char* ExtensionContainer::getPropertyName(const Property* prop) const +{ const char* res = App::PropertyContainer::getPropertyName(prop); - if (res) + if (res) { return res; + } for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyName(prop); - if (res) + if (res) { return res; + } } return nullptr; } -const char* ExtensionContainer::getPropertyGroup(const Property* prop) const { +const char* ExtensionContainer::getPropertyGroup(const Property* prop) const +{ const char* res = App::PropertyContainer::getPropertyGroup(prop); - if (res) + if (res) { return res; + } for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyGroup(prop); - if (res) + if (res) { return res; + } } return nullptr; } -const char* ExtensionContainer::getPropertyGroup(const char* name) const { +const char* ExtensionContainer::getPropertyGroup(const char* name) const +{ const char* res = App::PropertyContainer::getPropertyGroup(name); - if (res) + if (res) { return res; + } for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyGroup(name); - if (res) + if (res) { return res; + } } return nullptr; } -const char* ExtensionContainer::getPropertyDocumentation(const Property* prop) const { +const char* ExtensionContainer::getPropertyDocumentation(const Property* prop) const +{ const char* res = App::PropertyContainer::getPropertyDocumentation(prop); - if (res) + if (res) { return res; + } for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyDocumentation(prop); - if (res) + if (res) { return res; + } } return nullptr; } -const char* ExtensionContainer::getPropertyDocumentation(const char* name) const { +const char* ExtensionContainer::getPropertyDocumentation(const char* name) const +{ const char* res = App::PropertyContainer::getPropertyDocumentation(name); - if (res) + if (res) { return res; + } - for(const auto& entry : _extensions) { + for (const auto& entry : _extensions) { res = entry.second->extensionGetPropertyDocumentation(name); - if (res) + if (res) { return res; + } } return nullptr; } -void ExtensionContainer::onChanged(const Property* prop) { +void ExtensionContainer::onChanged(const Property* prop) +{ - //inform all extensions about changed property. This includes all properties from the - //extended object (this) as well as all extension properties - for(const auto& entry : _extensions) + // inform all extensions about changed property. This includes all properties from the + // extended object (this) as well as all extension properties + for (const auto& entry : _extensions) { entry.second->extensionOnChanged(prop); + } App::PropertyContainer::onChanged(prop); } -void ExtensionContainer::Save(Base::Writer& writer) const { +void ExtensionContainer::Save(Base::Writer& writer) const +{ - //Note: save extensions must be called first to ensure that the extension element is always the - // very first inside the object element. This is needed since extension element works together with - // an object attribute, and if another element would be read first the object attributes would be - // cleared. + // Note: save extensions must be called first to ensure that the extension element is always the + // very first inside the object element. This is needed since extension element works + // together with an object attribute, and if another element would be read first the + // object attributes would be cleared. saveExtensions(writer); App::PropertyContainer::Save(writer); } -void ExtensionContainer::Restore(Base::XMLReader& reader) { +void ExtensionContainer::Restore(Base::XMLReader& reader) +{ - //restore dynamic extensions. - //Note 1: The extension element must be read first, before all other object elements. That is - // needed as the element works together with an object element attribute, which would be - // cleared if another attribute is read first - //Note 2: This must happen before the py object of this container is used, as only in the - // pyobject constructor the extension methods are added to the container. + // restore dynamic extensions. + // Note 1: The extension element must be read first, before all other object elements. That is + // needed as the element works together with an object element attribute, which would be + // cleared if another attribute is read first + // Note 2: This must happen before the py object of this container is used, as only in the + // pyobject constructor the extension methods are added to the container. restoreExtensions(reader); App::PropertyContainer::Restore(reader); } -void ExtensionContainer::saveExtensions(Base::Writer& writer) const { +void ExtensionContainer::saveExtensions(Base::Writer& writer) const +{ - //we don't save anything if there are no dynamic extensions - if(!hasExtensions()) + // we don't save anything if there are no dynamic extensions + if (!hasExtensions()) { return; + } - //save dynamic extensions - writer.incInd(); // indentation for 'Extensions' - writer.Stream() << writer.ind() << "" << std::endl; - for(const auto& entry : _extensions) { + // save dynamic extensions + writer.incInd(); // indentation for 'Extensions' + writer.Stream() << writer.ind() << "" + << std::endl; + for (const auto& entry : _extensions) { auto ext = entry.second; - writer.incInd(); // indentation for 'Extension name' + writer.incInd(); // indentation for 'Extension name' writer.Stream() << writer.ind() << "getExtensionTypeId().getName() <<"\"" - << " name=\"" << ext->name() << "\">" << std::endl; - writer.incInd(); // indentation for the actual Extension + << " type=\"" << ext->getExtensionTypeId().getName() << "\"" + << " name=\"" << ext->name() << "\">" << std::endl; + writer.incInd(); // indentation for the actual Extension try { // We must make sure to handle all exceptions accordingly so that // the project file doesn't get invalidated. In the error case this // means to proceed instead of aborting the write operation. ext->extensionSave(writer); } - catch (const Base::Exception &e) { + catch (const Base::Exception& e) { Base::Console().Error("%s\n", e.what()); } - catch (const std::exception &e) { + catch (const std::exception& e) { Base::Console().Error("%s\n", e.what()); } catch (const char* e) { @@ -340,47 +395,51 @@ void ExtensionContainer::saveExtensions(Base::Writer& writer) const { } #ifndef FC_DEBUG catch (...) { - Base::Console().Error("ExtensionContainer::Save: Unknown C++ exception thrown. Try to continue...\n"); + Base::Console().Error( + "ExtensionContainer::Save: Unknown C++ exception thrown. Try to continue...\n"); } #endif - writer.decInd(); // indentation for the actual extension + writer.decInd(); // indentation for the actual extension writer.Stream() << writer.ind() << "" << std::endl; - writer.decInd(); // indentation for 'Extension name' + writer.decInd(); // indentation for 'Extension name' } writer.Stream() << writer.ind() << "" << std::endl; writer.decInd(); } -void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) { +void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) +{ - //Dynamic extensions are optional (also because they are introduced late into the document format) - //and hence it is possible that the element does not exist. As we cannot check for the existence of - //an element a object attribute is set if extensions are available. Here we check that - //attribute, and only if it exists the extensions element will be available. - if(!reader.hasAttribute("Extensions")) + // Dynamic extensions are optional (also because they are introduced late into the document + // format) and hence it is possible that the element does not exist. As we cannot check for the + // existence of an element a object attribute is set if extensions are available. Here we check + // that attribute, and only if it exists the extensions element will be available. + if (!reader.hasAttribute("Extensions")) { return; + } reader.readElement("Extensions"); int Cnt = reader.getAttributeAsInteger("Count"); - for (int i=0 ;i(extension.createInstance()); - //check if this really is a python extension! + // check if this really is a python extension! if (!ext->isPythonExtension()) { delete ext; std::stringstream str; @@ -390,16 +449,17 @@ void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) { ext->initExtension(this); } - if (ext && strcmp(ext->getExtensionTypeId().getName(), Type) == 0) + if (ext && strcmp(ext->getExtensionTypeId().getName(), Type) == 0) { ext->extensionRestore(reader); + } } catch (const Base::XMLParseException&) { - throw; // re-throw + throw; // re-throw } - catch (const Base::Exception &e) { + catch (const Base::Exception& e) { Base::Console().Error("%s\n", e.what()); } - catch (const std::exception &e) { + catch (const std::exception& e) { Base::Console().Error("%s\n", e.what()); } catch (const char* e) { @@ -416,29 +476,35 @@ void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) { reader.readEndElement("Extensions"); } -void ExtensionContainer::handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) +void ExtensionContainer::handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) { - //inform all extensions about changed property name. This includes all properties from the - //extended object (this) as well as all extension properties - for(const auto& entry : _extensions) { + // inform all extensions about changed property name. This includes all properties from the + // extended object (this) as well as all extension properties + for (const auto& entry : _extensions) { bool handled = entry.second->extensionHandleChangedPropertyName(reader, TypeName, PropName); - if(handled) - return; // one property change needs only be handled once + if (handled) { + return; // one property change needs only be handled once + } } PropertyContainer::handleChangedPropertyName(reader, TypeName, PropName); } -void ExtensionContainer::handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop) +void ExtensionContainer::handleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + Property* prop) { - //inform all extensions about changed property type. This includes all properties from the - //extended object (this) as well as all extension properties - for(const auto& entry : _extensions) { + // inform all extensions about changed property type. This includes all properties from the + // extended object (this) as well as all extension properties + for (const auto& entry : _extensions) { bool handled = entry.second->extensionHandleChangedPropertyType(reader, TypeName, prop); - if(handled) - return; // one property change needs only be handled once + if (handled) { + return; // one property change needs only be handled once + } } PropertyContainer::handleChangedPropertyType(reader, TypeName, prop); diff --git a/src/App/ExtensionContainer.h b/src/App/ExtensionContainer.h index 7ff7091a3c7b..9ef6999b1263 100644 --- a/src/App/ExtensionContainer.h +++ b/src/App/ExtensionContainer.h @@ -27,7 +27,8 @@ #include "PropertyContainer.h" -namespace App { +namespace App +{ class Extension; /** @@ -49,14 +50,14 @@ class Extension; * - Extensions can be added from c++ and python, even from both together * * The interoperability with python is highly important, as in FreeCAD all functionality should be - * as easily accessible from python as from c++. To ensure this, and as already noted, extensions can - * be added to a object from python. However, this means that it is not clear from the c++ object type - * if an extension was added or not. If added from c++ it becomes clear in the type due to the use of - * multiple inheritance. If added from python it is a runtime extension and not visible from type. - * Hence querying existing extensions of an object and accessing its methods works not by type - * casting but by the interface provided in ExtensionContainer. The default workflow is to query if - * an extension exists and then get the extension object. No matter if added from python or c++ this - * interface works always the same. + * as easily accessible from python as from c++. To ensure this, and as already noted, extensions + * can be added to a object from python. However, this means that it is not clear from the c++ + * object type if an extension was added or not. If added from c++ it becomes clear in the type due + * to the use of multiple inheritance. If added from python it is a runtime extension and not + * visible from type. Hence querying existing extensions of an object and accessing its methods + * works not by type casting but by the interface provided in ExtensionContainer. The default + * workflow is to query if an extension exists and then get the extension object. No matter if added + * from python or c++ this interface works always the same. * @code * if (object->hasExtension(GroupExtension::getClassTypeId())) { * App::GroupExtension* group = object->getExtensionByType(); @@ -77,8 +78,8 @@ class Extension; * * Here is a working example: * @code - * class AppExport Part : public App::DocumentObject, public App::FirstExtension, public App::SecondExtension { - * PROPERTY_HEADER_WITH_EXTENSIONS(App::Part); + * class AppExport Part : public App::DocumentObject, public App::FirstExtension, public + * App::SecondExtension { PROPERTY_HEADER_WITH_EXTENSIONS(App::Part); * }; * PROPERTY_SOURCE_WITH_EXTENSIONS(App::Part, App::DocumentObject) * Part::Part(void) { @@ -88,9 +89,9 @@ class Extension; * @endcode * * From python adding an extension is easier, it must be simply registered to a document object - * at object initialisation like done with properties. Note that the special python extension objects - * need to be added, not the c++ objects. Normally the only difference in name is the additional - * "Python" at the end of the extension name. + * at object initialisation like done with properties. Note that the special python extension + * objects need to be added, not the c++ objects. Normally the only difference in name is the + * additional "Python" at the end of the extension name. * @code{.py} * class Test(): * __init(self)__: @@ -99,86 +100,98 @@ class Extension; * @endcode * * Extensions can provide methods that should be overridden by the extended object for customisation - * of the extension behaviour. In c++ this is as simple as overriding the provided virtual functions. - * In python a class method must be provided which has the same name as the method to override. This - * method must not necessarily be in the object that is extended, it must be in the object which is - * provided to the "registerExtension" call as second argument. This second argument is used as a - * proxy and enqueired if the method to override exists in this proxy before calling it. + * of the extension behaviour. In c++ this is as simple as overriding the provided virtual + * functions. In python a class method must be provided which has the same name as the method to + * override. This method must not necessarily be in the object that is extended, it must be in the + * object which is provided to the "registerExtension" call as second argument. This second argument + * is used as a proxy and enqueired if the method to override exists in this proxy before calling + * it. * * For information on howto create extension see the documentation of Extension */ -class AppExport ExtensionContainer : public App::PropertyContainer +class AppExport ExtensionContainer: public App::PropertyContainer { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - using ExtensionIterator = std::map::iterator; ExtensionContainer(); ~ExtensionContainer() override; void registerExtension(Base::Type extension, App::Extension* ext); - //returns first of type (or derived from if set to true) and throws otherwise - bool hasExtension(Base::Type, bool derived=true) const; - //this version does not check derived classes + // returns first of type (or derived from if set to true) and throws otherwise + bool hasExtension(Base::Type, bool derived = true) const; + // this version does not check derived classes bool hasExtension(const std::string& name) const; bool hasExtensions() const; - App::Extension* getExtension(Base::Type, bool derived = true, bool no_except=false) const; - //this version does not check derived classes + App::Extension* getExtension(Base::Type, bool derived = true, bool no_except = false) const; + // this version does not check derived classes App::Extension* getExtension(const std::string& name) const; // this version checks for derived types and doesn't throw template - ExtensionT* getExtension() const { - return static_cast(getExtension(ExtensionT::getExtensionClassTypeId(), true, true)); + ExtensionT* getExtension() const + { + return static_cast( + getExtension(ExtensionT::getExtensionClassTypeId(), true, true)); } - //returns first of type (or derived from) and throws otherwise + // returns first of type (or derived from) and throws otherwise template - ExtensionT* getExtensionByType(bool no_except=false, bool derived=true) const { - return static_cast(getExtension(ExtensionT::getExtensionClassTypeId(),derived,no_except)); + ExtensionT* getExtensionByType(bool no_except = false, bool derived = true) const + { + return static_cast( + getExtension(ExtensionT::getExtensionClassTypeId(), derived, no_except)); } - //get all extensions which have the given base class + // get all extensions which have the given base class std::vector getExtensionsDerivedFrom(Base::Type type) const; template - std::vector getExtensionsDerivedFromType() const { + std::vector getExtensionsDerivedFromType() const + { std::vector typevec; - for(const auto& entry : _extensions) { - if(entry.first.isDerivedFrom(ExtensionT::getExtensionClassTypeId())) + for (const auto& entry : _extensions) { + if (entry.first.isDerivedFrom(ExtensionT::getExtensionClassTypeId())) { typevec.push_back(static_cast(entry.second)); + } } return typevec; } - ExtensionIterator extensionBegin() {return _extensions.begin();} - ExtensionIterator extensionEnd() {return _extensions.end();} + ExtensionIterator extensionBegin() + { + return _extensions.begin(); + } + ExtensionIterator extensionEnd() + { + return _extensions.end(); + } /** @name Access properties */ //@{ /// find a property by its name - Property *getPropertyByName(const char* name) const override; + Property* getPropertyByName(const char* name) const override; /// get the name of a property const char* getPropertyName(const Property* prop) const override; /// get all properties of the class (including properties of the parent) - void getPropertyMap(std::map &Map) const override; + void getPropertyMap(std::map& Map) const override; /// get all properties of the class (including properties of the parent) - void getPropertyList(std::vector &List) const override; + void getPropertyList(std::vector& List) const override; /// get the Type of a Property short getPropertyType(const Property* prop) const override; /// get the Type of a named Property - short getPropertyType(const char *name) const override; + short getPropertyType(const char* name) const override; /// get the Group of a Property const char* getPropertyGroup(const Property* prop) const override; /// get the Group of a named Property - const char* getPropertyGroup(const char *name) const override; + const char* getPropertyGroup(const char* name) const override; /// get the Group of a Property const char* getPropertyDocumentation(const Property* prop) const override; /// get the Group of a named Property - const char* getPropertyDocumentation(const char *name) const override; + const char* getPropertyDocumentation(const char* name) const override; //@} void onChanged(const Property*) override; @@ -186,43 +199,50 @@ class AppExport ExtensionContainer : public App::PropertyContainer void Save(Base::Writer& writer) const override; void Restore(Base::XMLReader& reader) override; - //those methods save/restore the dynamic extensions without handling properties, which is something - //done by the default Save/Restore methods. + // those methods save/restore the dynamic extensions without handling properties, which is + // something done by the default Save/Restore methods. void saveExtensions(Base::Writer& writer) const; void restoreExtensions(Base::XMLReader& reader); - /** Extends the rules for handling property name changed, so that extensions are given an opportunity to handle it. - * If an extension handles a change, neither the rest of the extensions, nor the container itself get to handle it. + /** Extends the rules for handling property name changed, so that extensions are given an + * opportunity to handle it. If an extension handles a change, neither the rest of the + * extensions, nor the container itself get to handle it. * * Extensions get their extensionHandleChangedPropertyName() called. * - * If no extension handles the request, then the containers handleChangedPropertyName() is called. + * If no extension handles the request, then the containers handleChangedPropertyName() is + * called. */ - void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override; - /** Extends the rules for handling property type changed, so that extensions are given an opportunity to handle it. - * If an extension handles a change, neither the rest of the extensions, nor the container itself get to handle it. + void handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) override; + /** Extends the rules for handling property type changed, so that extensions are given an + * opportunity to handle it. If an extension handles a change, neither the rest of the + * extensions, nor the container itself get to handle it. * * Extensions get their extensionHandleChangedPropertyType() called. * - * If no extension handles the request, then the containers handleChangedPropertyType() is called. + * If no extension handles the request, then the containers handleChangedPropertyType() is + * called. */ - void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop) override; + void handleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + Property* prop) override; private: - //stored extensions + // stored extensions std::map _extensions; }; -#define PROPERTY_HEADER_WITH_EXTENSIONS(_class_) \ - PROPERTY_HEADER_WITH_OVERRIDE(_class) +#define PROPERTY_HEADER_WITH_EXTENSIONS(_class_) PROPERTY_HEADER_WITH_OVERRIDE(_class) /// We make sure that the PropertyData of the container is not connected to the one of the extension -#define PROPERTY_SOURCE_WITH_EXTENSIONS(_class_, _parentclass_) \ +#define PROPERTY_SOURCE_WITH_EXTENSIONS(_class_, _parentclass_) \ PROPERTY_SOURCE(_class_, _parentclass_) -#define PROPERTY_SOURCE_ABSTRACT_WITH_EXTENSIONS(_class_, _parentclass_) \ +#define PROPERTY_SOURCE_ABSTRACT_WITH_EXTENSIONS(_class_, _parentclass_) \ PROPERTY_SOURCE_ABSTRACT(_class_, _parentclass_) -} //App +} // namespace App -#endif // APP_EXTENSIONCONTAINER_H +#endif // APP_EXTENSIONCONTAINER_H diff --git a/src/App/ExtensionContainerPy.xml b/src/App/ExtensionContainerPy.xml index 2497c3dda16f..da86226dc5f9 100644 --- a/src/App/ExtensionContainerPy.xml +++ b/src/App/ExtensionContainerPy.xml @@ -1,13 +1,13 @@  - diff --git a/src/App/ExtensionContainerPyImp.cpp b/src/App/ExtensionContainerPyImp.cpp index 3a22b9c906de..0202d0a0b947 100644 --- a/src/App/ExtensionContainerPyImp.cpp +++ b/src/App/ExtensionContainerPyImp.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "Application.h" @@ -41,22 +41,24 @@ std::string ExtensionContainerPy::representation() const return {""}; } -int ExtensionContainerPy::initialization() { +int ExtensionContainerPy::initialization() +{ if (!this->ob_type->tp_dict) { - if (PyType_Ready(this->ob_type) < 0) + if (PyType_Ready(this->ob_type) < 0) { return 0; + } } ExtensionContainer::ExtensionIterator it = this->getExtensionContainerPtr()->extensionBegin(); - for(; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { + for (; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { // The PyTypeObject is shared by all instances of this type and therefore // we have to add new methods only once. PyObject* obj = (*it).second->getExtensionPyObject(); PyMethodDef* meth = obj->ob_type->tp_methods; - PyTypeObject *type = this->ob_type; - PyObject *dict = type->tp_dict; + PyTypeObject* type = this->ob_type; + PyObject* dict = type->tp_dict; // make sure to do the initialization only once if (meth->ml_name) { @@ -67,12 +69,14 @@ int ExtensionContainerPy::initialization() { // to an instance Py_INCREF(dict); while (meth->ml_name) { - PyObject *func; + PyObject* func; func = PyCFunction_New(meth, 0); - if (!func) + if (!func) { break; - if (PyDict_SetItemString(dict, meth->ml_name, func) < 0) + } + if (PyDict_SetItemString(dict, meth->ml_name, func) < 0) { break; + } Py_DECREF(func); ++meth; } @@ -86,20 +90,22 @@ int ExtensionContainerPy::initialization() { return 1; } -int ExtensionContainerPy::finalization() { -/* - //we need to delete all added python extensions, as we are the owner! - ExtensionContainer::ExtensionIterator it = this->getExtensionContainerPtr()->extensionBegin(); - for(; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { - if((*it).second->isPythonExtension()) - delete (*it).second; - }*/ +int ExtensionContainerPy::finalization() +{ + /* + //we need to delete all added python extensions, as we are the owner! + ExtensionContainer::ExtensionIterator it = + this->getExtensionContainerPtr()->extensionBegin(); for(; it != + this->getExtensionContainerPtr()->extensionEnd(); ++it) { + if((*it).second->isPythonExtension()) + delete (*it).second; + }*/ return 1; } -PyObject* ExtensionContainerPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* ExtensionContainerPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { - // create a new instance of @self.export.Name@ and the Twin object + // create a new instance of @self.export.Name@ and the Twin object return nullptr; } @@ -109,7 +115,7 @@ int ExtensionContainerPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) return 0; } -PyObject *ExtensionContainerPy::getCustomAttributes(const char* attr) const +PyObject* ExtensionContainerPy::getCustomAttributes(const char* attr) const { if (Base::streq(attr, "__dict__")) { PyObject* dict = PyDict_New(); @@ -119,12 +125,13 @@ PyObject *ExtensionContainerPy::getCustomAttributes(const char* attr) const Py_DECREF(props); } - ExtensionContainer::ExtensionIterator it = this->getExtensionContainerPtr()->extensionBegin(); + ExtensionContainer::ExtensionIterator it = + this->getExtensionContainerPtr()->extensionBegin(); for (; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { // The PyTypeObject is shared by all instances of this type and therefore // we have to add new methods only once. PyObject* obj = (*it).second->getExtensionPyObject(); - PyTypeObject *tp = Py_TYPE(obj); + PyTypeObject* tp = Py_TYPE(obj); if (tp && tp->tp_dict) { Py_XINCREF(tp->tp_dict); PyDict_Merge(dict, tp->tp_dict, 0); @@ -139,13 +146,13 @@ PyObject *ExtensionContainerPy::getCustomAttributes(const char* attr) const // Py_FindMethod is successful then a PyCFunction_New instance is returned // with the PyObject pointer of the extension to make sure the method will // be called for the correct instance. - PyObject *func = nullptr; + PyObject* func = nullptr; ExtensionContainer::ExtensionIterator it = this->getExtensionContainerPtr()->extensionBegin(); for (; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { // The PyTypeObject is shared by all instances of this type and therefore // we have to add new methods only once. PyObject* obj = (*it).second->getExtensionPyObject(); - PyObject *nameobj = PyUnicode_FromString(attr); + PyObject* nameobj = PyUnicode_FromString(attr); func = PyObject_GenericGetAttr(obj, nameobj); Py_DECREF(nameobj); Py_DECREF(obj); @@ -153,33 +160,36 @@ PyObject *ExtensionContainerPy::getCustomAttributes(const char* attr) const PyCFunctionObject* cfunc = reinterpret_cast(func); // OK, that's what we wanted - if (cfunc->m_self == obj) + if (cfunc->m_self == obj) { break; + } // otherwise cleanup the result again Py_DECREF(func); func = nullptr; } - PyErr_Clear(); // clear the error set inside Py_FindMethod + PyErr_Clear(); // clear the error set inside Py_FindMethod } return func; } -int ExtensionContainerPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/) +int ExtensionContainerPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } -PyObject* ExtensionContainerPy::hasExtension(PyObject *args) { +PyObject* ExtensionContainerPy::hasExtension(PyObject* args) +{ - char *type; - PyObject *deriv = Py_True; - if (!PyArg_ParseTuple(args, "s|O!", &type, &PyBool_Type, &deriv)) + char* type; + PyObject* deriv = Py_True; + if (!PyArg_ParseTuple(args, "s|O!", &type, &PyBool_Type, &deriv)) { return nullptr; + } - //get the extension type asked for + // get the extension type asked for bool derived = Base::asBoolean(deriv); - Base::Type extension = Base::Type::fromName(type); + Base::Type extension = Base::Type::fromName(type); if (extension.isBad() || !extension.isDerivedFrom(App::Extension::getExtensionClassTypeId())) { std::stringstream str; str << "No extension found of type '" << type << "'" << std::ends; @@ -194,30 +204,34 @@ PyObject* ExtensionContainerPy::hasExtension(PyObject *args) { return PyBool_FromLong(val ? 1 : 0); } -PyObject* ExtensionContainerPy::addExtension(PyObject *args) { +PyObject* ExtensionContainerPy::addExtension(PyObject* args) +{ - char *typeId; + char* typeId; PyObject* proxy = nullptr; - if (!PyArg_ParseTuple(args, "s|O", &typeId, &proxy)) + if (!PyArg_ParseTuple(args, "s|O", &typeId, &proxy)) { return nullptr; + } if (proxy) { - PyErr_SetString(PyExc_DeprecationWarning, "Second argument is deprecated. It is ignored and will be removed in future versions. " - "The default Python feature proxy is used for extension method overrides."); + PyErr_SetString( + PyExc_DeprecationWarning, + "Second argument is deprecated. It is ignored and will be removed in future versions. " + "The default Python feature proxy is used for extension method overrides."); PyErr_Print(); } - //get the extension type asked for - Base::Type extension = Base::Type::fromName(typeId); + // get the extension type asked for + Base::Type extension = Base::Type::fromName(typeId); if (extension.isBad() || !extension.isDerivedFrom(App::Extension::getExtensionClassTypeId())) { std::stringstream str; str << "No extension found of type '" << typeId << "'" << std::ends; throw Py::TypeError(str.str()); } - //register the extension + // register the extension App::Extension* ext = static_cast(extension.createInstance()); - //check if this really is a python extension! + // check if this really is a python extension! if (!ext->isPythonExtension()) { delete ext; std::stringstream str; @@ -232,8 +246,8 @@ PyObject* ExtensionContainerPy::addExtension(PyObject *args) { // we have to add new methods only once. PyObject* obj = ext->getExtensionPyObject(); PyMethodDef* meth = obj->ob_type->tp_methods; - PyTypeObject *type = this->ob_type; - PyObject *dict = type->tp_dict; + PyTypeObject* type = this->ob_type; + PyObject* dict = type->tp_dict; // make sure to do the initialization only once if (meth->ml_name) { @@ -244,12 +258,14 @@ PyObject* ExtensionContainerPy::addExtension(PyObject *args) { // to an instance Py_INCREF(dict); while (meth->ml_name) { - PyObject *func; + PyObject* func; func = PyCFunction_New(meth, 0); - if (!func) + if (!func) { break; - if (PyDict_SetItemString(dict, meth->ml_name, func) < 0) + } + if (PyDict_SetItemString(dict, meth->ml_name, func) < 0) { break; + } Py_DECREF(func); ++meth; } @@ -259,8 +275,8 @@ PyObject* ExtensionContainerPy::addExtension(PyObject *args) { } Py_DECREF(obj); - - //throw the appropriate event + + // throw the appropriate event GetApplication().signalAddedDynamicExtension(*getExtensionContainerPtr(), typeId); Py_Return; diff --git a/src/App/ExtensionPy.xml b/src/App/ExtensionPy.xml index a499639e37a7..7551ad1e216f 100644 --- a/src/App/ExtensionPy.xml +++ b/src/App/ExtensionPy.xml @@ -1,13 +1,13 @@  - diff --git a/src/App/ExtensionPyImp.cpp b/src/App/ExtensionPyImp.cpp index b57bcb73a259..23a1cf2b743b 100644 --- a/src/App/ExtensionPyImp.cpp +++ b/src/App/ExtensionPyImp.cpp @@ -37,12 +37,12 @@ std::string ExtensionPy::representation() const return {""}; } -PyObject *ExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* ExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } -int ExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/) +int ExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } diff --git a/src/App/ExtensionPython.h b/src/App/ExtensionPython.h index b6672f15d7d9..6ba59bd548c4 100644 --- a/src/App/ExtensionPython.h +++ b/src/App/ExtensionPython.h @@ -28,21 +28,23 @@ #include "Extension.h" #include "PropertyPythonObject.h" -namespace App { +namespace App +{ /** * Generic Python extension class which allows every extension derived * class to behave as a Python extension -- simply by subclassing. */ -template -class ExtensionPythonT : public ExtensionT //NOLINT +template +class ExtensionPythonT: public ExtensionT // NOLINT { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::ExtensionPythonT); public: using Inherited = ExtensionT; - ExtensionPythonT() { + ExtensionPythonT() + { ExtensionT::m_isPythonExtension = true; ExtensionT::initExtensionType(ExtensionPythonT::getExtensionClassTypeId()); } @@ -50,73 +52,72 @@ class ExtensionPythonT : public ExtensionT //NOLINT ExtensionPythonT(const ExtensionPythonT&) = delete; ExtensionPythonT(ExtensionPythonT&&) = delete; - ExtensionPythonT& operator= (const ExtensionPythonT&) = delete; - ExtensionPythonT& operator= (ExtensionPythonT&&) = delete; + ExtensionPythonT& operator=(const ExtensionPythonT&) = delete; + ExtensionPythonT& operator=(ExtensionPythonT&&) = delete; }; using ExtensionPython = ExtensionPythonT; // Helper macros to define python extensions -#define EXTENSION_PROXY_FIRST(function) \ - Base::PyGILStateLocker lock;\ - Py::Object result;\ - try {\ - Property* proxy = this->getExtendedContainer()->getPropertyByName("Proxy");\ - if (proxy && proxy->is()) {\ - Py::Object feature = static_cast(proxy)->getValue();\ - if (feature.hasAttr(std::string("function"))) {\ - if (feature.hasAttr("__object__")) {\ +#define EXTENSION_PROXY_FIRST(function) \ + Base::PyGILStateLocker lock; \ + Py::Object result; \ + try { \ + Property* proxy = this->getExtendedContainer()->getPropertyByName("Proxy"); \ + if (proxy && proxy->is()) { \ + Py::Object feature = static_cast(proxy)->getValue(); \ + if (feature.hasAttr(std::string("function"))) { \ + if (feature.hasAttr("__object__")) { \ Py::Callable method(feature.getAttr(std::string("function"))); - - -#define EXTENSION_PROXY_SECOND(function)\ - result = method.apply(args);\ - }\ - else {\ - Py::Callable method(feature.getAttr(std::string("function"))); - -#define EXTENSION_PROXY_THIRD()\ - result = method.apply(args);\ - }\ - }\ - }\ - }\ - catch (Py::Exception&) {\ - Base::PyException e;\ - e.ReportException();\ +#define EXTENSION_PROXY_SECOND(function) \ + result = method.apply(args); \ + } \ + else \ + { \ + Py::Callable method(feature.getAttr(std::string("function"))); + +#define EXTENSION_PROXY_THIRD() \ + result = method.apply(args); \ + } \ + } \ + } \ + } \ + catch (Py::Exception&) \ + { \ + Base::PyException e; \ + e.ReportException(); \ } -#define EXTENSION_PROXY_NOARG(function)\ - EXTENSION_PROXY_FIRST(function) \ - Py::Tuple args;\ - EXTENSION_PROXY_SECOND(function) \ - Py::Tuple args(1);\ - args.setItem(0, Py::Object(this->getExtensionPyObject(), true));\ +#define EXTENSION_PROXY_NOARG(function) \ + EXTENSION_PROXY_FIRST(function) \ + Py::Tuple args; \ + EXTENSION_PROXY_SECOND(function) \ + Py::Tuple args(1); \ + args.setItem(0, Py::Object(this->getExtensionPyObject(), true)); \ EXTENSION_PROXY_THIRD() -#define EXTENSION_PROXY_ONEARG(function, arg)\ - EXTENSION_PROXY_FIRST(function) \ - Py::Tuple args;\ - args.setItem(0, arg); \ - EXTENSION_PROXY_SECOND(function) \ - Py::Tuple args(2);\ - args.setItem(0, Py::Object(this->getExtensionPyObject(), true));\ - args.setItem(1, arg); \ +#define EXTENSION_PROXY_ONEARG(function, arg) \ + EXTENSION_PROXY_FIRST(function) \ + Py::Tuple args; \ + args.setItem(0, arg); \ + EXTENSION_PROXY_SECOND(function) \ + Py::Tuple args(2); \ + args.setItem(0, Py::Object(this->getExtensionPyObject(), true)); \ + args.setItem(1, arg); \ EXTENSION_PROXY_THIRD() -#define EXTENSION_PYTHON_OVERRIDE_VOID_NOARGS(function)\ - virtual void function() override {\ - EXTENSION_PROXY_NOARGS(function)\ - }; +#define EXTENSION_PYTHON_OVERRIDE_VOID_NOARGS(function) \ + virtual void function() override { EXTENSION_PROXY_NOARGS(function) }; -#define EXTENSION_PYTHON_OVERRIDE_OBJECT_NOARGS(function)\ - virtual PyObject* function() override {\ - EXTENSION_PROXY_NOARGS(function)\ - return res.ptr();\ +#define EXTENSION_PYTHON_OVERRIDE_OBJECT_NOARGS(function) \ + virtual PyObject* function() override \ + { \ + EXTENSION_PROXY_NOARGS(function) \ + return res.ptr(); \ }; -} //App +} // namespace App -#endif // APP_EXTENSIONPYTHON_H +#endif // APP_EXTENSIONPYTHON_H diff --git a/src/App/FeatureCustom.h b/src/App/FeatureCustom.h index 3b1873d3fe10..7dd377b18ec1 100644 --- a/src/App/FeatureCustom.h +++ b/src/App/FeatureCustom.h @@ -21,7 +21,6 @@ ***************************************************************************/ - #ifndef APP_FEATURECUSTOM_H #define APP_FEATURECUSTOM_H @@ -41,8 +40,8 @@ class Property; * it has no support for in Python written feature classes. * @author Werner Mayer */ -template -class FeatureCustomT : public FeatureT //NOLINT +template +class FeatureCustomT: public FeatureT // NOLINT { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureCustomT); @@ -53,46 +52,55 @@ class FeatureCustomT : public FeatureT //NOLINT /** @name methods override DocumentObject */ //@{ - short mustExecute() const override { + short mustExecute() const override + { return FeatureT::mustExecute(); } /// recalculate the Feature - DocumentObjectExecReturn *execute() override { + DocumentObjectExecReturn* execute() override + { return FeatureT::execute(); } /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return FeatureT::getViewProviderName(); } - PyObject *getPyObject() override { + PyObject* getPyObject() override + { return FeatureT::getPyObject(); } - void setPyObject(PyObject *obj) override { + void setPyObject(PyObject* obj) override + { FeatureT::setPyObject(obj); } protected: - void onBeforeChange(const Property* prop) override { + void onBeforeChange(const Property* prop) override + { FeatureT::onBeforeChange(prop); } - void onChanged(const Property* prop) override { + void onChanged(const Property* prop) override + { FeatureT::onChanged(prop); } - void onDocumentRestored() override { + void onDocumentRestored() override + { FeatureT::onDocumentRestored(); } - void onSettingDocument() override { + void onSettingDocument() override + { FeatureT::onSettingDocument(); } public: FeatureCustomT(const FeatureCustomT&) = delete; FeatureCustomT(FeatureCustomT&&) = delete; - FeatureCustomT& operator= (const FeatureCustomT&) = delete; - FeatureCustomT& operator= (FeatureCustomT&&) = delete; + FeatureCustomT& operator=(const FeatureCustomT&) = delete; + FeatureCustomT& operator=(FeatureCustomT&&) = delete; }; -} //namespace App +} // namespace App -#endif // APP_FEATURECUSTOM_H +#endif // APP_FEATURECUSTOM_H diff --git a/src/App/FeaturePython.cpp b/src/App/FeaturePython.cpp index fa9c7018e957..fdb764082180 100644 --- a/src/App/FeaturePython.cpp +++ b/src/App/FeaturePython.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -39,8 +39,7 @@ using namespace App; FeaturePythonImp::FeaturePythonImp(App::DocumentObject* o) : object(o) -{ -} +{} FeaturePythonImp::~FeaturePythonImp() { @@ -56,7 +55,8 @@ FeaturePythonImp::~FeaturePythonImp() } } -void FeaturePythonImp::init(PyObject *pyobj) { +void FeaturePythonImp::init(PyObject* pyobj) +{ Base::PyGILStateLocker lock; has__object__ = !!PyObject_HasAttrString(pyobj, "__object__"); @@ -66,11 +66,11 @@ void FeaturePythonImp::init(PyObject *pyobj) { FC_PY_FEATURE_PYTHON } -#define FC_PY_CALL_CHECK(_name) _FC_PY_CALL_CHECK(_name,return(false)) +#define FC_PY_CALL_CHECK(_name) _FC_PY_CALL_CHECK(_name, return (false)) /*! - Calls the execute() method of the Python feature class. If the Python feature class doesn't have an execute() - method or if it returns False this method also return false and true otherwise. + Calls the execute() method of the Python feature class. If the Python feature class doesn't have an + execute() method or if it returns False this method also return false and true otherwise. */ bool FeaturePythonImp::execute() { @@ -79,16 +79,18 @@ bool FeaturePythonImp::execute() try { if (has__object__) { Py::Object res = Base::pyCall(py_execute.ptr()); - if (res.isBoolean() && !res.isTrue()) + if (res.isBoolean() && !res.isTrue()) { return false; + } return true; } else { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Object res = Base::pyCall(py_execute.ptr(),args.ptr()); - if (res.isBoolean() && !res.isTrue()) + Py::Object res = Base::pyCall(py_execute.ptr(), args.ptr()); + if (res.isBoolean() && !res.isTrue()) { return false; + } return true; } } @@ -97,7 +99,7 @@ bool FeaturePythonImp::execute() PyErr_Clear(); return false; } - Base::PyException::ThrowException(); // extract the Python error text + Base::PyException::ThrowException(); // extract the Python error text } return false; @@ -115,12 +117,12 @@ bool FeaturePythonImp::mustExecute() const else { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Object res(Base::pyCall(py_mustExecute.ptr(),args.ptr())); + Py::Object res(Base::pyCall(py_mustExecute.ptr(), args.ptr())); return res.isTrue(); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } return false; @@ -129,54 +131,58 @@ bool FeaturePythonImp::mustExecute() const void FeaturePythonImp::onBeforeChange(const Property* prop) { - if (py_onBeforeChange.isNone()) + if (py_onBeforeChange.isNone()) { return; + } // Run the execute method of the proxy object. Base::PyGILStateLocker lock; try { - const char *prop_name = object->getPropertyName(prop); - if (!prop_name) + const char* prop_name = object->getPropertyName(prop); + if (!prop_name) { return; + } if (has__object__) { Py::Tuple args(1); args.setItem(0, Py::String(prop_name)); - Base::pyCall(py_onBeforeChange.ptr(),args.ptr()); + Base::pyCall(py_onBeforeChange.ptr(), args.ptr()); } else { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); args.setItem(1, Py::String(prop_name)); - Base::pyCall(py_onBeforeChange.ptr(),args.ptr()); + Base::pyCall(py_onBeforeChange.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -bool FeaturePythonImp::onBeforeChangeLabel(std::string &newLabel) +bool FeaturePythonImp::onBeforeChangeLabel(std::string& newLabel) { - if(py_onBeforeChangeLabel.isNone()) + if (py_onBeforeChangeLabel.isNone()) { return false; + } // Run the execute method of the proxy object. Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1,Py::String(newLabel)); - Py::Object ret(Base::pyCall(py_onBeforeChangeLabel.ptr(),args.ptr())); - if(!ret.isNone()) { - if(!ret.isString()) + args.setItem(1, Py::String(newLabel)); + Py::Object ret(Base::pyCall(py_onBeforeChangeLabel.ptr(), args.ptr())); + if (!ret.isNone()) { + if (!ret.isString()) { throw Py::TypeError("onBeforeChangeLabel expects to return a string"); + } newLabel = ret.as_string(); return true; } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } return false; @@ -184,35 +190,37 @@ bool FeaturePythonImp::onBeforeChangeLabel(std::string &newLabel) void FeaturePythonImp::onChanged(const Property* prop) { - if (py_onChanged.isNone()) + if (py_onChanged.isNone()) { return; + } // Run the execute method of the proxy object. Base::PyGILStateLocker lock; try { - const char *prop_name = object->getPropertyName(prop); - if (!prop_name) + const char* prop_name = object->getPropertyName(prop); + if (!prop_name) { return; + } if (has__object__) { Py::Tuple args(1); args.setItem(0, Py::String(prop_name)); - Base::pyCall(py_onChanged.ptr(),args.ptr()); + Base::pyCall(py_onChanged.ptr(), args.ptr()); } else { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); args.setItem(1, Py::String(prop_name)); - Base::pyCall(py_onChanged.ptr(),args.ptr()); + Base::pyCall(py_onChanged.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } void FeaturePythonImp::onDocumentRestored() { - _FC_PY_CALL_CHECK(onDocumentRestored,return); + _FC_PY_CALL_CHECK(onDocumentRestored, return); // Run the execute method of the proxy object. Base::PyGILStateLocker lock; @@ -223,11 +231,11 @@ void FeaturePythonImp::onDocumentRestored() else { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Base::pyCall(py_onDocumentRestored.ptr(),args.ptr()); + Base::pyCall(py_onDocumentRestored.ptr(), args.ptr()); } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -249,57 +257,71 @@ void FeaturePythonImp::unsetupObject() } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } -bool FeaturePythonImp::getSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *_mat, bool transform, int depth) const +bool FeaturePythonImp::getSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* _mat, + bool transform, + int depth) const { FC_PY_CALL_CHECK(getSubObject); Base::PyGILStateLocker lock; try { Py::Tuple args(6); args.setItem(0, Py::Object(object->getPyObject(), true)); - if(!subname) subname = ""; - args.setItem(1,Py::String(subname)); - args.setItem(2,Py::Int(pyObj?2:1)); - Base::MatrixPy *pyMat = new Base::MatrixPy(new Base::Matrix4D); - if(_mat) *pyMat->getMatrixPtr() = *_mat; - args.setItem(3,Py::asObject(pyMat)); - args.setItem(4,Py::Boolean(transform)); - args.setItem(5,Py::Int(depth)); - - Py::Object res(Base::pyCall(py_getSubObject.ptr(),args.ptr())); - if(res.isNone()) { + if (!subname) { + subname = ""; + } + args.setItem(1, Py::String(subname)); + args.setItem(2, Py::Int(pyObj ? 2 : 1)); + Base::MatrixPy* pyMat = new Base::MatrixPy(new Base::Matrix4D); + if (_mat) { + *pyMat->getMatrixPtr() = *_mat; + } + args.setItem(3, Py::asObject(pyMat)); + args.setItem(4, Py::Boolean(transform)); + args.setItem(5, Py::Int(depth)); + + Py::Object res(Base::pyCall(py_getSubObject.ptr(), args.ptr())); + if (res.isNone()) { ret = nullptr; return true; } - if(!res.isTrue()) + if (!res.isTrue()) { return false; - if(!res.isSequence()) + } + if (!res.isSequence()) { throw Py::TypeError("getSubObject expects return type of tuple"); + } Py::Sequence seq(res); - if(seq.length() < 2 || - (!seq.getItem(0).isNone() && - !PyObject_TypeCheck(seq.getItem(0).ptr(),&DocumentObjectPy::Type)) || - !PyObject_TypeCheck(seq.getItem(1).ptr(),&Base::MatrixPy::Type)) - { + if (seq.length() < 2 + || (!seq.getItem(0).isNone() + && !PyObject_TypeCheck(seq.getItem(0).ptr(), &DocumentObjectPy::Type)) + || !PyObject_TypeCheck(seq.getItem(1).ptr(), &Base::MatrixPy::Type)) { throw Py::TypeError("getSubObject expects return type of (obj,matrix,pyobj)"); } - if(_mat) + if (_mat) { *_mat = *static_cast(seq.getItem(1).ptr())->getMatrixPtr(); - if(pyObj) { - if(seq.length()>2) + } + if (pyObj) { + if (seq.length() > 2) { *pyObj = Py::new_reference_to(seq.getItem(2)); - else + } + else { *pyObj = Py::new_reference_to(Py::None()); + } } - if(seq.getItem(0).isNone()) + if (seq.getItem(0).isNone()) { ret = nullptr; - else + } + else { ret = static_cast(seq.getItem(0).ptr())->getDocumentObjectPtr(); + } return true; } catch (Py::Exception&) { @@ -307,30 +329,34 @@ bool FeaturePythonImp::getSubObject(DocumentObject *&ret, const char *subname, PyErr_Clear(); return false; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); ret = nullptr; return true; } } -bool FeaturePythonImp::getSubObjects(std::vector &ret, int reason) const { +bool FeaturePythonImp::getSubObjects(std::vector& ret, int reason) const +{ FC_PY_CALL_CHECK(getSubObjects); Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); args.setItem(1, Py::Int(reason)); - Py::Object res(Base::pyCall(py_getSubObjects.ptr(),args.ptr())); - if(!res.isTrue()) + Py::Object res(Base::pyCall(py_getSubObjects.ptr(), args.ptr())); + if (!res.isTrue()) { return true; - if(!res.isSequence()) + } + if (!res.isSequence()) { throw Py::TypeError("getSubObjects expects return type of tuple"); + } Py::Sequence seq(res); - for(Py_ssize_t i=0;i &ret, int reason) PyErr_Clear(); return false; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return true; } } -bool FeaturePythonImp::getLinkedObject(DocumentObject *&ret, bool recurse, - Base::Matrix4D *_mat, bool transform, int depth) const +bool FeaturePythonImp::getLinkedObject(DocumentObject*& ret, + bool recurse, + Base::Matrix4D* _mat, + bool transform, + int depth) const { FC_PY_CALL_CHECK(getLinkedObject); Base::PyGILStateLocker lock; try { Py::Tuple args(5); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1,Py::Boolean(recurse)); - Base::MatrixPy *pyMat = new Base::MatrixPy(new Base::Matrix4D); - if(_mat) *pyMat->getMatrixPtr() = *_mat; - args.setItem(2,Py::asObject(pyMat)); - args.setItem(3,Py::Boolean(transform)); - args.setItem(4,Py::Int(depth)); - - Py::Object res(Base::pyCall(py_getLinkedObject.ptr(),args.ptr())); - if(!res.isTrue()) { + args.setItem(1, Py::Boolean(recurse)); + Base::MatrixPy* pyMat = new Base::MatrixPy(new Base::Matrix4D); + if (_mat) { + *pyMat->getMatrixPtr() = *_mat; + } + args.setItem(2, Py::asObject(pyMat)); + args.setItem(3, Py::Boolean(transform)); + args.setItem(4, Py::Int(depth)); + + Py::Object res(Base::pyCall(py_getLinkedObject.ptr(), args.ptr())); + if (!res.isTrue()) { ret = object; return true; } - if(!res.isSequence()) + if (!res.isSequence()) { throw Py::TypeError("getLinkedObject expects return type of (object,matrix)"); + } Py::Sequence seq(res); - if(seq.length() != 2 || - (!seq.getItem(0).isNone() && - !PyObject_TypeCheck(seq.getItem(0).ptr(),&DocumentObjectPy::Type)) || - !PyObject_TypeCheck(seq.getItem(1).ptr(),&Base::MatrixPy::Type)) - { + if (seq.length() != 2 + || (!seq.getItem(0).isNone() + && !PyObject_TypeCheck(seq.getItem(0).ptr(), &DocumentObjectPy::Type)) + || !PyObject_TypeCheck(seq.getItem(1).ptr(), &Base::MatrixPy::Type)) { throw Py::TypeError("getLinkedObject expects return type of (object,matrix)"); } - if(_mat) + if (_mat) { *_mat = *static_cast(seq.getItem(1).ptr())->getMatrixPtr(); - if(seq.getItem(0).isNone()) + } + if (seq.getItem(0).isNone()) { ret = object; - else + } + else { ret = static_cast(seq.getItem(0).ptr())->getDocumentObjectPtr(); + } return true; } catch (Py::Exception&) { @@ -389,28 +423,27 @@ bool FeaturePythonImp::getLinkedObject(DocumentObject *&ret, bool recurse, PyErr_Clear(); return false; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); ret = nullptr; return true; } } -PyObject *FeaturePythonImp::getPyObject() +PyObject* FeaturePythonImp::getPyObject() { // ref counter is set to 1 return new FeaturePythonPyT(object); } -FeaturePythonImp::ValueT -FeaturePythonImp::hasChildElement() const +FeaturePythonImp::ValueT FeaturePythonImp::hasChildElement() const { - _FC_PY_CALL_CHECK(hasChildElement,return(NotImplemented)); + _FC_PY_CALL_CHECK(hasChildElement, return (NotImplemented)); Base::PyGILStateLocker lock; try { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Boolean ok(Base::pyCall(py_hasChildElement.ptr(),args.ptr())); + Py::Boolean ok(Base::pyCall(py_hasChildElement.ptr(), args.ptr())); return static_cast(ok) ? Accepted : Rejected; } catch (Py::Exception&) { @@ -419,48 +452,50 @@ FeaturePythonImp::hasChildElement() const return NotImplemented; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return Rejected; } } -int FeaturePythonImp::isElementVisible(const char *element) const { - _FC_PY_CALL_CHECK(isElementVisible,return(-2)); +int FeaturePythonImp::isElementVisible(const char* element) const +{ + _FC_PY_CALL_CHECK(isElementVisible, return (-2)); Base::PyGILStateLocker lock; try { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1,Py::String(element?element:"")); - return Py::Int(Base::pyCall(py_isElementVisible.ptr(),args.ptr())); + args.setItem(1, Py::String(element ? element : "")); + return Py::Int(Base::pyCall(py_isElementVisible.ptr(), args.ptr())); } catch (Py::Exception&) { if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { PyErr_Clear(); return -2; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return -1; } } -int FeaturePythonImp::setElementVisible(const char *element, bool visible) { - _FC_PY_CALL_CHECK(setElementVisible,return(-2)); +int FeaturePythonImp::setElementVisible(const char* element, bool visible) +{ + _FC_PY_CALL_CHECK(setElementVisible, return (-2)); Base::PyGILStateLocker lock; try { Py::Tuple args(3); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1,Py::String(element?element:"")); - args.setItem(2,Py::Boolean(visible)); - return Py::Int(Base::pyCall(py_setElementVisible.ptr(),args.ptr())); + args.setItem(1, Py::String(element ? element : "")); + args.setItem(2, Py::Boolean(visible)); + return Py::Int(Base::pyCall(py_setElementVisible.ptr(), args.ptr())); } catch (Py::Exception&) { if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { PyErr_Clear(); return -2; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return -1; } @@ -468,30 +503,29 @@ int FeaturePythonImp::setElementVisible(const char *element, bool visible) { std::string FeaturePythonImp::getViewProviderName() { - _FC_PY_CALL_CHECK(getViewProviderName,return(std::string())); + _FC_PY_CALL_CHECK(getViewProviderName, return (std::string())); Base::PyGILStateLocker lock; try { Py::TupleN args(Py::Object(object->getPyObject(), true)); - Py::String ret(Base::pyCall(py_getViewProviderName.ptr(),args.ptr())); + Py::String ret(Base::pyCall(py_getViewProviderName.ptr(), args.ptr())); return ret.as_string(); } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } return {}; } -FeaturePythonImp::ValueT -FeaturePythonImp::canLinkProperties() const +FeaturePythonImp::ValueT FeaturePythonImp::canLinkProperties() const { - _FC_PY_CALL_CHECK(canLinkProperties,return(NotImplemented)); + _FC_PY_CALL_CHECK(canLinkProperties, return (NotImplemented)); Base::PyGILStateLocker lock; try { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Boolean ok(Base::pyCall(py_canLinkProperties.ptr(),args.ptr())); + Py::Boolean ok(Base::pyCall(py_canLinkProperties.ptr(), args.ptr())); return ok ? Accepted : Rejected; } catch (Py::Exception&) { @@ -499,21 +533,20 @@ FeaturePythonImp::canLinkProperties() const PyErr_Clear(); return NotImplemented; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return Rejected; } } -FeaturePythonImp::ValueT -FeaturePythonImp::allowDuplicateLabel() const +FeaturePythonImp::ValueT FeaturePythonImp::allowDuplicateLabel() const { - _FC_PY_CALL_CHECK(allowDuplicateLabel,return(NotImplemented)); + _FC_PY_CALL_CHECK(allowDuplicateLabel, return (NotImplemented)); Base::PyGILStateLocker lock; try { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Boolean ok(Base::pyCall(py_allowDuplicateLabel.ptr(),args.ptr())); + Py::Boolean ok(Base::pyCall(py_allowDuplicateLabel.ptr(), args.ptr())); return ok ? Accepted : Rejected; } catch (Py::Exception&) { @@ -522,19 +555,20 @@ FeaturePythonImp::allowDuplicateLabel() const return NotImplemented; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return Rejected; } } -int FeaturePythonImp::canLoadPartial() const { - _FC_PY_CALL_CHECK(canLoadPartial,return(-1)); +int FeaturePythonImp::canLoadPartial() const +{ + _FC_PY_CALL_CHECK(canLoadPartial, return (-1)); Base::PyGILStateLocker lock; try { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Int ret(Base::pyCall(py_canLoadPartial.ptr(),args.ptr())); + Py::Int ret(Base::pyCall(py_canLoadPartial.ptr(), args.ptr())); return ret; } catch (Py::Exception&) { @@ -542,28 +576,28 @@ int FeaturePythonImp::canLoadPartial() const { PyErr_Clear(); return -1; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return 0; } } -FeaturePythonImp::ValueT -FeaturePythonImp::redirectSubName(std::ostringstream &ss, - App::DocumentObject *topParent, - App::DocumentObject *child) const +FeaturePythonImp::ValueT FeaturePythonImp::redirectSubName(std::ostringstream& ss, + App::DocumentObject* topParent, + App::DocumentObject* child) const { - _FC_PY_CALL_CHECK(redirectSubName,return(NotImplemented)); + _FC_PY_CALL_CHECK(redirectSubName, return (NotImplemented)); Base::PyGILStateLocker lock; try { Py::Tuple args(4); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1,Py::String(ss.str())); - args.setItem(2,topParent?Py::Object(topParent->getPyObject(),true):Py::Object()); - args.setItem(3,child?Py::Object(child->getPyObject(),true):Py::Object()); - Py::Object ret(Base::pyCall(py_redirectSubName.ptr(),args.ptr())); - if (ret.isNone()) + args.setItem(1, Py::String(ss.str())); + args.setItem(2, topParent ? Py::Object(topParent->getPyObject(), true) : Py::Object()); + args.setItem(3, child ? Py::Object(child->getPyObject(), true) : Py::Object()); + Py::Object ret(Base::pyCall(py_redirectSubName.ptr(), args.ptr())); + if (ret.isNone()) { return Rejected; + } ss.str(""); ss << ret.as_string(); return Accepted; @@ -574,20 +608,20 @@ FeaturePythonImp::redirectSubName(std::ostringstream &ss, return NotImplemented; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); return Rejected; } } -bool FeaturePythonImp::editProperty(const char *name) +bool FeaturePythonImp::editProperty(const char* name) { - _FC_PY_CALL_CHECK(editProperty,return false); + _FC_PY_CALL_CHECK(editProperty, return false); Base::PyGILStateLocker lock; try { Py::Tuple args(1); args.setItem(0, Py::String(name)); - Py::Object ret(Base::pyCall(py_editProperty.ptr(),args.ptr())); + Py::Object ret(Base::pyCall(py_editProperty.ptr(), args.ptr())); return ret.isTrue(); } catch (Py::Exception&) { @@ -596,7 +630,7 @@ bool FeaturePythonImp::editProperty(const char *name) return false; } - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } return false; @@ -604,29 +638,37 @@ bool FeaturePythonImp::editProperty(const char *name) // --------------------------------------------------------- -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::FeaturePython, App::DocumentObject) -template<> const char* App::FeaturePython::getViewProviderName() const { +template<> +const char* App::FeaturePython::getViewProviderName() const +{ return "Gui::ViewProviderFeaturePython"; } -template<> PyObject* App::FeaturePython::getPyObject() { +template<> +PyObject* App::FeaturePython::getPyObject() +{ if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FeaturePythonPyT(this),true); + PythonObject = Py::Object(new FeaturePythonPyT(this), true); } return Py::new_reference_to(PythonObject); } // explicit template instantiation template class AppExport FeaturePythonT; -} +} // namespace App // --------------------------------------------------------- -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::GeometryPython, App::GeoFeature) -template<> const char* App::GeometryPython::getViewProviderName() const { +template<> +const char* App::GeometryPython::getViewProviderName() const +{ return "Gui::ViewProviderGeometryPython"; } // explicit template instantiation template class AppExport FeaturePythonT; -} +} // namespace App diff --git a/src/App/FeaturePython.h b/src/App/FeaturePython.h index d57747bfbbac..c9208e3b954c 100644 --- a/src/App/FeaturePython.h +++ b/src/App/FeaturePython.h @@ -21,7 +21,6 @@ ***************************************************************************/ - #ifndef APP_FEATUREPYTHON_H #define APP_FEATUREPYTHON_H @@ -38,10 +37,11 @@ class Property; class AppExport FeaturePythonImp { public: - enum ValueT { - NotImplemented = 0, // not handled - Accepted = 1, // handled and accepted - Rejected = 2 // handled and rejected + enum ValueT + { + NotImplemented = 0, // not handled + Accepted = 1, // handled and accepted + Rejected = 2 // handled and rejected }; explicit FeaturePythonImp(App::DocumentObject*); @@ -50,93 +50,95 @@ class AppExport FeaturePythonImp bool execute(); bool mustExecute() const; void onBeforeChange(const Property* prop); - bool onBeforeChangeLabel(std::string &newLabel); + bool onBeforeChangeLabel(std::string& newLabel); void onChanged(const Property* prop); void onDocumentRestored(); void unsetupObject(); std::string getViewProviderName(); - PyObject *getPyObject(); + PyObject* getPyObject(); - bool getSubObject(App::DocumentObject *&ret, const char *subname, PyObject **pyObj, - Base::Matrix4D *mat, bool transform, int depth) const; + bool getSubObject(App::DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const; - bool getSubObjects(std::vector &ret, int reason) const; + bool getSubObjects(std::vector& ret, int reason) const; - bool getLinkedObject(App::DocumentObject *&ret, bool recurse, - Base::Matrix4D *mat, bool transform, int depth) const; + bool getLinkedObject(App::DocumentObject*& ret, + bool recurse, + Base::Matrix4D* mat, + bool transform, + int depth) const; ValueT canLinkProperties() const; ValueT allowDuplicateLabel() const; - ValueT redirectSubName(std::ostringstream &ss, - App::DocumentObject *topParent, - App::DocumentObject *child) const; + ValueT redirectSubName(std::ostringstream& ss, + App::DocumentObject* topParent, + App::DocumentObject* child) const; int canLoadPartial() const; /// return true to activate tree view group object handling ValueT hasChildElement() const; /// Get sub-element visibility - int isElementVisible(const char *) const; + int isElementVisible(const char*) const; /// Set sub-element visibility - int setElementVisible(const char *, bool); + int setElementVisible(const char*, bool); - bool editProperty(const char *propName); + bool editProperty(const char* propName); private: App::DocumentObject* object; - bool has__object__{false}; - -#define FC_PY_FEATURE_PYTHON \ - FC_PY_ELEMENT(execute)\ - FC_PY_ELEMENT(mustExecute)\ - FC_PY_ELEMENT(onBeforeChange)\ - FC_PY_ELEMENT(onBeforeChangeLabel)\ - FC_PY_ELEMENT(onChanged)\ - FC_PY_ELEMENT(onDocumentRestored)\ - FC_PY_ELEMENT(unsetupObject)\ - FC_PY_ELEMENT(getViewProviderName)\ - FC_PY_ELEMENT(getSubObject)\ - FC_PY_ELEMENT(getSubObjects)\ - FC_PY_ELEMENT(getLinkedObject)\ - FC_PY_ELEMENT(canLinkProperties)\ - FC_PY_ELEMENT(allowDuplicateLabel)\ - FC_PY_ELEMENT(redirectSubName)\ - FC_PY_ELEMENT(canLoadPartial)\ - FC_PY_ELEMENT(hasChildElement)\ - FC_PY_ELEMENT(isElementVisible)\ - FC_PY_ELEMENT(setElementVisible)\ - FC_PY_ELEMENT(editProperty)\ - -#define FC_PY_ELEMENT_DEFINE(_name) \ - Py::Object py_##_name; - -#define FC_PY_ELEMENT_INIT(_name) \ - FC_PY_GetCallable(pyobj,#_name,py_##_name);\ - if(!py_##_name.isNone()) {\ - PyObject *pyRecursive = PyObject_GetAttrString(pyobj, \ - "__allow_recursive_" #_name);\ - if(!pyRecursive) {\ - PyErr_Clear();\ - _Flags.set(FlagAllowRecursive_##_name, false);\ - }else{\ - _Flags.set(FlagAllowRecursive_##_name, PyObject_IsTrue(pyRecursive));\ - Py_DECREF(pyRecursive);\ - }\ + bool has__object__ {false}; + +#define FC_PY_FEATURE_PYTHON \ + FC_PY_ELEMENT(execute) \ + FC_PY_ELEMENT(mustExecute) \ + FC_PY_ELEMENT(onBeforeChange) \ + FC_PY_ELEMENT(onBeforeChangeLabel) \ + FC_PY_ELEMENT(onChanged) \ + FC_PY_ELEMENT(onDocumentRestored) \ + FC_PY_ELEMENT(unsetupObject) \ + FC_PY_ELEMENT(getViewProviderName) \ + FC_PY_ELEMENT(getSubObject) \ + FC_PY_ELEMENT(getSubObjects) \ + FC_PY_ELEMENT(getLinkedObject) \ + FC_PY_ELEMENT(canLinkProperties) \ + FC_PY_ELEMENT(allowDuplicateLabel) \ + FC_PY_ELEMENT(redirectSubName) \ + FC_PY_ELEMENT(canLoadPartial) \ + FC_PY_ELEMENT(hasChildElement) \ + FC_PY_ELEMENT(isElementVisible) \ + FC_PY_ELEMENT(setElementVisible) \ + FC_PY_ELEMENT(editProperty) + +#define FC_PY_ELEMENT_DEFINE(_name) Py::Object py_##_name; + +#define FC_PY_ELEMENT_INIT(_name) \ + FC_PY_GetCallable(pyobj, #_name, py_##_name); \ + if (!py_##_name.isNone()) { \ + PyObject* pyRecursive = PyObject_GetAttrString(pyobj, "__allow_recursive_" #_name); \ + if (!pyRecursive) { \ + PyErr_Clear(); \ + _Flags.set(FlagAllowRecursive_##_name, false); \ + } \ + else { \ + _Flags.set(FlagAllowRecursive_##_name, PyObject_IsTrue(pyRecursive)); \ + Py_DECREF(pyRecursive); \ + } \ } -#define FC_PY_ELEMENT_FLAG(_name) \ - FlagCalling_##_name,\ - FlagAllowRecursive_##_name, - -#define _FC_PY_CALL_CHECK(_name,_ret) \ - if((!_Flags.test(FlagAllowRecursive_##_name) \ - && _Flags.test(FlagCalling_##_name)) \ - || py_##_name.isNone()) \ - {\ - _ret;\ - }\ +#define FC_PY_ELEMENT_FLAG(_name) FlagCalling_##_name, FlagAllowRecursive_##_name, + +#define _FC_PY_CALL_CHECK(_name, _ret) \ + if ((!_Flags.test(FlagAllowRecursive_##_name) && _Flags.test(FlagCalling_##_name)) \ + || py_##_name.isNone()) { \ + _ret; \ + } \ Base::BitsetLocker guard(_Flags, FlagCalling_##_name); #undef FC_PY_ELEMENT @@ -147,16 +149,16 @@ class AppExport FeaturePythonImp #undef FC_PY_ELEMENT #define FC_PY_ELEMENT(_name) FC_PY_ELEMENT_FLAG(_name) - enum Flag { - FC_PY_FEATURE_PYTHON - FlagMax, + enum Flag + { + FC_PY_FEATURE_PYTHON FlagMax, }; using Flags = std::bitset; mutable Flags _Flags; public: - void init(PyObject *pyobj); + void init(PyObject* pyobj); }; /** @@ -164,185 +166,226 @@ class AppExport FeaturePythonImp * derived class as Python feature -- simply by subclassing. * @author Werner Mayer */ -template -class FeaturePythonT : public FeatureT +template +class FeaturePythonT: public FeatureT { PROPERTY_HEADER_WITH_OVERRIDE(App::FeaturePythonT); public: - FeaturePythonT() { - ADD_PROPERTY(Proxy,(Py::Object())); + FeaturePythonT() + { + ADD_PROPERTY(Proxy, (Py::Object())); // cannot move this to the initializer list to avoid warning imp = new FeaturePythonImp(this); } - ~FeaturePythonT() override { + ~FeaturePythonT() override + { delete imp; } /** @name methods override DocumentObject */ //@{ - short mustExecute() const override { - if (this->isTouched()) + short mustExecute() const override + { + if (this->isTouched()) { return 1; + } auto ret = FeatureT::mustExecute(); - if(ret) return ret; - return imp->mustExecute()?1:0; + if (ret) { + return ret; + } + return imp->mustExecute() ? 1 : 0; } /// recalculate the Feature - DocumentObjectExecReturn *execute() override { + DocumentObjectExecReturn* execute() override + { try { bool handled = imp->execute(); - if (!handled) + if (!handled) { return FeatureT::execute(); + } } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } return DocumentObject::StdReturn; } - const char* getViewProviderNameOverride() const override { + const char* getViewProviderNameOverride() const override + { viewProviderName = imp->getViewProviderName(); - if(!viewProviderName.empty()) + if (!viewProviderName.empty()) { return viewProviderName.c_str(); + } return FeatureT::getViewProviderNameOverride(); } /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return FeatureT::getViewProviderName(); } - App::DocumentObject *getSubObject(const char *subname, PyObject **pyObj, - Base::Matrix4D *mat, bool transform, int depth) const override + App::DocumentObject* getSubObject(const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const override { - App::DocumentObject *ret = nullptr; - if(imp->getSubObject(ret,subname,pyObj,mat,transform,depth)) + App::DocumentObject* ret = nullptr; + if (imp->getSubObject(ret, subname, pyObj, mat, transform, depth)) { return ret; - return FeatureT::getSubObject(subname,pyObj,mat,transform,depth); + } + return FeatureT::getSubObject(subname, pyObj, mat, transform, depth); } - std::vector getSubObjects(int reason=0) const override { + std::vector getSubObjects(int reason = 0) const override + { std::vector ret; - if(imp->getSubObjects(ret,reason)) + if (imp->getSubObjects(ret, reason)) { return ret; + } return FeatureT::getSubObjects(reason); } - App::DocumentObject *getLinkedObject(bool recurse, - Base::Matrix4D *mat, bool transform, int depth) const override + App::DocumentObject* + getLinkedObject(bool recurse, Base::Matrix4D* mat, bool transform, int depth) const override { - App::DocumentObject *ret = nullptr; - if(imp->getLinkedObject(ret,recurse,mat,transform,depth)) + App::DocumentObject* ret = nullptr; + if (imp->getLinkedObject(ret, recurse, mat, transform, depth)) { return ret; - return FeatureT::getLinkedObject(recurse,mat,transform,depth); + } + return FeatureT::getLinkedObject(recurse, mat, transform, depth); } /// return true to activate tree view group object handling - bool hasChildElement() const override { + bool hasChildElement() const override + { switch (imp->hasChildElement()) { - case FeaturePythonImp::Accepted: - return true; - case FeaturePythonImp::Rejected: - return false; - default: - return FeatureT::hasChildElement(); + case FeaturePythonImp::Accepted: + return true; + case FeaturePythonImp::Rejected: + return false; + default: + return FeatureT::hasChildElement(); } } /// Get sub-element visibility - int isElementVisible(const char *element) const override { + int isElementVisible(const char* element) const override + { int ret = imp->isElementVisible(element); - if(ret == -2) + if (ret == -2) { return FeatureT::isElementVisible(element); + } return ret; } /// Set sub-element visibility - int setElementVisible(const char *element, bool visible) override { - int ret = imp->setElementVisible(element,visible); - if(ret == -2) - return FeatureT::setElementVisible(element,visible); + int setElementVisible(const char* element, bool visible) override + { + int ret = imp->setElementVisible(element, visible); + if (ret == -2) { + return FeatureT::setElementVisible(element, visible); + } return ret; } - bool canLinkProperties() const override { + bool canLinkProperties() const override + { switch (imp->canLinkProperties()) { - case FeaturePythonImp::Accepted: - return true; - case FeaturePythonImp::Rejected: - return false; - default: - return FeatureT::canLinkProperties(); + case FeaturePythonImp::Accepted: + return true; + case FeaturePythonImp::Rejected: + return false; + default: + return FeatureT::canLinkProperties(); } } - bool allowDuplicateLabel() const override { + bool allowDuplicateLabel() const override + { switch (imp->allowDuplicateLabel()) { - case FeaturePythonImp::Accepted: - return true; - case FeaturePythonImp::Rejected: - return false; - default: - return FeatureT::allowDuplicateLabel(); + case FeaturePythonImp::Accepted: + return true; + case FeaturePythonImp::Rejected: + return false; + default: + return FeatureT::allowDuplicateLabel(); } } - bool redirectSubName(std::ostringstream &ss, - App::DocumentObject *topParent, App::DocumentObject *child) const override + bool redirectSubName(std::ostringstream& ss, + App::DocumentObject* topParent, + App::DocumentObject* child) const override { - switch (imp->redirectSubName(ss,topParent,child)) { - case FeaturePythonImp::Accepted: - return true; - case FeaturePythonImp::Rejected: - return false; - default: - return FeatureT::redirectSubName(ss, topParent, child); + switch (imp->redirectSubName(ss, topParent, child)) { + case FeaturePythonImp::Accepted: + return true; + case FeaturePythonImp::Rejected: + return false; + default: + return FeatureT::redirectSubName(ss, topParent, child); } } - int canLoadPartial() const override { + int canLoadPartial() const override + { int ret = imp->canLoadPartial(); - if(ret>=0) + if (ret >= 0) { return ret; + } return FeatureT::canLoadPartial(); } - void editProperty(const char *propName) override { - if (!imp->editProperty(propName)) + void editProperty(const char* propName) override + { + if (!imp->editProperty(propName)) { FeatureT::editProperty(propName); + } } - PyObject *getPyObject() override { + PyObject* getPyObject() override + { if (FeatureT::PythonObject.is(Py::_None())) { // ref counter is set to 1 - FeatureT::PythonObject = Py::Object(imp->getPyObject(),true); + FeatureT::PythonObject = Py::Object(imp->getPyObject(), true); } return Py::new_reference_to(FeatureT::PythonObject); } - void setPyObject(PyObject *obj) override { - if (obj) + void setPyObject(PyObject* obj) override + { + if (obj) { FeatureT::PythonObject = obj; - else + } + else { FeatureT::PythonObject = Py::None(); + } } protected: - void onBeforeChange(const Property* prop) override { + void onBeforeChange(const Property* prop) override + { FeatureT::onBeforeChange(prop); imp->onBeforeChange(prop); } - void onBeforeChangeLabel(std::string &newLabel) override{ - if(!imp->onBeforeChangeLabel(newLabel)) + void onBeforeChangeLabel(std::string& newLabel) override + { + if (!imp->onBeforeChangeLabel(newLabel)) { FeatureT::onBeforeChangeLabel(newLabel); + } } - void onChanged(const Property* prop) override { - if(prop == &Proxy) + void onChanged(const Property* prop) override + { + if (prop == &Proxy) { imp->init(Proxy.getValue().ptr()); + } imp->onChanged(prop); FeatureT::onChanged(prop); } - void onDocumentRestored() override { + void onDocumentRestored() override + { imp->onDocumentRestored(); FeatureT::onDocumentRestored(); } - void unsetupObject() override { + void unsetupObject() override + { imp->unsetupObject(); FeatureT::unsetupObject(); } @@ -350,8 +393,8 @@ class FeaturePythonT : public FeatureT public: FeaturePythonT(const FeaturePythonT&) = delete; FeaturePythonT(FeaturePythonT&&) = delete; - FeaturePythonT& operator= (const FeaturePythonT&) = delete; - FeaturePythonT& operator= (FeaturePythonT&&) = delete; + FeaturePythonT& operator=(const FeaturePythonT&) = delete; + FeaturePythonT& operator=(FeaturePythonT&&) = delete; private: FeaturePythonImp* imp; @@ -360,9 +403,9 @@ class FeaturePythonT : public FeatureT }; // Special Feature-Python classes -using FeaturePython = FeaturePythonT; -using GeometryPython = FeaturePythonT; +using FeaturePython = FeaturePythonT; +using GeometryPython = FeaturePythonT; -} //namespace App +} // namespace App -#endif // APP_FEATUREPYTHON_H +#endif // APP_FEATUREPYTHON_H diff --git a/src/App/FreeCADTest.py b/src/App/FreeCADTest.py index e74c5dd55909..8f97014893f0 100644 --- a/src/App/FreeCADTest.py +++ b/src/App/FreeCADTest.py @@ -1,25 +1,25 @@ -#*************************************************************************** -#* Copyright (c) 2002 Jürgen Riegel * -#* * -#* 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 * -#* * -#***************************************************************************/ +# *************************************************************************** +# * Copyright (c) 2002 Jürgen Riegel * +# * * +# * 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 * +# * * +# ***************************************************************************/ # FreeCAD test module # @@ -27,8 +27,7 @@ # (if existing) the test function of the modules - -Log ("FreeCAD test running...\n\n") +Log("FreeCAD test running...\n\n") import sys @@ -39,6 +38,6 @@ testResult = TestApp.TestText(testCase) -Log ("FreeCAD test done\n") +Log("FreeCAD test done\n") sys.exit(0 if testResult.wasSuccessful() else 1) diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index 70ecdb467814..6da11bf098f9 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -52,24 +52,28 @@ GeoFeatureGroupExtension::GeoFeatureGroupExtension() GeoFeatureGroupExtension::~GeoFeatureGroupExtension() = default; -void GeoFeatureGroupExtension::initExtension(ExtensionContainer* obj) { +void GeoFeatureGroupExtension::initExtension(ExtensionContainer* obj) +{ - if(!obj->isDerivedFrom(App::GeoFeature::getClassTypeId())) + if (!obj->isDerivedFrom(App::GeoFeature::getClassTypeId())) { throw Base::RuntimeError("GeoFeatureGroupExtension can only be applied to GeoFeatures"); + } App::GroupExtension::initExtension(obj); } -PropertyPlacement& GeoFeatureGroupExtension::placement() { +PropertyPlacement& GeoFeatureGroupExtension::placement() +{ - if(!getExtendedContainer()) + if (!getExtendedContainer()) { throw Base::RuntimeError("GeoFeatureGroupExtension was not applied to GeoFeature"); + } return static_cast(getExtendedContainer())->Placement; } -void GeoFeatureGroupExtension::transformPlacement(const Base::Placement &transform) +void GeoFeatureGroupExtension::transformPlacement(const Base::Placement& transform) { // NOTE: Keep in sync with APP::GeoFeature Base::Placement plm = this->placement().getValue(); @@ -79,25 +83,29 @@ void GeoFeatureGroupExtension::transformPlacement(const Base::Placement &transfo DocumentObject* GeoFeatureGroupExtension::getGroupOfObject(const DocumentObject* obj) { - if(!obj) + if (!obj) { return nullptr; + } - //we will find origins, but not origin features - if(obj->isDerivedFrom(App::OriginFeature::getClassTypeId())) + // we will find origins, but not origin features + if (obj->isDerivedFrom(App::OriginFeature::getClassTypeId())) { return OriginGroupExtension::getGroupOfObject(obj); + } - //compared to GroupExtension we do return here all GeoFeatureGroups including all extensions derived from it - //like OriginGroup. That is needed as we use this function to get all local coordinate systems. Also there - //is no reason to distinguish between GeoFeatuerGroups, there is only between group/geofeaturegroup + // compared to GroupExtension we do return here all GeoFeatureGroups including all extensions + // derived from it like OriginGroup. That is needed as we use this function to get all local + // coordinate systems. Also there is no reason to distinguish between GeoFeatuerGroups, there is + // only between group/geofeaturegroup auto list = obj->getInList(); for (auto inObj : list) { - //There is a chance that a derived geofeaturegroup links with a local link and hence is not - //the parent group even though it links to the object. We use hasObject as one and only truth - //if it has the object within the group + // There is a chance that a derived geofeaturegroup links with a local link and hence is not + // the parent group even though it links to the object. We use hasObject as one and only + // truth if it has the object within the group auto group = inObj->getExtensionByType(true); - if(group && group->hasObject(obj)) + if (group && group->hasObject(obj)) { return inObj; + } } return nullptr; @@ -115,8 +123,9 @@ Base::Placement GeoFeatureGroupExtension::globalGroupPlacement() } -Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement(GeoFeatureGroupExtension* group, - std::unordered_set& history) +Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement( + GeoFeatureGroupExtension* group, + std::unordered_set& history) { history.insert(this); @@ -135,25 +144,29 @@ Base::Placement GeoFeatureGroupExtension::recursiveGroupPlacement(GeoFeatureGrou return group->placement().getValue(); } -std::vector GeoFeatureGroupExtension::addObjects(std::vector objects) { +std::vector +GeoFeatureGroupExtension::addObjects(std::vector objects) +{ std::vector grp = Group.getValues(); std::vector ret; - for(auto object : objects) { + for (auto object : objects) { - if(!allowObject(object)) + if (!allowObject(object)) { continue; + } - //cross CoordinateSystem links are not allowed, so we need to move the whole link group + // cross CoordinateSystem links are not allowed, so we need to move the whole link group std::vector links = getCSRelevantLinks(object); links.push_back(object); - for( auto obj : links) { - //only one geofeaturegroup per object. - auto *group = App::GeoFeatureGroupExtension::getGroupOfObject(obj); - if(group && group != getExtendedObject()) + for (auto obj : links) { + // only one geofeaturegroup per object. + auto* group = App::GeoFeatureGroupExtension::getGroupOfObject(obj); + if (group && group != getExtendedObject()) { group->getExtensionByType()->removeObject(obj); + } if (!hasObject(obj)) { grp.push_back(obj); @@ -166,61 +179,68 @@ std::vector GeoFeatureGroupExtension::addObjects(std::vector GeoFeatureGroupExtension::removeObjects(std::vector objects) { +std::vector +GeoFeatureGroupExtension::removeObjects(std::vector objects) +{ std::vector removed; std::vector grp = Group.getValues(); - for(auto object : objects) { - //cross CoordinateSystem links are not allowed, so we need to remove the whole link group - std::vector< DocumentObject* > links = getCSRelevantLinks(object); + for (auto object : objects) { + // cross CoordinateSystem links are not allowed, so we need to remove the whole link group + std::vector links = getCSRelevantLinks(object); links.push_back(object); - //remove all links out of group - for(auto link : links) { + // remove all links out of group + for (auto link : links) { auto end = std::remove(grp.begin(), grp.end(), link); - if(end != grp.end()) { + if (end != grp.end()) { grp.erase(end, grp.end()); removed.push_back(link); } } } - if(!removed.empty()) + if (!removed.empty()) { Group.setValues(grp); + } return removed; } -void GeoFeatureGroupExtension::extensionOnChanged(const Property* p) { +void GeoFeatureGroupExtension::extensionOnChanged(const Property* p) +{ - //objects are only allowed in a single GeoFeatureGroup - if(p == &Group && !Group.testStatus(Property::User3)) { + // objects are only allowed in a single GeoFeatureGroup + if (p == &Group && !Group.testStatus(Property::User3)) { - if((!getExtendedObject()->isRestoring() - || getExtendedObject()->getDocument()->testStatus(Document::Importing)) + if ((!getExtendedObject()->isRestoring() + || getExtendedObject()->getDocument()->testStatus(Document::Importing)) && !getExtendedObject()->getDocument()->isPerformingTransaction()) { bool error = false; auto corrected = Group.getValues(); - for(auto obj : Group.getValues()) { + for (auto obj : Group.getValues()) { - //we have already set the obj into the group, so in a case of multiple groups getGroupOfObject - //would return anyone of it and hence it is possible that we miss an error. We need a custom check + // we have already set the obj into the group, so in a case of multiple groups + // getGroupOfObject would return anyone of it and hence it is possible that we miss + // an error. We need a custom check auto list = obj->getInList(); for (auto in : list) { - if(in == getExtendedObject()) + if (in == getExtendedObject()) { continue; + } auto parent = in->getExtensionByType(true); - if(parent && parent->hasObject(obj)) { + if (parent && parent->hasObject(obj)) { error = true; - corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), corrected.end()); + corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), + corrected.end()); } } } - //if an error was found we need to correct the values and inform the user - if(error) { + // if an error was found we need to correct the values and inform the user + if (error) { Base::ObjectStatusLocker guard(Property::User3, &Group); Group.setValues(corrected); throw Base::RuntimeError("Object can only be in a single GeoFeatureGroup"); @@ -232,99 +252,119 @@ void GeoFeatureGroupExtension::extensionOnChanged(const Property* p) { } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getScopedObjectsFromLinks(const DocumentObject* obj, LinkScope scope) { +std::vector +GeoFeatureGroupExtension::getScopedObjectsFromLinks(const DocumentObject* obj, LinkScope scope) +{ - if(!obj) + if (!obj) { return {}; + } - //we get all linked objects. We can't use outList() as this includes the links from expressions - std::vector< App::DocumentObject* > result; + // we get all linked objects. We can't use outList() as this includes the links from expressions + std::vector result; std::vector list; obj->getPropertyList(list); - for(App::Property* prop : list) { + for (App::Property* prop : list) { auto vec = getScopedObjectsFromLink(prop, scope); result.insert(result.end(), vec.begin(), vec.end()); } - //clear all null objects and duplicates + // clear all null objects and duplicates std::sort(result.begin(), result.end()); result.erase(std::unique(result.begin(), result.end()), result.end()); return result; } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getScopedObjectsFromLink(App::Property* prop, LinkScope scope) { +std::vector GeoFeatureGroupExtension::getScopedObjectsFromLink(App::Property* prop, + LinkScope scope) +{ - if(!prop) + if (!prop) { return {}; + } - std::vector< App::DocumentObject* > result; + std::vector result; auto link = Base::freecad_dynamic_cast(prop); - if(link && link->getScope()==scope) + if (link && link->getScope() == scope) { link->getLinks(result); + } return result; } void GeoFeatureGroupExtension::getCSOutList(const App::DocumentObject* obj, - std::vector< DocumentObject* >& vec) { + std::vector& vec) +{ - if(!obj) + if (!obj) { return; + } - //we get all relevant linked objects. We can't use outList() as this includes the links from expressions, - //also we only want links with scope Local + // we get all relevant linked objects. We can't use outList() as this includes the links from + // expressions, also we only want links with scope Local auto result = getScopedObjectsFromLinks(obj, LinkScope::Local); - //we remove all links to origin features and origins, they belong to a CS too and can't be moved - result.erase(std::remove_if(result.begin(), result.end(), [](App::DocumentObject* obj)->bool { - return (obj->isDerivedFrom(App::OriginFeature::getClassTypeId()) || - obj->isDerivedFrom(App::Origin::getClassTypeId())); - }), result.end()); + // we remove all links to origin features and origins, they belong to a CS too and can't be + // moved + result.erase(std::remove_if(result.begin(), + result.end(), + [](App::DocumentObject* obj) -> bool { + return (obj->isDerivedFrom(App::OriginFeature::getClassTypeId()) + || obj->isDerivedFrom(App::Origin::getClassTypeId())); + }), + result.end()); vec.insert(vec.end(), result.begin(), result.end()); - //post process the vector + // post process the vector std::sort(vec.begin(), vec.end()); vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } void GeoFeatureGroupExtension::getCSInList(const DocumentObject* obj, - std::vector< DocumentObject* >& vec) { + std::vector& vec) +{ - if(!obj) + if (!obj) { return; + } - //search the inlist for objects that have non-expression links to us - for(App::DocumentObject* parent : obj->getInList()) { + // search the inlist for objects that have non-expression links to us + for (App::DocumentObject* parent : obj->getInList()) { - //not interested in other groups (and here we mean all groups, normal ones and geofeaturegroup) - if(parent->hasExtension(App::GroupExtension::getExtensionClassTypeId())) + // not interested in other groups (and here we mean all groups, normal ones and + // geofeaturegroup) + if (parent->hasExtension(App::GroupExtension::getExtensionClassTypeId())) { continue; + } - //check if the link is real Local scope one or if it is a expression one (could also be both, so it is not - //enough to check the expressions) + // check if the link is real Local scope one or if it is a expression one (could also be + // both, so it is not enough to check the expressions) auto res = getScopedObjectsFromLinks(parent, LinkScope::Local); - if(std::find(res.begin(), res.end(), obj) != res.end()) + if (std::find(res.begin(), res.end(), obj) != res.end()) { vec.push_back(parent); + } } - //clear all duplicates + // clear all duplicates std::sort(vec.begin(), vec.end()); vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } -std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSRelevantLinks(const DocumentObject* obj) { +std::vector GeoFeatureGroupExtension::getCSRelevantLinks(const DocumentObject* obj) +{ - if(!obj) + if (!obj) { return {}; + } - //get all out links + // get all out links std::vector vec; recursiveCSRelevantLinks(obj, vec); - //post process the list after we added many things + // post process the list after we added many things std::sort(vec.begin(), vec.end()); vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); vec.erase(std::remove(vec.begin(), vec.end(), obj), vec.end()); @@ -333,53 +373,63 @@ std::vector< DocumentObject* > GeoFeatureGroupExtension::getCSRelevantLinks(cons } void GeoFeatureGroupExtension::recursiveCSRelevantLinks(const DocumentObject* obj, - std::vector< DocumentObject* >& vec) { + std::vector& vec) +{ - if(!obj) + if (!obj) { return; + } - std::vector< DocumentObject* > links; + std::vector links; getCSOutList(obj, links); getCSInList(obj, links); - //go on traversing the graph in all directions! - for(auto o : links) { - if(!o || o == obj || std::find(vec.begin(), vec.end(), o) != vec.end()) + // go on traversing the graph in all directions! + for (auto o : links) { + if (!o || o == obj || std::find(vec.begin(), vec.end(), o) != vec.end()) { continue; + } vec.push_back(o); recursiveCSRelevantLinks(o, vec); } } -bool GeoFeatureGroupExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +bool GeoFeatureGroupExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { ret = nullptr; - const char *dot; - if(!subname || *subname==0) { + const char* dot; + if (!subname || *subname == 0) { auto obj = dynamic_cast(getExtendedContainer()); ret = const_cast(obj); - if(mat && transform) + if (mat && transform) { *mat *= const_cast(this)->placement().getValue().toMatrix(); - }else if((dot=strchr(subname,'.'))) { - if(subname[0]!='$') - ret = Group.findUsingMap(std::string(subname,dot)); - else{ - std::string name = std::string(subname+1,dot); - for(auto child : Group.getValues()) { - if(name == child->Label.getStrValue()){ + } + } + else if ((dot = strchr(subname, '.'))) { + if (subname[0] != '$') { + ret = Group.findUsingMap(std::string(subname, dot)); + } + else { + std::string name = std::string(subname + 1, dot); + for (auto child : Group.getValues()) { + if (name == child->Label.getStrValue()) { ret = child; break; } } } - if(ret) { - if(dot) ++dot; - if(dot && *dot - && !ret->hasExtension(App::LinkBaseExtension::getExtensionClassTypeId()) - && !ret->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) - { + if (ret) { + if (dot) { + ++dot; + } + if (dot && *dot && !ret->hasExtension(App::LinkBaseExtension::getExtensionClassTypeId()) + && !ret->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) { // Consider this // Body // | -- Pad @@ -391,33 +441,37 @@ bool GeoFeatureGroupExtension::extensionGetSubObject(DocumentObject *&ret, const // getSubObject(Pad,"Sketch.") as this will transform Sketch // using Pad's placement. // - const char *next = strchr(dot,'.'); - if(next) { - App::DocumentObject *nret=nullptr; - extensionGetSubObject(nret,dot,pyObj,mat,transform,depth+1); - if(nret) { + const char* next = strchr(dot, '.'); + if (next) { + App::DocumentObject* nret = nullptr; + extensionGetSubObject(nret, dot, pyObj, mat, transform, depth + 1); + if (nret) { ret = nret; return true; } } } - if(mat && transform) - *mat *= const_cast(this)->placement().getValue().toMatrix(); - ret = ret->getSubObject(dot?dot:"",pyObj,mat,true,depth+1); + if (mat && transform) { + *mat *= + const_cast(this)->placement().getValue().toMatrix(); + } + ret = ret->getSubObject(dot ? dot : "", pyObj, mat, true, depth + 1); } } return true; } -bool GeoFeatureGroupExtension::areLinksValid(const DocumentObject* obj) { +bool GeoFeatureGroupExtension::areLinksValid(const DocumentObject* obj) +{ - if(!obj) + if (!obj) { return true; + } std::vector list; obj->getPropertyList(list); - for(App::Property* prop : list) { - if(!isLinkValid(prop)) { + for (App::Property* prop : list) { + if (!isLinkValid(prop)) { return false; } } @@ -425,65 +479,79 @@ bool GeoFeatureGroupExtension::areLinksValid(const DocumentObject* obj) { return true; } -bool GeoFeatureGroupExtension::isLinkValid(App::Property* prop) { +bool GeoFeatureGroupExtension::isLinkValid(App::Property* prop) +{ - if(!prop) + if (!prop) { return true; + } - //get the object that holds the property - if(!prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - return true; //this link comes not from a document object, scopes are meaningless + // get the object that holds the property + if (!prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + return true; // this link comes not from a document object, scopes are meaningless + } auto obj = static_cast(prop->getContainer()); - //no cross CS link for local links. + // no cross CS link for local links. auto result = getScopedObjectsFromLink(prop, LinkScope::Local); auto group = getGroupOfObject(obj); - for(auto link : result) { - if(getGroupOfObject(link) != group) + for (auto link : result) { + if (getGroupOfObject(link) != group) { return false; + } } - //for links with scope SubGroup we need to check if all features are part of subgroups - if(obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) { + // for links with scope SubGroup we need to check if all features are part of subgroups + if (obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) { result = getScopedObjectsFromLink(prop, LinkScope::Child); auto groupExt = obj->getExtensionByType(); - for(auto link : result) { - if(!groupExt->hasObject(link, true)) + for (auto link : result) { + if (!groupExt->hasObject(link, true)) { return false; + } } } return true; } -void GeoFeatureGroupExtension::getInvalidLinkObjects(const DocumentObject* obj, std::vector< DocumentObject* >& vec) { +void GeoFeatureGroupExtension::getInvalidLinkObjects(const DocumentObject* obj, + std::vector& vec) +{ - if(!obj) + if (!obj) { return; + } - //no cross CS link for local links. + // no cross CS link for local links. auto result = getScopedObjectsFromLinks(obj, LinkScope::Local); - auto group = obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId()) ? obj : getGroupOfObject(obj); - for(auto link : result) { - if(getGroupOfObject(link) != group) + auto group = obj->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId()) + ? obj + : getGroupOfObject(obj); + for (auto link : result) { + if (getGroupOfObject(link) != group) { vec.push_back(link); + } } - //for links with scope SubGroup we need to check if all features are part of subgroups - if(group) { + // for links with scope SubGroup we need to check if all features are part of subgroups + if (group) { result = getScopedObjectsFromLinks(obj, LinkScope::Child); auto groupExt = group->getExtensionByType(); - for(auto link : result) { - if(!groupExt->hasObject(link, true)) + for (auto link : result) { + if (!groupExt->hasObject(link, true)) { vec.push_back(link); + } } } } -bool GeoFeatureGroupExtension::extensionGetSubObjects(std::vector &ret, int) const { - for(auto obj : Group.getValues()) { - if(obj && obj->isAttachedToDocument() && !obj->testStatus(ObjectStatus::GeoExcluded)) - ret.push_back(std::string(obj->getNameInDocument())+'.'); +bool GeoFeatureGroupExtension::extensionGetSubObjects(std::vector& ret, int) const +{ + for (auto obj : Group.getValues()) { + if (obj && obj->isAttachedToDocument() && !obj->testStatus(ObjectStatus::GeoExcluded)) { + ret.push_back(std::string(obj->getNameInDocument()) + '.'); + } } return true; } @@ -491,9 +559,11 @@ bool GeoFeatureGroupExtension::extensionGetSubObjects(std::vector & // Python feature --------------------------------------------------------- -namespace App { -EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::GeoFeatureGroupExtensionPython, App::GeoFeatureGroupExtension) +namespace App +{ +EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::GeoFeatureGroupExtensionPython, + App::GeoFeatureGroupExtension) // explicit template instantiation template class AppExport ExtensionPythonT>; -} +} // namespace App diff --git a/src/App/GeoFeatureGroupExtension.h b/src/App/GeoFeatureGroupExtension.h index bd3dadb6243c..411f27b65e52 100644 --- a/src/App/GeoFeatureGroupExtension.h +++ b/src/App/GeoFeatureGroupExtension.h @@ -35,21 +35,23 @@ namespace App { /** - * @brief The base class for placeable group of DocumentObjects. It represents a local coordnate system + * @brief The base class for placeable group of DocumentObjects. It represents a local coordnate + * system * - * This class is the FreeCAD way of representing local coordinate systems. It groups its children beneath - * it and transforms them all with the GeoFeatureGroup placement. A few important properties: - * - Every child that belongs to the CS must be in the Group property. Even if a sketch is part of a pad, - * it must be in the Group property of the same GeoFeatureGroup as pad. This also holds for normal - * GroupExtensions. They can be added to a GeoFeatureGroup, but all objects that the group holds must - * also be added to the GeoFeatureGroup + * This class is the FreeCAD way of representing local coordinate systems. It groups its children + * beneath it and transforms them all with the GeoFeatureGroup placement. A few important + * properties: + * - Every child that belongs to the CS must be in the Group property. Even if a sketch is part of a + * pad, it must be in the Group property of the same GeoFeatureGroup as pad. This also holds for + * normal GroupExtensions. They can be added to a GeoFeatureGroup, but all objects that the group + * holds must also be added to the GeoFeatureGroup * - Objects can be only in a single GeoFeatureGroup. It is not allowed to have a document object in * multiple GeoFeatureGroups - * - PropertyLinks between different GeoFeatureGroups are forbidden. There are special link properties - * that allow such cross-CS links. + * - PropertyLinks between different GeoFeatureGroups are forbidden. There are special link + * properties that allow such cross-CS links. * - Expressions can cross GeoFeatureGroup borders */ -class AppExport GeoFeatureGroupExtension : public App::GroupExtension +class AppExport GeoFeatureGroupExtension: public App::GroupExtension { using inherited = App::GroupExtension; EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::GeoFeatureGroupExtension); @@ -65,7 +67,7 @@ class AppExport GeoFeatureGroupExtension : public App::GroupExtension * features. * @param transform (input). */ - virtual void transformPlacement(const Base::Placement &transform); + virtual void transformPlacement(const Base::Placement& transform); /// Constructor GeoFeatureGroupExtension(); @@ -84,65 +86,77 @@ class AppExport GeoFeatureGroupExtension : public App::GroupExtension * @brief Calculates the global placement of this group * * The returned placement describes the transformation from the global reference coordinate - * system to the local coordinate system of this geo feature group. If this group has a no parent - * GeoFeatureGroup the returned placement is the one of this group. For multiple stacked + * system to the local coordinate system of this geo feature group. If this group has a no + * parent GeoFeatureGroup the returned placement is the one of this group. For multiple stacked * GeoFeatureGroups the returned Placement is the combination of all parent placements including * the one of this group. - * @return Base::Placement The transformation from global reference system to the groups local system + * @return Base::Placement The transformation from global reference system to the groups local + * system */ Base::Placement globalGroupPlacement(); /// Returns true if the given DocumentObject is DocumentObjectGroup but not GeoFeatureGroup - static bool isNonGeoGroup(const DocumentObject* obj) { - return obj->hasExtension(GroupExtension::getExtensionClassTypeId()) && - !obj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()); + static bool isNonGeoGroup(const DocumentObject* obj) + { + return obj->hasExtension(GroupExtension::getExtensionClassTypeId()) + && !obj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()); } - bool extensionGetSubObject(DocumentObject *&ret, const char *subname, PyObject **pyObj, - Base::Matrix4D *mat, bool transform, int depth) const override; + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const override; - bool extensionGetSubObjects(std::vector &ret, int reason) const override; + bool extensionGetSubObjects(std::vector& ret, int reason) const override; - std::vector< DocumentObject* > addObjects(std::vector< DocumentObject* > obj) override; - std::vector< DocumentObject* > removeObjects(std::vector< DocumentObject* > obj) override; + std::vector addObjects(std::vector obj) override; + std::vector removeObjects(std::vector obj) override; - /// Collects all links that are relevant for the coordinate system, meaning all recursive links to - /// obj and from obj excluding expressions and stopping the recursion at other geofeaturegroups. - /// The result is the combination of CSOutList and CSInList. + /// Collects all links that are relevant for the coordinate system, meaning all recursive links + /// to obj and from obj excluding expressions and stopping the recursion at other + /// geofeaturegroups. The result is the combination of CSOutList and CSInList. static std::vector getCSRelevantLinks(const App::DocumentObject* obj); - /// Checks if the links of the given object comply with all GeoFeatureGroup requirements, that means - /// if normal links are only within the parent GeoFeatureGroup. + /// Checks if the links of the given object comply with all GeoFeatureGroup requirements, that + /// means if normal links are only within the parent GeoFeatureGroup. static bool areLinksValid(const App::DocumentObject* obj); /// Checks if the given link complies with all GeoFeatureGroup requirements, that means /// if normal links are only within the parent GeoFeatureGroup. static bool isLinkValid(App::Property* link); - //Returns all objects that are wrongly linked from this object, meaning which are out of scope of the - //links of obj - static void getInvalidLinkObjects(const App::DocumentObject* obj, std::vector& vec); + // Returns all objects that are wrongly linked from this object, meaning which are out of scope + // of the links of obj + static void getInvalidLinkObjects(const App::DocumentObject* obj, + std::vector& vec); private: - Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group, std::unordered_set& history); - static std::vector getScopedObjectsFromLinks(const App::DocumentObject*, LinkScope scope = LinkScope::Local); - static std::vector getScopedObjectsFromLink(App::Property*, LinkScope scope = LinkScope::Local); - - /// Collects GeoFeatureGroup relevant objects that are linked from the given one. That means all linked objects - /// except GeoFeatureGroups. Expressions links are ignored. Only local scope links are considered. There is no - /// recursion. An exception is thrown when there are dependency loops. - static void getCSOutList(const App::DocumentObject* obj, std::vector& vec); + Base::Placement recursiveGroupPlacement(GeoFeatureGroupExtension* group, + std::unordered_set& history); + static std::vector + getScopedObjectsFromLinks(const App::DocumentObject*, LinkScope scope = LinkScope::Local); + static std::vector + getScopedObjectsFromLink(App::Property*, LinkScope scope = LinkScope::Local); + + /// Collects GeoFeatureGroup relevant objects that are linked from the given one. That means all + /// linked objects except GeoFeatureGroups. Expressions links are ignored. Only local scope + /// links are considered. There is no recursion. An exception is thrown when there are + /// dependency loops. + static void getCSOutList(const App::DocumentObject* obj, + std::vector& vec); /// Collects GeoFeatureGroup relevant objects that link to the given one. That means all objects - /// except GeoFeatureGroups. Expression links are ignored. Only local scope links are relevant, and - /// there is no recursion. An exception is thrown when there are dependency loops. + /// except GeoFeatureGroups. Expression links are ignored. Only local scope links are relevant, + /// and there is no recursion. An exception is thrown when there are dependency loops. static void getCSInList(const App::DocumentObject* obj, std::vector& vec); static void recursiveCSRelevantLinks(const App::DocumentObject* obj, std::vector& vec); - }; -using GeoFeatureGroupExtensionPython = ExtensionPythonT>; +using GeoFeatureGroupExtensionPython = + ExtensionPythonT>; -} //namespace App +} // namespace App -#endif // APP_GeoFeatureGroup_H +#endif // APP_GeoFeatureGroup_H diff --git a/src/App/GeoFeatureGroupExtensionPyImp.cpp b/src/App/GeoFeatureGroupExtensionPyImp.cpp index 6a27200f32eb..48660bb41e52 100644 --- a/src/App/GeoFeatureGroupExtensionPyImp.cpp +++ b/src/App/GeoFeatureGroupExtensionPyImp.cpp @@ -36,7 +36,7 @@ std::string GeoFeatureGroupExtensionPy::representation() const return {""}; } -PyObject *GeoFeatureGroupExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* GeoFeatureGroupExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -45,5 +45,3 @@ int GeoFeatureGroupExtensionPy::setCustomAttributes(const char* /*attr*/, PyObje { return 0; } - - diff --git a/src/App/GeoFeaturePyImp.cpp b/src/App/GeoFeaturePyImp.cpp index 1792f225b92a..2d78e698676e 100644 --- a/src/App/GeoFeaturePyImp.cpp +++ b/src/App/GeoFeaturePyImp.cpp @@ -37,16 +37,18 @@ std::string GeoFeaturePy::representation() const return {""}; } -PyObject* GeoFeaturePy::getPaths(PyObject * /*args*/) +PyObject* GeoFeaturePy::getPaths(PyObject* /*args*/) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } -PyObject* GeoFeaturePy::getGlobalPlacement(PyObject * args) { +PyObject* GeoFeaturePy::getGlobalPlacement(PyObject* args) +{ - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } try { Base::Placement p = static_cast(getDocumentObjectPtr())->globalPlacement(); @@ -57,7 +59,8 @@ PyObject* GeoFeaturePy::getGlobalPlacement(PyObject * args) { } } -PyObject* GeoFeaturePy::getGlobalPlacementOf(PyObject * args) { +PyObject* GeoFeaturePy::getGlobalPlacementOf(PyObject* args) +{ PyObject* pyTargetObj {nullptr}; PyObject* pyRootObj {nullptr}; @@ -78,10 +81,11 @@ PyObject* GeoFeaturePy::getGlobalPlacementOf(PyObject * args) { } } -PyObject* GeoFeaturePy::getPropertyNameOfGeometry(PyObject * args) +PyObject* GeoFeaturePy::getPropertyNameOfGeometry(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } GeoFeature* object = this->getGeoFeaturePtr(); const PropertyComplexGeoData* prop = object->getPropertyOfGeometry(); @@ -92,10 +96,11 @@ PyObject* GeoFeaturePy::getPropertyNameOfGeometry(PyObject * args) return Py::new_reference_to(Py::None()); } -PyObject* GeoFeaturePy::getPropertyOfGeometry(PyObject * args) +PyObject* GeoFeaturePy::getPropertyOfGeometry(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } GeoFeature* object = this->getGeoFeaturePtr(); const PropertyComplexGeoData* prop = object->getPropertyOfGeometry(); @@ -105,7 +110,7 @@ PyObject* GeoFeaturePy::getPropertyOfGeometry(PyObject * args) return Py::new_reference_to(Py::None()); } -PyObject *GeoFeaturePy::getCustomAttributes(const char* /*attr*/) const +PyObject* GeoFeaturePy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -115,7 +120,8 @@ int GeoFeaturePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) return 0; } -Py::String GeoFeaturePy::getElementMapVersion() const { - return Py::String(getGeoFeaturePtr()->getElementMapVersion( - getGeoFeaturePtr()->getPropertyOfGeometry())); +Py::String GeoFeaturePy::getElementMapVersion() const +{ + return Py::String( + getGeoFeaturePtr()->getElementMapVersion(getGeoFeaturePtr()->getPropertyOfGeometry())); } diff --git a/src/App/Graphviz.cpp b/src/App/Graphviz.cpp index 567dc0728ac0..ec74cf5f68d1 100644 --- a/src/App/Graphviz.cpp +++ b/src/App/Graphviz.cpp @@ -38,21 +38,22 @@ using namespace App; using namespace boost; -void Document::writeDependencyGraphViz(std::ostream &out) +void Document::writeDependencyGraphViz(std::ostream& out) { // // caching vertex to DocObject - //std::map VertexMap; - //for(std::map::const_iterator It1= _DepConMap.begin();It1 != _DepConMap.end(); ++It1) + // std::map VertexMap; + // for(std::map::const_iterator It1= _DepConMap.begin();It1 != + // _DepConMap.end(); ++It1) // VertexMap[It1->second] = It1->first; out << "digraph G {" << std::endl; out << "\tordering=out;" << std::endl; out << "\tnode [shape = box];" << std::endl; - for (const auto &It : d->objectMap) { + for (const auto& It : d->objectMap) { out << "\t" << It.first << ";" << std::endl; std::vector OutList = It.second->getOutList(); - for (const auto &It2 : OutList) { + for (const auto& It2 : OutList) { if (It2) { out << "\t" << It.first << "->" << It2->getNameInDocument() << ";" << std::endl; } @@ -75,14 +76,19 @@ void Document::exportGraphviz(std::ostream& out) const { /* Type defs for a graph with graphviz attributes */ using GraphvizAttributes = std::map; - using Graph = boost::subgraph< adjacency_list, - property >, - property - > > > > >; + using Graph = boost::subgraph, + property>, + property>>>>>; /** * @brief The GraphCreator class @@ -91,18 +97,25 @@ void Document::exportGraphviz(std::ostream& out) const * */ - class GraphCreator { + class GraphCreator + { public: - - explicit GraphCreator(struct DocumentP* _d) : d(_d), seed(std::random_device()()), distribution(0,255) { + explicit GraphCreator(struct DocumentP* _d) + : d(_d) + , seed(std::random_device()()) + , distribution(0, 255) + { build(); } - const Graph & getGraph() const { return DepList; } + const Graph& getGraph() const + { + return DepList; + } private: - - void build() { + void build() + { // Set attribute(s) for main graph get_property(DepList, graph_graph_attribute)["compound"] = "true"; @@ -119,7 +132,8 @@ void Document::exportGraphviz(std::ostream& out) const * @return A string */ - std::string getId(const DocumentObject * docObj) { + std::string getId(const DocumentObject* docObj) + { std::string id; if (docObj->isAttachedToDocument()) { auto doc = docObj->getDocument(); @@ -136,25 +150,32 @@ void Document::exportGraphviz(std::ostream& out) const * @return A string */ - std::string getId(const ObjectIdentifier & path) { - DocumentObject * docObj = path.getDocumentObject(); - if (!docObj) + std::string getId(const ObjectIdentifier& path) + { + DocumentObject* docObj = path.getDocumentObject(); + if (!docObj) { return {}; + } - return std::string((docObj)->getDocument()->getName()) + "#" + docObj->getNameInDocument() + "." + path.getPropertyName() + path.getSubPathStr(); + return std::string((docObj)->getDocument()->getName()) + "#" + + docObj->getNameInDocument() + "." + path.getPropertyName() + path.getSubPathStr(); } - std::string getClusterName(const DocumentObject * docObj) const { + std::string getClusterName(const DocumentObject* docObj) const + { return std::string("cluster") + docObj->getNameInDocument(); } - void setGraphLabel(Graph& g, const DocumentObject* obj) const { + void setGraphLabel(Graph& g, const DocumentObject* obj) const + { std::string name(obj->getNameInDocument()); std::string label(obj->Label.getValue()); - if (name == label) + if (name == label) { get_property(g, graph_graph_attribute)["label"] = name; - else + } + else { get_property(g, graph_graph_attribute)["label"] = name + "\n(" + label + ")"; + } } /** @@ -162,7 +183,8 @@ void Document::exportGraphviz(std::ostream& out) const * @param obj DocumentObject */ - void setGraphAttributes(const DocumentObject * obj) { + void setGraphAttributes(const DocumentObject* obj) + { assert(GraphList.find(obj) != GraphList.end()); get_property(*GraphList[obj], graph_name) = getClusterName(obj); @@ -179,7 +201,8 @@ void Document::exportGraphviz(std::ostream& out) const * @param name Name of node */ - void setPropertyVertexAttributes(Graph & g, Vertex vertex, const std::string & name) { + void setPropertyVertexAttributes(Graph& g, Vertex vertex, const std::string& name) + { get(vertex_attribute, g)[vertex]["label"] = name; get(vertex_attribute, g)[vertex]["shape"] = "box"; get(vertex_attribute, g)[vertex]["style"] = "dashed"; @@ -187,13 +210,15 @@ void Document::exportGraphviz(std::ostream& out) const } /** - * @brief addExpressionSubgraphIfNeeded Add a subgraph to the main graph if it is needed, i.e. there are defined at least one - * expression in the document object, or other objects are referencing properties in it. + * @brief addExpressionSubgraphIfNeeded Add a subgraph to the main graph if it is needed, + * i.e. there are defined at least one expression in the document object, or other objects + * are referencing properties in it. * @param obj DocumentObject to assess. * @param CSSubgraphs Boolean if the GeoFeatureGroups are created as subgraphs */ - void addExpressionSubgraphIfNeeded(DocumentObject * obj, bool CSsubgraphs) { + void addExpressionSubgraphIfNeeded(DocumentObject* obj, bool CSsubgraphs) + { auto expressions = obj->ExpressionEngine.getExpressions(); @@ -205,8 +230,9 @@ void Document::exportGraphviz(std::ostream& out) const auto group = GeoFeatureGroupExtension::getGroupOfObject(obj); if (group) { auto it = GraphList.find(group); - if (it != GraphList.end()) + if (it != GraphList.end()) { graph = it->second; + } } } @@ -216,16 +242,18 @@ void Document::exportGraphviz(std::ostream& out) const setGraphAttributes(obj); } - // Create subgraphs for all document objects that it depends on; it will depend on some property there - for (const auto &expr : expressions) { + // Create subgraphs for all document objects that it depends on; it will depend on + // some property there + for (const auto& expr : expressions) { std::map deps; expr.second->getIdentifiers(deps); - for (const auto &dep : deps) { - if (dep.second) + for (const auto& dep : deps) { + if (dep.second) { continue; - DocumentObject * o = dep.first.getDocumentObject(); + } + DocumentObject* o = dep.first.getDocumentObject(); // Doesn't exist already? if (o && !GraphList[o]) { @@ -249,38 +277,48 @@ void Document::exportGraphviz(std::ostream& out) const } /** - * @brief add Add @docObj to the graph, including all expressions (and dependencies) it includes. + * @brief add Add @docObj to the graph, including all expressions (and dependencies) it + * includes. * @param docObj The document object to add. * @param name Name of node. */ - void add(DocumentObject *docObj, const std::string &name, const std::string &label, bool CSSubgraphs) + void add(DocumentObject* docObj, + const std::string& name, + const std::string& label, + bool CSSubgraphs) { - //don't add objects twice - if (std::find(objects.begin(), objects.end(), docObj) != objects.end()) + // don't add objects twice + if (std::find(objects.begin(), objects.end(), docObj) != objects.end()) { return; + } - //find the correct graph to add the vertex to. Check first expression graphs, afterwards - //the parent CS and origin graphs - Graph *sgraph = GraphList[docObj]; + // find the correct graph to add the vertex to. Check first expression graphs, + // afterwards the parent CS and origin graphs + Graph* sgraph = GraphList[docObj]; if (CSSubgraphs) { if (!sgraph) { auto group = GeoFeatureGroupExtension::getGroupOfObject(docObj); if (group) { - if (docObj->isDerivedFrom(App::OriginFeature::getClassTypeId())) - sgraph = GraphList[group->getExtensionByType()->Origin.getValue()]; - else + if (docObj->isDerivedFrom(App::OriginFeature::getClassTypeId())) { + sgraph = GraphList[group->getExtensionByType() + ->Origin.getValue()]; + } + else { sgraph = GraphList[group]; + } } } if (!sgraph) { - if (docObj->isDerivedFrom(OriginFeature::getClassTypeId())) - sgraph = GraphList[static_cast(docObj)->getOrigin()]; + if (docObj->isDerivedFrom(OriginFeature::getClassTypeId())) { + sgraph = GraphList[static_cast(docObj)->getOrigin()]; + } } } - if (!sgraph) + if (!sgraph) { sgraph = &DepList; + } // Keep a list of all added document objects. objects.insert(docObj); @@ -294,21 +332,25 @@ void Document::exportGraphviz(std::ostream& out) const get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["style"] = "filled"; get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["shape"] = "Mrecord"; // Set node label - if (name == label) + if (name == label) { get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["label"] = name; - else - get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["label"] = name + "\n(" + label + ")"; + } + else { + get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["label"] = + name + "\n(" + label + ")"; + } } else { get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["style"] = "invis"; - get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["fixedsize"] = "true"; + get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["fixedsize"] = + "true"; get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["width"] = "0"; get(vertex_attribute, *sgraph)[LocalVertexList[getId(docObj)]]["height"] = "0"; } // Add expressions and its dependencies - auto expressions{docObj->ExpressionEngine.getExpressions()}; - for (const auto &expr : expressions) { + auto expressions {docObj->ExpressionEngine.getExpressions()}; + for (const auto& expr : expressions) { auto found = std::as_const(GlobalVertexList).find(getId(expr.first)); if (found == GlobalVertexList.end()) { int vid = LocalVertexList[getId(expr.first)] = add_vertex(*sgraph); @@ -318,63 +360,70 @@ void Document::exportGraphviz(std::ostream& out) const } // Add all dependencies - for (const auto &expression : expressions) { + for (const auto& expression : expressions) { // Get dependencies std::map deps; expression.second->getIdentifiers(deps); - // Create subgraphs for all documentobjects that it depends on; it will depend on some property there - for (const auto &dep : deps) { + // Create subgraphs for all documentobjects that it depends on; it will depend on + // some property there + for (const auto& dep : deps) { if (dep.second) { continue; } - DocumentObject *depObjDoc = dep.first.getDocumentObject(); + DocumentObject* depObjDoc = dep.first.getDocumentObject(); auto found = GlobalVertexList.find(getId(dep.first)); if (found == GlobalVertexList.end()) { - Graph *depSgraph = GraphList[depObjDoc] ? GraphList[depObjDoc] : &DepList; + Graph* depSgraph = GraphList[depObjDoc] ? GraphList[depObjDoc] : &DepList; LocalVertexList[getId(dep.first)] = add_vertex(*depSgraph); GlobalVertexList[getId(dep.first)] = vertex_no++; - setPropertyVertexAttributes(*depSgraph, LocalVertexList[getId(dep.first)], dep.first.getPropertyName() + dep.first.getSubPathStr()); + setPropertyVertexAttributes(*depSgraph, + LocalVertexList[getId(dep.first)], + dep.first.getPropertyName() + + dep.first.getSubPathStr()); } } } } - void recursiveCSSubgraphs(DocumentObject* cs, DocumentObject* parent) { + void recursiveCSSubgraphs(DocumentObject* cs, DocumentObject* parent) + { auto graph = parent ? GraphList[parent] : &DepList; // check if the value for the key 'parent' is null - if (!graph) + if (!graph) { return; + } auto& sub = graph->create_subgraph(); GraphList[cs] = ⊂ get_property(sub, graph_name) = getClusterName(cs); - //build random color string + // build random color string std::stringstream stream; - stream << "#" << std::setfill('0') << std::setw(2)<< std::hex << distribution(seed) - << std::setfill('0') << std::setw(2)<< std::hex << distribution(seed) - << std::setfill('0') << std::setw(2)<< std::hex << distribution(seed) << 80; + stream << "#" << std::setfill('0') << std::setw(2) << std::hex << distribution(seed) + << std::setfill('0') << std::setw(2) << std::hex << distribution(seed) + << std::setfill('0') << std::setw(2) << std::hex << distribution(seed) << 80; std::string result(stream.str()); get_property(sub, graph_graph_attribute)["bgcolor"] = result; get_property(sub, graph_graph_attribute)["style"] = "rounded,filled"; setGraphLabel(sub, cs); - for(auto obj : cs->getOutList()) { + for (auto obj : cs->getOutList()) { if (obj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) { // in case of dependencies loops check if obj is already part of the // map to avoid infinite recursions auto it = GraphList.find(obj); - if (it == GraphList.end()) + if (it == GraphList.end()) { recursiveCSSubgraphs(obj, cs); + } } } - //setup the origin if available - if(cs->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) { + // setup the origin if available + if (cs->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) { auto origin = cs->getExtensionByType()->Origin.getValue(); if (!origin) { std::cerr << "Origin feature not found" << std::endl; @@ -388,67 +437,80 @@ void Document::exportGraphviz(std::ostream& out) const } } - void addSubgraphs() { + void addSubgraphs() + { - ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DependencyGraph"); + ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/DependencyGraph"); bool CSSubgraphs = depGrp->GetBool("GeoFeatureSubgraphs", true); - if(CSSubgraphs) { - //first build up the coordinate system subgraphs + if (CSSubgraphs) { + // first build up the coordinate system subgraphs for (auto objectIt : d->objectArray) { - // ignore groups inside other groups, these will be processed in one of the next recursive calls. - // App::Origin now has the GeoFeatureGroupExtension but it should not move its - // group symbol outside its parent - if (!objectIt->isDerivedFrom(Origin::getClassTypeId()) && - objectIt->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()) && - GeoFeatureGroupExtension::getGroupOfObject(objectIt) == nullptr) - { + // ignore groups inside other groups, these will be processed in one of the next + // recursive calls. App::Origin now has the GeoFeatureGroupExtension but it + // should not move its group symbol outside its parent + if (!objectIt->isDerivedFrom(Origin::getClassTypeId()) + && objectIt->hasExtension( + GeoFeatureGroupExtension::getExtensionClassTypeId()) + && GeoFeatureGroupExtension::getGroupOfObject(objectIt) == nullptr) { recursiveCSSubgraphs(objectIt, nullptr); } } } // Internal document objects - for (const auto & It : d->objectMap) + for (const auto& It : d->objectMap) { addExpressionSubgraphIfNeeded(It.second, CSSubgraphs); + } // Add external document objects - for (const auto & it : d->objectMap) { + for (const auto& it : d->objectMap) { std::vector OutList = it.second->getOutList(); for (auto obj : OutList) { if (obj) { - std::map::const_iterator item = GlobalVertexList.find(getId(obj)); + std::map::const_iterator item = + GlobalVertexList.find(getId(obj)); - if (item == GlobalVertexList.end()) + if (item == GlobalVertexList.end()) { addExpressionSubgraphIfNeeded(obj, CSSubgraphs); + } } } } - } // Filling up the adjacency List - void buildAdjacencyList() { + void buildAdjacencyList() + { - ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DependencyGraph"); + ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/DependencyGraph"); bool CSSubgraphs = depGrp->GetBool("GeoFeatureSubgraphs", true); // Add internal document objects - for (const auto & It : d->objectMap) - add(It.second, It.second->getNameInDocument(), It.second->Label.getValue(), CSSubgraphs); + for (const auto& It : d->objectMap) { + add(It.second, + It.second->getNameInDocument(), + It.second->Label.getValue(), + CSSubgraphs); + } // Add external document objects - for (const auto & It : d->objectMap) { + for (const auto& It : d->objectMap) { std::vector OutList = It.second->getOutList(); for (auto obj : OutList) { if (obj) { - std::map::const_iterator item = GlobalVertexList.find(getId(obj)); + std::map::const_iterator item = + GlobalVertexList.find(getId(obj)); if (item == GlobalVertexList.end()) { if (obj->isAttachedToDocument()) { add(obj, - std::string(obj->getDocument()->getName()) + "#" + obj->getNameInDocument(), - std::string(obj->getDocument()->getName()) + "#" + obj->Label.getValue(), + std::string(obj->getDocument()->getName()) + "#" + + obj->getNameInDocument(), + std::string(obj->getDocument()->getName()) + "#" + + obj->Label.getValue(), CSSubgraphs); } } @@ -457,31 +519,37 @@ void Document::exportGraphviz(std::ostream& out) const } } - void addEdges() { + void addEdges() + { // Get edge properties for main graph - const boost::property_map::type& edgeAttrMap = boost::get(boost::edge_attribute, DepList); + const boost::property_map::type& edgeAttrMap = + boost::get(boost::edge_attribute, DepList); // Track edges between document objects connected by expression dependencies - std::set > existingEdges; + std::set> existingEdges; // Add edges between properties - for (const auto &docObj : objects) { + for (const auto& docObj : objects) { // Add expressions and its dependencies auto expressions = docObj->ExpressionEngine.getExpressions(); - for (const auto &expr : expressions) { + for (const auto& expr : expressions) { std::map deps; expr.second->getIdentifiers(deps); - // Create subgraphs for all documentobjects that it depends on; it will depend on some property there - for (const auto &dep : deps) { - if (dep.second) + // Create subgraphs for all documentobjects that it depends on; it will depend + // on some property there + for (const auto& dep : deps) { + if (dep.second) { continue; - DocumentObject * depObjDoc = dep.first.getDocumentObject(); + } + DocumentObject* depObjDoc = dep.first.getDocumentObject(); Edge edge; bool inserted; - tie(edge, inserted) = add_edge(GlobalVertexList[getId(expr.first)], GlobalVertexList[getId(dep.first)], DepList); + tie(edge, inserted) = add_edge(GlobalVertexList[getId(expr.first)], + GlobalVertexList[getId(dep.first)], + DepList); // Add this edge to the set of all expression generated edges existingEdges.insert(std::make_pair(docObj, depObjDoc)); @@ -493,54 +561,69 @@ void Document::exportGraphviz(std::ostream& out) const } } - ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DependencyGraph"); + ParameterGrp::handle depGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/DependencyGraph"); bool omitGeoFeatureGroups = depGrp->GetBool("GeoFeatureSubgraphs", true); // Add edges between document objects - for (const auto & It : d->objectMap) { + for (const auto& It : d->objectMap) { - if(omitGeoFeatureGroups && It.second->isDerivedFrom(Origin::getClassTypeId())) { + if (omitGeoFeatureGroups && It.second->isDerivedFrom(Origin::getClassTypeId())) { continue; } std::map dups; std::vector OutList = It.second->getOutList(); - const DocumentObject * docObj = It.second; - const bool docObj_is_group = docObj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()); + const DocumentObject* docObj = It.second; + const bool docObj_is_group = + docObj->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()); for (auto obj : OutList) { if (obj) { - if(omitGeoFeatureGroups && docObj_is_group && GeoFeatureGroupExtension::getGroupOfObject(obj) == docObj) { + if (omitGeoFeatureGroups && docObj_is_group + && GeoFeatureGroupExtension::getGroupOfObject(obj) == docObj) { continue; } // Count duplicate edges - bool inserted = edge(GlobalVertexList[getId(docObj)], GlobalVertexList[getId(obj)], DepList).second; + bool inserted = edge(GlobalVertexList[getId(docObj)], + GlobalVertexList[getId(obj)], + DepList) + .second; if (inserted) { dups[obj]++; continue; } // Skip edge if an expression edge already exists - if (existingEdges.find(std::make_pair(docObj, obj)) != existingEdges.end()) + if (existingEdges.find(std::make_pair(docObj, obj)) + != existingEdges.end()) { continue; + } // Add edge Edge edge; - tie(edge, inserted) = add_edge(GlobalVertexList[getId(docObj)], GlobalVertexList[getId(obj)], DepList); + tie(edge, inserted) = add_edge(GlobalVertexList[getId(docObj)], + GlobalVertexList[getId(obj)], + DepList); // Set properties to make arrows go between subgraphs if needed - if (GraphList[docObj]) + if (GraphList[docObj]) { edgeAttrMap[edge]["ltail"] = getClusterName(docObj); - if (GraphList[obj]) + } + if (GraphList[obj]) { edgeAttrMap[edge]["lhead"] = getClusterName(obj); + } } } // Set labels for duplicate edges - for (const auto & dup : dups) { - Edge e(edge(GlobalVertexList[getId(It.second)], GlobalVertexList[getId(dup.first)], DepList).first); + for (const auto& dup : dups) { + Edge e(edge(GlobalVertexList[getId(It.second)], + GlobalVertexList[getId(dup.first)], + DepList) + .first); std::stringstream s; s << " " << (dup.second + 1) << "x"; edgeAttrMap[e]["label"] = s.str(); @@ -550,10 +633,11 @@ void Document::exportGraphviz(std::ostream& out) const using EdgeMap = std::unordered_multimap; - void removeEdges(EdgeMap & in_edges, - EdgeMap & out_edges, - std::pair i_pair, - std::function select_vertex) { + void removeEdges(EdgeMap& in_edges, + EdgeMap& out_edges, + std::pair i_pair, + std::function select_vertex) + { auto i = i_pair.first; while (i != i_pair.second) { @@ -562,10 +646,12 @@ void Document::exportGraphviz(std::ostream& out) const auto in_i = in_i_pair.first; while (in_i != in_i_pair.second) { - if (in_i->second == i->second) + if (in_i->second == i->second) { in_i = in_edges.erase(in_i); - else + } + else { ++in_i; + } } // Remove node from out_edges @@ -574,12 +660,13 @@ void Document::exportGraphviz(std::ostream& out) const } #if defined(__clang__) -#elif defined (__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif - void markCycles() { + void markCycles() + { bool changed = true; std::unordered_set in_use; EdgeMap in_edges; @@ -588,8 +675,9 @@ void Document::exportGraphviz(std::ostream& out) const // Add all vertices to the in_use set graph_traits::vertex_iterator vi, vi_end; tie(vi, vi_end) = vertices(DepList); - for (; vi != vi_end; ++vi) + for (; vi != vi_end; ++vi) { in_use.insert(*vi); + } // Add all edges to the in_edges and out_edges multimaps graph_traits::edge_iterator ei, ei_end; @@ -616,21 +704,26 @@ void Document::exportGraphviz(std::ostream& out) const auto i_in_deg_pair = in_edges.equal_range(*uvi); auto i_out_deg_pair = out_edges.equal_range(*uvi); - if (i_in_deg_pair.first == in_edges.end() && i_out_deg_pair.first == out_edges.end()) { + if (i_in_deg_pair.first == in_edges.end() + && i_out_deg_pair.first == out_edges.end()) { uvi = in_use.erase(uvi); continue; } // Remove out edges of nodes that don't have a single edge in if (i_in_deg_pair.first == in_edges.end()) { - removeEdges(in_edges, out_edges, i_out_deg_pair, [&](Edge e) { return target(e, DepList); }); + removeEdges(in_edges, out_edges, i_out_deg_pair, [&](Edge e) { + return target(e, DepList); + }); changed = true; i_out_deg_pair = out_edges.equal_range(*uvi); } // Remove in edges of nodes that don't have a single edge out if (i_out_deg_pair.first == out_edges.end()) { - removeEdges(out_edges, in_edges, i_in_deg_pair, [&](Edge e) { return source(e, DepList); }); + removeEdges(out_edges, in_edges, i_in_deg_pair, [&](Edge e) { + return source(e, DepList); + }); changed = true; } @@ -639,41 +732,48 @@ void Document::exportGraphviz(std::ostream& out) const } // Update colors in graph - const boost::property_map::type& edgeAttrMap = boost::get(boost::edge_attribute, DepList); - for (auto ei : out_edges) + const boost::property_map::type& edgeAttrMap = + boost::get(boost::edge_attribute, DepList); + for (auto ei : out_edges) { edgeAttrMap[ei.second]["color"] = "red"; + } } #if defined(__clang__) -#elif defined (__GNUC__) -# pragma GCC diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop #endif - void markOutOfScopeLinks() { - const boost::property_map::type& edgeAttrMap = boost::get(boost::edge_attribute, DepList); + void markOutOfScopeLinks() + { + const boost::property_map::type& edgeAttrMap = + boost::get(boost::edge_attribute, DepList); - for( auto obj : objects) { + for (auto obj : objects) { std::vector invalids; GeoFeatureGroupExtension::getInvalidLinkObjects(obj, invalids); - //isLinkValid returns true for non-link properties - for(auto linkedObj : invalids) { + // isLinkValid returns true for non-link properties + for (auto linkedObj : invalids) { - auto res = edge(GlobalVertexList[getId(obj)], GlobalVertexList[getId(linkedObj)], DepList); - if(res.second) + auto res = edge(GlobalVertexList[getId(obj)], + GlobalVertexList[getId(linkedObj)], + DepList); + if (res.second) { edgeAttrMap[res.first]["color"] = "orange"; + } } } } const struct DocumentP* d; Graph DepList; - int vertex_no{0}; + int vertex_no {0}; std::map LocalVertexList; std::map GlobalVertexList; std::set objects; std::map GraphList; - //random color generation + // random color generation std::mt19937 seed; std::uniform_int_distribution distribution; }; diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index 7e47743846cc..6e017b82f9c9 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -35,21 +35,29 @@ namespace sp = std::placeholders; EXTENSION_PROPERTY_SOURCE(App::GroupExtension, App::DocumentObjectExtension) -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::GroupExtensionPython, App::GroupExtension) // explicit template instantiation template class AppExport ExtensionPythonT>; -} +} // namespace App GroupExtension::GroupExtension() { initExtensionType(GroupExtension::getExtensionClassTypeId()); - - EXTENSION_ADD_PROPERTY_TYPE(Group,(nullptr),"Base",(App::PropertyType)(Prop_None),"List of referenced objects"); - EXTENSION_ADD_PROPERTY_TYPE(_GroupTouched, (false), "Base", - PropertyType(Prop_Hidden|Prop_Transient),0); + EXTENSION_ADD_PROPERTY_TYPE(Group, + (nullptr), + "Base", + (App::PropertyType)(Prop_None), + "List of referenced objects"); + + EXTENSION_ADD_PROPERTY_TYPE(_GroupTouched, + (false), + "Base", + PropertyType(Prop_Hidden | Prop_Transient), + 0); } GroupExtension::~GroupExtension() = default; @@ -57,7 +65,7 @@ GroupExtension::~GroupExtension() = default; DocumentObject* GroupExtension::addObject(const char* sType, const char* pObjectName) { DocumentObject* obj = getExtendedObject()->getDocument()->addObject(sType, pObjectName); - if(!allowObject(obj)) { + if (!allowObject(obj)) { getExtendedObject()->getDocument()->removeObject(obj->getNameInDocument()); return nullptr; } @@ -71,47 +79,55 @@ std::vector GroupExtension::addObject(DocumentObject* obj) return addObjects(vec); } -std::vector< DocumentObject* > GroupExtension::addObjects(std::vector< DocumentObject* > objs) { - +std::vector GroupExtension::addObjects(std::vector objs) +{ + std::vector added; std::vector grp = Group.getValues(); - for(auto obj : objs) { - - if(!allowObject(obj)) + for (auto obj : objs) { + + if (!allowObject(obj)) { continue; - - if (hasObject(obj)) + } + + if (hasObject(obj)) { continue; - - //only one group per object. Note that it is allowed to be in a group and geofeaturegroup. However, - //getGroupOfObject() returns only normal groups, no GeoFeatureGroups. Hence this works. - auto *group = App::GroupExtension::getGroupOfObject(obj); - if(group && group != getExtendedObject()) + } + + // only one group per object. Note that it is allowed to be in a group and geofeaturegroup. + // However, getGroupOfObject() returns only normal groups, no GeoFeatureGroups. Hence this + // works. + auto* group = App::GroupExtension::getGroupOfObject(obj); + if (group && group != getExtendedObject()) { group->getExtensionByType()->removeObject(obj); - - //if we are in a geofeaturegroup we need to ensure the object is too + } + + // if we are in a geofeaturegroup we need to ensure the object is too auto geogrp = GeoFeatureGroupExtension::getGroupOfObject(getExtendedObject()); auto objgrp = GeoFeatureGroupExtension::getGroupOfObject(obj); - if( geogrp != objgrp ) { - //what to do depends on if we are in geofeature group or not - if(geogrp) + if (geogrp != objgrp) { + // what to do depends on if we are in geofeature group or not + if (geogrp) { geogrp->getExtensionByType()->addObject(obj); - else + } + else { objgrp->getExtensionByType()->removeObject(obj); + } } - + grp.push_back(obj); added.push_back(obj); } - + Group.setValues(grp); - + return added; } -std::vector< DocumentObject* > GroupExtension::setObjects(std::vector< DocumentObject* > obj) { +std::vector GroupExtension::setObjects(std::vector obj) +{ - Group.setValues(std::vector< DocumentObject* > ()); + Group.setValues(std::vector()); return addObjects(obj); } @@ -121,26 +137,27 @@ std::vector GroupExtension::removeObject(DocumentObject* obj) return removeObjects(vec); } -std::vector< DocumentObject* > GroupExtension::removeObjects(std::vector< DocumentObject* > objs) { +std::vector GroupExtension::removeObjects(std::vector objs) +{ - const std::vector & grp = Group.getValues(); + const std::vector& grp = Group.getValues(); std::vector newGrp = grp; std::vector removed; std::vector::iterator end = newGrp.end(); - for(auto obj : objs) { - auto res = std::remove(newGrp.begin(), end, obj); - if(res != end) { - end = res; - removed.push_back(obj); - } + for (auto obj : objs) { + auto res = std::remove(newGrp.begin(), end, obj); + if (res != end) { + end = res; + removed.push_back(obj); + } } - + newGrp.erase(end, newGrp.end()); if (grp.size() != newGrp.size()) { - Group.setValues (newGrp); + Group.setValues(newGrp); } - + return removed; } @@ -150,7 +167,7 @@ void GroupExtension::removeObjectsFromDocument() // Remove the objects step by step because it can happen // that an object is part of several groups and thus a // double destruction could be possible - const std::vector & grp = Group.getValues(); + const std::vector& grp = Group.getValues(); removeObjectFromDocument(grp.front()); } } @@ -158,12 +175,14 @@ void GroupExtension::removeObjectsFromDocument() void GroupExtension::removeObjectFromDocument(DocumentObject* obj) { // check that object is not invalid - if (!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { return; + } // remove all children if (obj->hasExtension(GroupExtension::getExtensionClassTypeId())) { - GroupExtension *grp = static_cast(obj->getExtension(GroupExtension::getExtensionClassTypeId())); + GroupExtension* grp = static_cast( + obj->getExtension(GroupExtension::getExtensionClassTypeId())); // recursive call to remove all subgroups grp->removeObjectsFromDocument(); @@ -172,11 +191,12 @@ void GroupExtension::removeObjectFromDocument(DocumentObject* obj) getExtendedObject()->getDocument()->removeObject(obj->getNameInDocument()); } -DocumentObject *GroupExtension::getObject(const char *Name) const +DocumentObject* GroupExtension::getObject(const char* Name) const { DocumentObject* obj = getExtendedObject()->getDocument()->getObject(Name); - if (obj && hasObject(obj)) + if (obj && hasObject(obj)) { return obj; + } return nullptr; } @@ -190,22 +210,24 @@ bool GroupExtension::hasObject(const DocumentObject* obj, bool recursive) const const std::vector& grp = Group.getValues(); for (auto child : grp) { - if (!child) + if (!child) { continue; + } if (child == obj) { return true; } else if (child == getExtendedObject()) { - throw Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); + throw Base::RuntimeError( + "Cyclic dependencies detected: Search cannot be performed"); } - else if ( recursive && child->hasExtension(GroupExtension::getExtensionClassTypeId()) ) { - App::GroupExtension *subGroup = static_cast ( - child->getExtension(GroupExtension::getExtensionClassTypeId())); + else if (recursive && child->hasExtension(GroupExtension::getExtensionClassTypeId())) { + App::GroupExtension* subGroup = static_cast( + child->getExtension(GroupExtension::getExtensionClassTypeId())); std::vector history; history.push_back(this); - if (subGroup->recursiveHasObject (obj, subGroup, history)) { + if (subGroup->recursiveHasObject(obj, subGroup, history)) { return true; } } @@ -219,31 +241,36 @@ bool GroupExtension::hasObject(const DocumentObject* obj, bool recursive) const } } -bool GroupExtension::recursiveHasObject(const DocumentObject* obj, const GroupExtension* group, - std::vector< const GroupExtension* > history) const { +bool GroupExtension::recursiveHasObject(const DocumentObject* obj, + const GroupExtension* group, + std::vector history) const +{ - //the purpose is to prevent infinite recursion when groups form a cyclic graph. To do this - //we store every group we processed on the current leave of the tree, and if we reach an - //already processed group we know that it not really is a tree but a cycle. + // the purpose is to prevent infinite recursion when groups form a cyclic graph. To do this + // we store every group we processed on the current leave of the tree, and if we reach an + // already processed group we know that it not really is a tree but a cycle. history.push_back(this); - //we use hasObject with out recursion to allow override in derived classes - if(group->hasObject(obj, false)) + // we use hasObject with out recursion to allow override in derived classes + if (group->hasObject(obj, false)) { return true; + } - //we checked for the searched object already with hasObject and did not find it, now we need to - //do the same for all subgroups + // we checked for the searched object already with hasObject and did not find it, now we need to + // do the same for all subgroups for (auto child : group->Group.getValues()) { - if(!child) + if (!child) { continue; + } - if ( child->hasExtension(GroupExtension::getExtensionClassTypeId()) ) { + if (child->hasExtension(GroupExtension::getExtensionClassTypeId())) { auto ext = child->getExtensionByType(); - + if (std::find(history.begin(), history.end(), ext) != history.end()) { - throw Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); + throw Base::RuntimeError( + "Cyclic dependencies detected: Search cannot be performed"); } if (recursiveHasObject(obj, ext, history)) { @@ -259,7 +286,7 @@ bool GroupExtension::isChildOf(const GroupExtension* group, bool recursive) cons return group->hasObject(getExtendedObject(), recursive); } -const std::vector &GroupExtension::getObjects() const +const std::vector& GroupExtension::getObjects() const { return Group.getValues(); } @@ -269,8 +296,9 @@ std::vector GroupExtension::getObjectsOfType(const Base::Type& std::vector type; const std::vector& grp = Group.getValues(); for (auto it : grp) { - if (it->getTypeId().isDerivedFrom(typeId)) + if (it->getTypeId().isDerivedFrom(typeId)) { type.push_back(it); + } } return type; @@ -278,11 +306,12 @@ std::vector GroupExtension::getObjectsOfType(const Base::Type& int GroupExtension::countObjectsOfType(const Base::Type& typeId) const { - int type=0; + int type = 0; const std::vector& grp = Group.getValues(); for (auto it : grp) { - if ( it->getTypeId().isDerivedFrom(typeId)) + if (it->getTypeId().isDerivedFrom(typeId)) { type++; + } } return type; @@ -290,57 +319,63 @@ int GroupExtension::countObjectsOfType(const Base::Type& typeId) const DocumentObject* GroupExtension::getGroupOfObject(const DocumentObject* obj) { - //note that we return here only Groups, but nothing derived from it, e.g. no GeoFeatureGroups. - //That is important as there are clear differences between groups/geofeature groups (e.g. an object - //can be in only one group, and only one geofeaturegroup, however, it can be in both at the same time) + // note that we return here only Groups, but nothing derived from it, e.g. no GeoFeatureGroups. + // That is important as there are clear differences between groups/geofeature groups (e.g. an + // object can be in only one group, and only one geofeaturegroup, however, it can be in both at + // the same time) for (auto o : obj->getInList()) { - if (o->hasExtension(App::GroupExtension::getExtensionClassTypeId(), false)) + if (o->hasExtension(App::GroupExtension::getExtensionClassTypeId(), false)) { return o; - if (o->hasExtension(App::GroupExtensionPython::getExtensionClassTypeId(), false)) + } + if (o->hasExtension(App::GroupExtensionPython::getExtensionClassTypeId(), false)) { return o; + } } return nullptr; } -PyObject* GroupExtension::getExtensionPyObject() { +PyObject* GroupExtension::getExtensionPyObject() +{ - if (ExtensionPythonObject.is(Py::_None())){ + if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 auto grp = new GroupExtensionPy(this); - ExtensionPythonObject = Py::Object(grp,true); + ExtensionPythonObject = Py::Object(grp, true); } return Py::new_reference_to(ExtensionPythonObject); } -void GroupExtension::extensionOnChanged(const Property* p) { +void GroupExtension::extensionOnChanged(const Property* p) +{ + + // objects are only allowed in a single group. Note that this check must only be done for normal + // groups, not any derived classes + if ((this->getExtensionTypeId() == GroupExtension::getExtensionClassTypeId()) && p == &Group + && !Group.testStatus(Property::User3)) { + if (!getExtendedObject()->isRestoring() + && !getExtendedObject()->getDocument()->isPerformingTransaction()) { - //objects are only allowed in a single group. Note that this check must only be done for normal - //groups, not any derived classes - if((this->getExtensionTypeId() == GroupExtension::getExtensionClassTypeId()) - && p == &Group && !Group.testStatus(Property::User3)) - { - if(!getExtendedObject()->isRestoring() && - !getExtendedObject()->getDocument()->isPerformingTransaction()) { - bool error = false; auto corrected = Group.getValues(); - for(auto obj : Group.getValues()) { + for (auto obj : Group.getValues()) { - //we have already set the obj into the group, so in a case of multiple groups getGroupOfObject - //would return anyone of it and hence it is possible that we miss an error. We need a custom check + // we have already set the obj into the group, so in a case of multiple groups + // getGroupOfObject would return anyone of it and hence it is possible that we miss + // an error. We need a custom check auto list = obj->getInList(); for (auto in : list) { - if(in->hasExtension(App::GroupExtension::getExtensionClassTypeId(), false) && - in != getExtendedObject()) { + if (in->hasExtension(App::GroupExtension::getExtensionClassTypeId(), false) + && in != getExtendedObject()) { error = true; - corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), corrected.end()); + corrected.erase(std::remove(corrected.begin(), corrected.end(), obj), + corrected.end()); } } } - //if an error was found we need to correct the values and inform the user - if(error) { + // if an error was found we need to correct the values and inform the user + if (error) { Base::ObjectStatusLocker guard(Property::User3, &Group); Group.setValues(corrected); throw Base::RuntimeError("Object can only be in a single Group"); @@ -348,14 +383,14 @@ void GroupExtension::extensionOnChanged(const Property* p) { } } - if(p == &Group) { + if (p == &Group) { _Conns.clear(); - for(auto obj : Group.getValue()) { - if(obj && obj->isAttachedToDocument()) { - //NOLINTBEGIN - _Conns[obj] = obj->signalChanged.connect(std::bind( - &GroupExtension::slotChildChanged,this,sp::_1, sp::_2)); - //NOLINTEND + for (auto obj : Group.getValue()) { + if (obj && obj->isAttachedToDocument()) { + // NOLINTBEGIN + _Conns[obj] = obj->signalChanged.connect( + std::bind(&GroupExtension::slotChildChanged, this, sp::_1, sp::_2)); + // NOLINTEND } } } @@ -363,71 +398,87 @@ void GroupExtension::extensionOnChanged(const Property* p) { App::Extension::extensionOnChanged(p); } -void GroupExtension::slotChildChanged(const DocumentObject &obj, const Property &prop) { - if(&prop == &obj.Visibility) +void GroupExtension::slotChildChanged(const DocumentObject& obj, const Property& prop) +{ + if (&prop == &obj.Visibility) { _GroupTouched.touch(); + } } -bool GroupExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool /*transform*/, int depth) const +bool GroupExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool /*transform*/, + int depth) const { - const char *dot; - if(!subname || *subname==0) { + const char* dot; + if (!subname || *subname == 0) { auto obj = Base::freecad_dynamic_cast(getExtendedContainer()); ret = const_cast(obj); return true; } - dot=strchr(subname,'.'); - if(!dot) + dot = strchr(subname, '.'); + if (!dot) { return false; - if(subname[0]!='$') - ret = Group.findUsingMap(std::string(subname,dot)); - else{ - std::string name = std::string(subname+1,dot); - for(auto child : Group.getValues()) { - if(name == child->Label.getStrValue()){ + } + if (subname[0] != '$') { + ret = Group.findUsingMap(std::string(subname, dot)); + } + else { + std::string name = std::string(subname + 1, dot); + for (auto child : Group.getValues()) { + if (name == child->Label.getStrValue()) { ret = child; break; } } } - if(!ret) + if (!ret) { return false; - return ret->getSubObject(dot+1,pyObj,mat,true,depth+1); + } + return ret->getSubObject(dot + 1, pyObj, mat, true, depth + 1); } -bool GroupExtension::extensionGetSubObjects(std::vector &ret, int) const { - for(auto obj : Group.getValues()) { - if(obj && obj->isAttachedToDocument()) - ret.push_back(std::string(obj->getNameInDocument())+'.'); +bool GroupExtension::extensionGetSubObjects(std::vector& ret, int) const +{ + for (auto obj : Group.getValues()) { + if (obj && obj->isAttachedToDocument()) { + ret.push_back(std::string(obj->getNameInDocument()) + '.'); + } } return true; } -App::DocumentObjectExecReturn *GroupExtension::extensionExecute() { +App::DocumentObjectExecReturn* GroupExtension::extensionExecute() +{ // This touch property is for propagating changes to upper group _GroupTouched.touch(); return inherited::extensionExecute(); } -std::vector GroupExtension::getAllChildren() const { +std::vector GroupExtension::getAllChildren() const +{ std::vector res; std::set rset; - getAllChildren(res,rset); + getAllChildren(res, rset); return res; } -void GroupExtension::getAllChildren(std::vector &res, - std::set &rset) const +void GroupExtension::getAllChildren(std::vector& res, + std::set& rset) const { - for(auto obj : Group.getValues()) { - if(!obj || !obj->isAttachedToDocument()) + for (auto obj : Group.getValues()) { + if (!obj || !obj->isAttachedToDocument()) { continue; - if(!rset.insert(obj).second) + } + if (!rset.insert(obj).second) { continue; + } res.push_back(obj); - auto ext = obj->getExtensionByType(true,false); - if(ext) - ext->getAllChildren(res,rset); + auto ext = obj->getExtensionByType(true, false); + if (ext) { + ext->getAllChildren(res, rset); + } } } diff --git a/src/App/GroupExtension.h b/src/App/GroupExtension.h index 810ff0d410ae..4130023d23ef 100644 --- a/src/App/GroupExtension.h +++ b/src/App/GroupExtension.h @@ -35,7 +35,7 @@ namespace App class DocumentObjectGroup; class GroupExtensionPy; -class AppExport GroupExtension : public DocumentObjectExtension +class AppExport GroupExtension: public DocumentObjectExtension { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::GroupExtension); using inherited = DocumentObjectExtension; @@ -50,22 +50,25 @@ class AppExport GroupExtension : public DocumentObjectExtension /** Adds an object of \a sType with \a pObjectName to the document this group belongs to and * append it to this group as well. */ - virtual DocumentObject *addObject(const char* sType, const char* pObjectName); + virtual DocumentObject* addObject(const char* sType, const char* pObjectName); /* Adds the object \a obj to this group. Returns all objects that have been added. */ virtual std::vector addObject(DocumentObject* obj); /* Adds the objects \a objs to this group. Returns all objects that have been added. */ virtual std::vector addObjects(std::vector obj); - + /* Sets the objects in this group. Everything contained already will be removed first */ - virtual std::vector< DocumentObject* > setObjects(std::vector< DocumentObject* > obj); - + virtual std::vector setObjects(std::vector obj); + /*override this function if you want only special objects */ - virtual bool allowObject(DocumentObject* ) {return true;} - + virtual bool allowObject(DocumentObject*) + { + return true; + } + /** Removes an object from this group. Returns all objects that have been removed. */ virtual std::vector removeObject(DocumentObject* obj); @@ -75,16 +78,19 @@ class AppExport GroupExtension : public DocumentObjectExtension /** Removes all children objects from this group and the document. */ virtual void removeObjectsFromDocument(); - /** Returns the object of this group with \a Name. If the group doesn't have such an object 0 is returned. - * @note This method might return 0 even if the document this group belongs to contains an object with this name. + /** Returns the object of this group with \a Name. If the group doesn't have such an object 0 is + * returned. + * @note This method might return 0 even if the document this group belongs to contains an + * object with this name. */ - DocumentObject *getObject(const char* Name) const; + DocumentObject* getObject(const char* Name) const; /** * Checks whether the object \a obj is part of this group. * @param obj the object to check for. - * @param recursive if true check also if the obj is child of some sub group (default is false). + * @param recursive if true check also if the obj is child of some sub group (default is + * false). */ - virtual bool hasObject(const DocumentObject* obj, bool recursive=false) const; + virtual bool hasObject(const DocumentObject* obj, bool recursive = false) const; /** * Checks whether this group object is a child (or sub-child if enabled) * of the given group object. @@ -92,7 +98,7 @@ class AppExport GroupExtension : public DocumentObjectExtension bool isChildOf(const GroupExtension* group, bool recursive = true) const; /** Returns a list of all objects this group does have. */ - const std::vector &getObjects() const; + const std::vector& getObjects() const; /** Returns a list of all objects of \a typeId this group does have. */ std::vector getObjectsOfType(const Base::Type& typeId) const; @@ -100,36 +106,44 @@ class AppExport GroupExtension : public DocumentObjectExtension */ int countObjectsOfType(const Base::Type& typeId) const; /** Returns the object group of the document which the given object \a obj is part of. - * In case this object is not part of a group 0 is returned. - * @note This only returns objects that are normal groups, not any special derived type - * like GeoFeatureGroups or OriginGroups. To retrieve those please use their appropriate functions + * In case this object is not part of a group 0 is returned. + * @note This only returns objects that are normal groups, not any special derived type + * like GeoFeatureGroups or OriginGroups. To retrieve those please use their appropriate + * functions */ static DocumentObject* getGroupOfObject(const DocumentObject* obj); //@} - + PyObject* getExtensionPyObject() override; void extensionOnChanged(const Property* p) override; - bool extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const override; + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const override; - bool extensionGetSubObjects(std::vector &ret, int reason) const override; + bool extensionGetSubObjects(std::vector& ret, int reason) const override; - App::DocumentObjectExecReturn *extensionExecute() override; + App::DocumentObjectExecReturn* extensionExecute() override; std::vector getAllChildren() const; - void getAllChildren(std::vector &, std::set &) const; - + void getAllChildren(std::vector&, std::set&) const; + /// Properties PropertyLinkList Group; PropertyBool _GroupTouched; private: void removeObjectFromDocument(DocumentObject*); - // This function stores the already searched objects to prevent infinite recursion in case of a cyclic group graph - // It throws an exception of type Base::RuntimeError if a cyclic dependency is detected. - bool recursiveHasObject(const DocumentObject* obj, const GroupExtension* group, std::vector history) const; + // This function stores the already searched objects to prevent infinite recursion in case of a + // cyclic group graph It throws an exception of type Base::RuntimeError if a cyclic dependency + // is detected. + bool recursiveHasObject(const DocumentObject* obj, + const GroupExtension* group, + std::vector history) const; // for tracking children visibility void slotChildChanged(const App::DocumentObject&, const App::Property&); @@ -138,32 +152,35 @@ class AppExport GroupExtension : public DocumentObjectExtension template -class GroupExtensionPythonT : public ExtensionT { - +class GroupExtensionPythonT: public ExtensionT +{ + public: - GroupExtensionPythonT() = default; ~GroupExtensionPythonT() override = default; - - //override the documentobjectextension functions to make them available in python - bool allowObject(DocumentObject* obj) override { + + // override the documentobjectextension functions to make them available in python + bool allowObject(DocumentObject* obj) override + { Base::PyGILStateLocker locker; Py::Object pyobj = Py::asObject(obj->getPyObject()); EXTENSION_PROXY_ONEARG(allowObject, pyobj); - - if(result.isNone()) + + if (result.isNone()) { return ExtensionT::allowObject(obj); - - if(result.isBoolean()) + } + + if (result.isBoolean()) { return result.isTrue(); - + } + return false; }; }; using GroupExtensionPython = ExtensionPythonT>; -} //namespace App +} // namespace App -#endif // APP_GROUPEXTENSION_H +#endif // APP_GROUPEXTENSION_H diff --git a/src/App/GroupExtensionPy.xml b/src/App/GroupExtensionPy.xml index 5576a43407e1..5860051f6737 100644 --- a/src/App/GroupExtensionPy.xml +++ b/src/App/GroupExtensionPy.xml @@ -1,13 +1,13 @@ - diff --git a/src/App/GroupExtensionPyImp.cpp b/src/App/GroupExtensionPyImp.cpp index 5b2b118d3dec..a13fbd7f65a5 100644 --- a/src/App/GroupExtensionPyImp.cpp +++ b/src/App/GroupExtensionPyImp.cpp @@ -39,14 +39,15 @@ std::string GroupExtensionPy::representation() const return {""}; } -PyObject* GroupExtensionPy::newObject(PyObject *args) +PyObject* GroupExtensionPy::newObject(PyObject* args) { - char *sType,*sName=nullptr; - if (!PyArg_ParseTuple(args, "s|s", &sType,&sName)) + char *sType, *sName = nullptr; + if (!PyArg_ParseTuple(args, "s|s", &sType, &sName)) { return nullptr; + } - DocumentObject *object = getGroupExtensionPtr()->addObject(sType, sName); - if ( object ) { + DocumentObject* object = getGroupExtensionPtr()->addObject(sType, sName); + if (object) { return object->getPyObject(); } else { @@ -55,20 +56,24 @@ PyObject* GroupExtensionPy::newObject(PyObject *args) } } -PyObject* GroupExtensionPy::addObject(PyObject *args) +PyObject* GroupExtensionPy::addObject(PyObject* args) { - PyObject *object; - if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(object); - if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { + if (!docObj->getDocumentObjectPtr() + || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add an invalid object"); return nullptr; } - - if (docObj->getDocumentObjectPtr()->getDocument() != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add an object from another document to this group"); + + if (docObj->getDocumentObjectPtr()->getDocument() + != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot add an object from another document to this group"); return nullptr; } if (docObj->getDocumentObjectPtr() == this->getGroupExtensionPtr()->getExtendedObject()) { @@ -76,29 +81,34 @@ PyObject* GroupExtensionPy::addObject(PyObject *args) return nullptr; } if (docObj->getDocumentObjectPtr()->hasExtension(GroupExtension::getExtensionClassTypeId())) { - App::GroupExtension* docGrp = docObj->getDocumentObjectPtr()->getExtensionByType(); + App::GroupExtension* docGrp = + docObj->getDocumentObjectPtr()->getExtensionByType(); if (docGrp->hasObject(getGroupExtensionPtr()->getExtendedObject())) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add a group object to a child group"); + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot add a group object to a child group"); return nullptr; } } GroupExtension* grp = getGroupExtensionPtr(); - auto vec = grp->addObject(docObj->getDocumentObjectPtr()); + auto vec = grp->addObject(docObj->getDocumentObjectPtr()); Py::List list; - for (App::DocumentObject* obj : vec) + for (App::DocumentObject* obj : vec) { list.append(Py::asObject(obj->getPyObject())); + } return Py::new_reference_to(list); } -PyObject* GroupExtensionPy::addObjects(PyObject *args) { - - PyObject *object; - if (!PyArg_ParseTuple(args, "O", &object)) +PyObject* GroupExtensionPy::addObjects(PyObject* args) +{ + + PyObject* object; + if (!PyArg_ParseTuple(args, "O", &object)) { return nullptr; - + } + if (PyTuple_Check(object) || PyList_Check(object)) { Py::Sequence list(object); Py::Sequence::size_type size = list.size(); @@ -117,24 +127,27 @@ PyObject* GroupExtensionPy::addObjects(PyObject *args) { } GroupExtension* grp = getGroupExtensionPtr(); - auto vec = grp->addObjects(values); + auto vec = grp->addObjects(values); Py::List result; - for (App::DocumentObject* obj : vec) + for (App::DocumentObject* obj : vec) { result.append(Py::asObject(obj->getPyObject())); + } return Py::new_reference_to(result); } - + std::string error = std::string("type must be list of 'DocumentObject', not "); error += object->ob_type->tp_name; throw Base::TypeError(error); } -PyObject* GroupExtensionPy::setObjects(PyObject *args) { +PyObject* GroupExtensionPy::setObjects(PyObject* args) +{ - PyObject *object; - if (!PyArg_ParseTuple(args, "O", &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O", &object)) { return nullptr; + } if (PyTuple_Check(object) || PyList_Check(object)) { Py::Sequence list(object); @@ -154,32 +167,37 @@ PyObject* GroupExtensionPy::setObjects(PyObject *args) { } GroupExtension* grp = getGroupExtensionPtr(); - auto vec = grp->setObjects(values); + auto vec = grp->setObjects(values); Py::List result; - for (App::DocumentObject* obj : vec) + for (App::DocumentObject* obj : vec) { result.append(Py::asObject(obj->getPyObject())); + } return Py::new_reference_to(result); } - + std::string error = std::string("type must be list of 'DocumentObject', not "); error += object->ob_type->tp_name; throw Base::TypeError(error); } -PyObject* GroupExtensionPy::removeObject(PyObject *args) +PyObject* GroupExtensionPy::removeObject(PyObject* args) { - PyObject *object; - if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(object); - if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { + if (!docObj->getDocumentObjectPtr() + || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot remove an invalid object"); return nullptr; } - if (docObj->getDocumentObjectPtr()->getDocument() != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot remove an object from another document from this group"); + if (docObj->getDocumentObjectPtr()->getDocument() + != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot remove an object from another document from this group"); return nullptr; } @@ -187,18 +205,21 @@ PyObject* GroupExtensionPy::removeObject(PyObject *args) auto vec = grp->removeObject(docObj->getDocumentObjectPtr()); Py::List list; - for (App::DocumentObject* obj : vec) + for (App::DocumentObject* obj : vec) { list.append(Py::asObject(obj->getPyObject())); + } return Py::new_reference_to(list); } -PyObject* GroupExtensionPy::removeObjects(PyObject *args) { +PyObject* GroupExtensionPy::removeObjects(PyObject* args) +{ - PyObject *object; - if (!PyArg_ParseTuple(args, "O", &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O", &object)) { return nullptr; - + } + if (PyTuple_Check(object) || PyList_Check(object)) { Py::Sequence list(object); Py::Sequence::size_type size = list.size(); @@ -217,10 +238,11 @@ PyObject* GroupExtensionPy::removeObjects(PyObject *args) { } GroupExtension* grp = getGroupExtensionPtr(); - auto vec = grp->removeObjects(values); + auto vec = grp->removeObjects(values); Py::List result; - for (App::DocumentObject* obj : vec) + for (App::DocumentObject* obj : vec) { result.append(Py::asObject(obj->getPyObject())); + } return Py::new_reference_to(result); } @@ -230,44 +252,56 @@ PyObject* GroupExtensionPy::removeObjects(PyObject *args) { throw Base::TypeError(error); } -PyObject* GroupExtensionPy::removeObjectsFromDocument(PyObject *args) +PyObject* GroupExtensionPy::removeObjectsFromDocument(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } getGroupExtensionPtr()->removeObjectsFromDocument(); Py_Return; } -PyObject* GroupExtensionPy::getObject(PyObject *args) +PyObject* GroupExtensionPy::getObject(PyObject* args) { char* pcName; - if (!PyArg_ParseTuple(args, "s", &pcName)) + if (!PyArg_ParseTuple(args, "s", &pcName)) { return nullptr; + } DocumentObject* obj = getGroupExtensionPtr()->getObject(pcName); - if ( obj ) { + if (obj) { return obj->getPyObject(); - } else { + } + else { Py_Return; } } -PyObject* GroupExtensionPy::hasObject(PyObject *args) +PyObject* GroupExtensionPy::hasObject(PyObject* args) { - PyObject *object; - PyObject *recursivePy = Py_False; - if (!PyArg_ParseTuple(args, "O!|O!", &(DocumentObjectPy::Type), &object, &PyBool_Type, &recursivePy)) + PyObject* object; + PyObject* recursivePy = Py_False; + if (!PyArg_ParseTuple(args, + "O!|O!", + &(DocumentObjectPy::Type), + &object, + &PyBool_Type, + &recursivePy)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(object); bool recursive = Base::asBoolean(recursivePy); - if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { + if (!docObj->getDocumentObjectPtr() + || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check an invalid object"); return nullptr; } - if (docObj->getDocumentObjectPtr()->getDocument() != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot check an object from another document with this group"); + if (docObj->getDocumentObjectPtr()->getDocument() + != getGroupExtensionPtr()->getExtendedObject()->getDocument()) { + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot check an object from another document with this group"); return nullptr; } @@ -275,7 +309,7 @@ PyObject* GroupExtensionPy::hasObject(PyObject *args) return PyBool_FromLong(v ? 1 : 0); } -PyObject *GroupExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* GroupExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/App/ImagePlane.cpp b/src/App/ImagePlane.cpp index 9d8b8133ba19..120575871e73 100644 --- a/src/App/ImagePlane.cpp +++ b/src/App/ImagePlane.cpp @@ -32,9 +32,9 @@ PROPERTY_SOURCE(Image::ImagePlane, App::GeoFeature) ImagePlane::ImagePlane() { - ADD_PROPERTY_TYPE( ImageFile,(nullptr) , "ImagePlane",App::Prop_None,"File of the image"); - ADD_PROPERTY_TYPE( XSize, (100), "ImagePlane",App::Prop_None,"Size of a pixel in X"); - ADD_PROPERTY_TYPE( YSize, (100), "ImagePlane",App::Prop_None,"Size of a pixel in Y"); + ADD_PROPERTY_TYPE(ImageFile, (nullptr), "ImagePlane", App::Prop_None, "File of the image"); + ADD_PROPERTY_TYPE(XSize, (100), "ImagePlane", App::Prop_None, "Size of a pixel in X"); + ADD_PROPERTY_TYPE(YSize, (100), "ImagePlane", App::Prop_None, "Size of a pixel in Y"); } int ImagePlane::getXSizeInPixel() diff --git a/src/App/ImagePlane.h b/src/App/ImagePlane.h index 4afffe1d9c64..ff57e2c84419 100644 --- a/src/App/ImagePlane.h +++ b/src/App/ImagePlane.h @@ -30,7 +30,7 @@ namespace Image { -class AppExport ImagePlane : public App::GeoFeature +class AppExport ImagePlane: public App::GeoFeature { PROPERTY_HEADER_WITH_OVERRIDE(Image::ImagePlane); @@ -40,24 +40,25 @@ class AppExport ImagePlane : public App::GeoFeature ~ImagePlane() override = default; App::PropertyFileIncluded ImageFile; - App::PropertyLength XSize; - App::PropertyLength YSize; + App::PropertyLength XSize; + App::PropertyLength YSize; int getXSizeInPixel(); int getYSizeInPixel(); void setXSizeInPixel(int); void setYSizeInPixel(int); - double XPixelsPerMeter{1000.0}; - double YPixelsPerMeter{1000.0}; + double XPixelsPerMeter {1000.0}; + double YPixelsPerMeter {1000.0}; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderImagePlane"; } }; -} //namespace Image +} // namespace Image -#endif // App_ImagePlane_H +#endif // App_ImagePlane_H diff --git a/src/App/IndexedName.cpp b/src/App/IndexedName.cpp index ebe9bf2ddbc6..86fd2234b6d5 100644 --- a/src/App/IndexedName.cpp +++ b/src/App/IndexedName.cpp @@ -26,8 +26,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include "IndexedName.h" @@ -37,17 +37,17 @@ using namespace Data; /// Check whether the input character is an underscore or an ASCII letter a-Z or A-Z inline bool isInvalidChar(char test) { - return test != '_' && (test < 'a' || test > 'z' ) && (test < 'A' || test > 'Z'); + return test != '_' && (test < 'a' || test > 'z') && (test < 'A' || test > 'Z'); } /// Get the integer suffix of name. Returns a tuple of (suffix, suffixPosition). Calling code -/// should check to ensure that suffixPosition is not equal to nameLength (in which case there was no -/// suffix). +/// should check to ensure that suffixPosition is not equal to nameLength (in which case there was +/// no suffix). /// /// \param name The name to check /// \param nameLength The length of the string in name /// \returns An integer pair of the suffix itself and the position of that suffix in name -std::pair getIntegerSuffix(const char *name, int nameLength) +std::pair getIntegerSuffix(const char* name, int nameLength) { int suffixPosition {nameLength - 1}; @@ -68,11 +68,10 @@ std::pair getIntegerSuffix(const char *name, int nameLength) return std::make_pair(suffix, suffixPosition); } -void IndexedName::set( - const char* name, - int length, - const std::vector& allowedNames, - bool allowOthers) +void IndexedName::set(const char* name, + int length, + const std::vector& allowedNames, + bool allowOthers) { // Storage for names that we weren't given external storage for static std::unordered_set NameSet; @@ -90,22 +89,22 @@ void IndexedName::set( // underscore. If any other character appears, reject the entire string. // When we support C++20 we can use std::span<> to eliminate the clang-tidy warning // NOLINTNEXTLINE cppcoreguidelines-pro-bounds-pointer-arithmetic - if (std::any_of(name, name+suffixPosition, isInvalidChar)) { + if (std::any_of(name, name + suffixPosition, isInvalidChar)) { this->type = ""; return; } - // If a list of allowedNames was provided, see if our set name matches one of those allowedNames: if it - // does, reference that memory location and return. - for (const auto *typeName : allowedNames) { + // If a list of allowedNames was provided, see if our set name matches one of those + // allowedNames: if it does, reference that memory location and return. + for (const auto* typeName : allowedNames) { if (std::strncmp(name, typeName, suffixPosition) == 0) { this->type = typeName; return; } } - // If the type was NOT in the list of allowedNames, but the caller has set the allowOthers flag to - // true, then add the new type to the static NameSet (if it is not already there). + // If the type was NOT in the list of allowedNames, but the caller has set the allowOthers flag + // to true, then add the new type to the static NameSet (if it is not already there). if (allowOthers) { auto res = NameSet.insert(ByteArray(QByteArray::fromRawData(name, suffixPosition))); if (res.second /*The insert succeeded (the type was new)*/) { diff --git a/src/App/IndexedName.h b/src/App/IndexedName.h index 7b152a2506da..c2504cbaa3b2 100644 --- a/src/App/IndexedName.h +++ b/src/App/IndexedName.h @@ -40,21 +40,21 @@ namespace Data { -/// The IndexedName class provides a very memory-efficient data structure to hold a name and an index -/// value, and to perform various comparisons and validations of those values. The name must only -/// consist of upper- and lower-case ASCII characters and the underscore ('_') character. The index -/// must be a positive integer. The string representation of this IndexedName is the name followed by -/// the index, with no spaces between: an IndexedName may be constructed from this string. For -/// example "EDGE1" or "FACE345" might be the names of elements that use an IndexedName. If there is -/// then an "EDGE2", only a pointer to the original stored name "EDGE" is retained. +/// The IndexedName class provides a very memory-efficient data structure to hold a name and an +/// index value, and to perform various comparisons and validations of those values. The name must +/// only consist of upper- and lower-case ASCII characters and the underscore ('_') character. The +/// index must be a positive integer. The string representation of this IndexedName is the name +/// followed by the index, with no spaces between: an IndexedName may be constructed from this +/// string. For example "EDGE1" or "FACE345" might be the names of elements that use an IndexedName. +/// If there is then an "EDGE2", only a pointer to the original stored name "EDGE" is retained. /// /// The memory efficiency of the class comes from re-using the same character storage for names that /// match, while retaining their differing indices. This is achieved by either using user-provided /// const char * names (provided as a list of typeNames and presumed to never be deallocated), or by /// maintaining an internal list of names that have been used before, and can be re-used later. -class AppExport IndexedName { +class AppExport IndexedName +{ public: - /// Construct from a name and an optional index. If the name contains an index it is read, but /// is used as the index *only* if _index parameter is unset. If the _index parameter is given /// it overrides any trailing integer in the name. Index must be positive, and name must contain @@ -64,7 +64,7 @@ class AppExport IndexedName { /// \param name The new name - ASCII letters and underscores only, with optional integer suffix. /// This memory will be copied into a new internal storage location and need not be persistent. /// \param _index The new index - if provided, it overrides any suffix provided by name - explicit IndexedName(const char *name = nullptr, int _index = 0) + explicit IndexedName(const char* name = nullptr, int _index = 0) : index(0) { assert(_index >= 0); @@ -93,9 +93,11 @@ class AppExport IndexedName { /// \param allowOthers Whether a name not in allowedTypeNames is permitted. If true (the /// default) then a name not in allowedTypeNames is added to a static internal storage vector /// so that it can be re-used later without additional memory allocation. - IndexedName(const char *name, - const std::vector & allowedTypeNames, - bool allowOthers=true) : type(""), index(0) + IndexedName(const char* name, + const std::vector& allowedTypeNames, + bool allowOthers = true) + : type("") + , index(0) { set(name, -1, allowedTypeNames, allowOthers); } @@ -105,7 +107,9 @@ class AppExport IndexedName { /// is made. /// /// \param data The QByteArray to copy the data from - explicit IndexedName(const QByteArray & data) : type(""), index(0) + explicit IndexedName(const QByteArray& data) + : type("") + , index(0) { set(data.constData(), data.size()); } @@ -117,8 +121,9 @@ class AppExport IndexedName { /// \param name The name of the object. This memory is NOT copied and must be persistent. /// \param index A positive, non-zero integer /// \return An IndexedName with the given name and index, re-using the existing memory for name - static IndexedName fromConst(const char *name, int index) { - assert (index >= 0); + static IndexedName fromConst(const char* name, int index) + { + assert(index >= 0); IndexedName res; res.type = name; res.index = index; @@ -130,7 +135,7 @@ class AppExport IndexedName { /// /// \param buffer A (possibly non-empty) string buffer to append the name to. /// \return A const char pointer to the name we appended to the buffer. - const char * appendToStringBuffer(std::string & buffer) const + const char* appendToStringBuffer(std::string& buffer) const { // Note! buffer is not cleared on purpose. std::size_t offset = buffer.size(); @@ -153,7 +158,7 @@ class AppExport IndexedName { /// An indexedName is represented as the simple concatenation of the name and its index, e.g. /// "EDGE1" or "FACE42". - friend std::ostream & operator<<(std::ostream & stream, const IndexedName & indexedName) + friend std::ostream& operator<<(std::ostream& stream, const IndexedName& indexedName) { stream << indexedName.type; if (indexedName.index > 0) { @@ -163,15 +168,14 @@ class AppExport IndexedName { } /// True only if both the name and index compare exactly equal. - bool operator==(const IndexedName & other) const + bool operator==(const IndexedName& other) const { return this->index == other.index - && (this->type == other.type - || std::strcmp(this->type, other.type)==0); + && (this->type == other.type || std::strcmp(this->type, other.type) == 0); } /// Increments the index by the given offset. Does not affect the text part of the name. - IndexedName & operator+=(int offset) + IndexedName& operator+=(int offset) { this->index += offset; assert(this->index >= 0); @@ -179,7 +183,7 @@ class AppExport IndexedName { } /// Pre-increment operator: increases the index of this element by one. - IndexedName & operator++() + IndexedName& operator++() { ++this->index; return *this; @@ -187,7 +191,7 @@ class AppExport IndexedName { /// Pre-decrement operator: decreases the index of this element by one. Must not make the index /// negative (only checked when compiled in debug mode). - IndexedName & operator--() + IndexedName& operator--() { --this->index; assert(this->index >= 0); @@ -195,13 +199,13 @@ class AppExport IndexedName { } /// True if either the name or the index compare not equal. - bool operator!=(const IndexedName & other) const + bool operator!=(const IndexedName& other) const { return !(this->operator==(other)); } /// Equivalent to C++20's operator <=> - int compare(const IndexedName & other) const + int compare(const IndexedName& other) const { int res = std::strcmp(this->type, other.type); if (res != 0) { @@ -218,7 +222,7 @@ class AppExport IndexedName { /// Provided to enable sorting operations: the comparison is first lexicographical for the text /// element of the names, then numerical for the indices. - bool operator<(const IndexedName & other) const + bool operator<(const IndexedName& other) const { return compare(other) < 0; } @@ -235,25 +239,41 @@ class AppExport IndexedName { } /// Get a pointer to text part of the name - does NOT make a copy, returns direct memory access - const char * getType() const { return this->type; } + const char* getType() const + { + return this->type; + } /// Get the numerical part of the name - int getIndex() const { return this->index; } + int getIndex() const + { + return this->index; + } /// Set the numerical part of the name (note that there is no equivalent function to allow /// changing the text part of the name, which is immutable once created). /// /// \param input The new index. Must be a positive non-zero integer - void setIndex(int input) { assert(input>=0); this->index = input; } + void setIndex(int input) + { + assert(input >= 0); + this->index = input; + } /// A name is considered "null" if its text component is an empty string. // When we support C++20 we can use std::span<> to eliminate the clang-tidy warning // NOLINTNEXTLINE cppcoreguidelines-pro-bounds-pointer-arithmetic - bool isNull() const { return this->type[0] == '\0'; } + bool isNull() const + { + return this->type[0] == '\0'; + } /// Boolean conversion provides the opposite of isNull(), yielding true when the text part of /// the name is NOT the empty string. - explicit operator bool() const { return !isNull(); } + explicit operator bool() const + { + return !isNull(); + } protected: /// Apply the IndexedName rules and either store the characters of a new type or a reference to @@ -268,13 +288,13 @@ class AppExport IndexedName { /// \param allowOthers If true (the default), then if name is not in allowedNames it is allowed, /// and it is added to internal storage (making a copy of the name if this is its first /// occurrence). - void set(const char *name, + void set(const char* name, int length = -1, - const std::vector & allowedNames = {}, + const std::vector& allowedNames = {}, bool allowOthers = true); private: - const char * type; + const char* type; int index; }; @@ -285,13 +305,13 @@ class AppExport IndexedName { struct ByteArray { explicit ByteArray(QByteArray other) - :bytes(std::move(other)) + : bytes(std::move(other)) {} ByteArray(const ByteArray& other) = default; ByteArray(ByteArray&& other) noexcept - :bytes(std::move(other.bytes)) + : bytes(std::move(other.bytes)) {} ~ByteArray() = default; @@ -304,17 +324,19 @@ struct ByteArray bytes = copy; } - bool operator==(const ByteArray& other) const { + bool operator==(const ByteArray& other) const + { return bytes == other.bytes; } - ByteArray &operator=(const ByteArray & other) { + ByteArray& operator=(const ByteArray& other) + { bytes.clear(); bytes.append(other.bytes.constData(), other.bytes.size()); return *this; } - ByteArray &operator= (ByteArray&& other) noexcept + ByteArray& operator=(ByteArray&& other) noexcept { bytes = std::move(other.bytes); return *this; @@ -337,6 +359,6 @@ struct ByteArrayHasher } }; -} +} // namespace Data -#endif // APP_INDEXEDNAME_H +#endif // APP_INDEXEDNAME_H diff --git a/src/App/InventorObject.cpp b/src/App/InventorObject.cpp index eded2a6f5740..255baee05279 100644 --- a/src/App/InventorObject.cpp +++ b/src/App/InventorObject.cpp @@ -32,10 +32,10 @@ using namespace App; PROPERTY_SOURCE(App::InventorObject, App::GeoFeature) -InventorObject::InventorObject() +InventorObject::InventorObject() { - ADD_PROPERTY_TYPE(Buffer,(""),"",Prop_None,"String buffer with a scene graph"); - ADD_PROPERTY_TYPE(FileName,(""),"",Prop_None,"Path to an Inventor file"); + ADD_PROPERTY_TYPE(Buffer, (""), "", Prop_None, "String buffer with a scene graph"); + ADD_PROPERTY_TYPE(FileName, (""), "", Prop_None, "Path to an Inventor file"); } InventorObject::~InventorObject() = default; @@ -45,11 +45,11 @@ short InventorObject::mustExecute() const return 0; } -PyObject *InventorObject::getPyObject() +PyObject* InventorObject::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); + PythonObject = Py::Object(new DocumentObjectPy(this), true); } - return Py::new_reference_to(PythonObject); + return Py::new_reference_to(PythonObject); } diff --git a/src/App/InventorObject.h b/src/App/InventorObject.h index af0c9825acab..3fe6d7d7701e 100644 --- a/src/App/InventorObject.h +++ b/src/App/InventorObject.h @@ -31,7 +31,7 @@ namespace App { -class AppExport InventorObject : public GeoFeature +class AppExport InventorObject: public GeoFeature { PROPERTY_HEADER_WITH_OVERRIDE(App::InventorObject); @@ -41,20 +41,22 @@ class AppExport InventorObject : public GeoFeature ~InventorObject() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderInventorObject"; } - DocumentObjectExecReturn *execute() override { + DocumentObjectExecReturn* execute() override + { return DocumentObject::StdReturn; } short mustExecute() const override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; PropertyString Buffer; PropertyString FileName; }; -} //namespace App +} // namespace App -#endif // APP_INVENTOROBJECT_H +#endif // APP_INVENTOROBJECT_H diff --git a/src/App/License.h b/src/App/License.h index b16c2b725278..a07e72274d83 100644 --- a/src/App/License.h +++ b/src/App/License.h @@ -75,6 +75,6 @@ int constexpr findLicense(const char* identifier) } return -1; } -}// namespace App +} // namespace App -#endif// APP_LICENSE_H +#endif // APP_LICENSE_H diff --git a/src/App/MappedElement.cpp b/src/App/MappedElement.cpp index 137c0e888378..7b69e35c709c 100644 --- a/src/App/MappedElement.cpp +++ b/src/App/MappedElement.cpp @@ -24,8 +24,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include "DocumentObject.h" @@ -164,9 +164,12 @@ bool ElementNameComparator::operator()(const MappedName& leftName, return leftName.size() < rightName.size(); } -HistoryItem::HistoryItem(App::DocumentObject *obj, const Data::MappedName &name) - :obj(obj),tag(0),element(name) +HistoryItem::HistoryItem(App::DocumentObject* obj, const Data::MappedName& name) + : obj(obj) + , tag(0) + , element(name) { - if(obj) + if (obj) { tag = obj->getID(); + } } diff --git a/src/App/MappedElement.h b/src/App/MappedElement.h index 8c4901668617..4880354592b0 100644 --- a/src/App/MappedElement.h +++ b/src/App/MappedElement.h @@ -46,13 +46,13 @@ struct AppExport MappedElement MappedElement() = default; MappedElement(const IndexedName& idx, MappedName n) - : index(idx), - name(std::move(n)) + : index(idx) + , name(std::move(n)) {} MappedElement(MappedName n, const IndexedName& idx) - : index(idx), - name(std::move(n)) + : index(idx) + , name(std::move(n)) {} ~MappedElement() = default; @@ -60,8 +60,8 @@ struct AppExport MappedElement MappedElement(const MappedElement& other) = default; MappedElement(MappedElement&& other) noexcept - : index(other.index), - name(std::move(other.name)) + : index(other.index) + , name(std::move(other.name)) {} MappedElement& operator=(MappedElement&& other) noexcept @@ -99,16 +99,18 @@ struct AppExport MappedElement } }; -struct AppExport HistoryItem { - App::DocumentObject *obj; +struct AppExport HistoryItem +{ + App::DocumentObject* obj; long tag; Data::MappedName element; Data::IndexedName index; std::vector intermediates; - HistoryItem(App::DocumentObject *obj, const Data::MappedName &name); + HistoryItem(App::DocumentObject* obj, const Data::MappedName& name); }; -struct AppExport ElementNameComparator { +struct AppExport ElementNameComparator +{ /** Comparison function to make topo name more stable * * The sorting decomposes the name into either of the following two forms @@ -121,10 +123,10 @@ struct AppExport ElementNameComparator { * The reason for this is to prevent names with bigger digits (which usually means * they come later in history) from coming earlier when sorting. */ - bool operator()(const MappedName & leftName, const MappedName & rightName) const; + bool operator()(const MappedName& leftName, const MappedName& rightName) const; }; -}// namespace Data +} // namespace Data -#endif// APP_MAPPED_ELEMENT_H +#endif // APP_MAPPED_ELEMENT_H diff --git a/src/App/MappedName.cpp b/src/App/MappedName.cpp index 968bfd48504a..2f00e75335a3 100644 --- a/src/App/MappedName.cpp +++ b/src/App/MappedName.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "MappedName.h" @@ -34,13 +34,15 @@ #include -FC_LOG_LEVEL_INIT("MappedName", true, 2);// NOLINT +FC_LOG_LEVEL_INIT("MappedName", true, 2); // NOLINT -namespace Data { +namespace Data +{ void MappedName::compact() const { - auto self = const_cast(this); //FIXME this is a workaround for a single call in ElementMap::addName() + auto self = const_cast( + this); // FIXME this is a workaround for a single call in ElementMap::addName() if (this->raw) { self->data = QByteArray(self->data.constData(), self->data.size()); @@ -49,8 +51,12 @@ void MappedName::compact() const } -int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* postfixOut, - char* typeOut, bool negative, bool recursive) const +int MappedName::findTagInElementName(long* tagOut, + int* lenOut, + std::string* postfixOut, + char* typeOut, + bool negative, + bool recursive) const { bool hex = true; int pos = this->rfind(POSTFIX_TAG); @@ -61,7 +67,7 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos // | // pos - if(pos < 0) { + if (pos < 0) { pos = this->rfind(POSTFIX_DECIMAL_TAG); if (pos < 0) { return -1; @@ -77,7 +83,7 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos char eof = 0; int size {0}; - const char * nameAsChars = this->toConstString(offset, size); + const char* nameAsChars = this->toConstString(offset, size); // check if the number followed by the tagPosfix is negative bool isNegative = (nameAsChars[0] == '-'); @@ -89,7 +95,8 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos if (!hex) { // no hex is an older version of the encoding scheme iss >> _tag >> sep; - } else { + } + else { // The purpose of tagOut postfixOut is to encode one model operation. The // 'tagOut' field is used to record the own object ID of that model shape, // and the 'lenOut' field indicates the length of the operation codes @@ -148,13 +155,13 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos } if (hex) { - if (pos-_len < 0) { + if (pos - _len < 0) { return -1; } if ((_len != 0) && recursive && (tagOut || lenOut)) { // in case of recursive tagOut postfixOut (used by hierarchy element // map), look for any embedded tagOut postfixOut - int next = MappedName::fromRawData(*this, pos-_len, _len).rfind(POSTFIX_TAG); + int next = MappedName::fromRawData(*this, pos - _len, _len).rfind(POSTFIX_TAG); if (next >= 0) { next += pos - _len; // #94;:G0;XTR;:H19:8,F;:H1a,F;BND:-1:0;:H1b:10,F @@ -174,7 +181,7 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos .find(ELEMENT_MAP_PREFIX); } if (end >= 0) { - end += next+1; + end += next + 1; // #94;:G0;XTR;:H19:8,F;:H1a,F;BND:-1:0;:H1b:10,F // ^ // | @@ -183,7 +190,8 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos // #94;:G0;XTR;:H19:8,F;:H1a,F;BND:-1:0;:H1b:10,F // | | // -- lenOut -- - } else { + } + else { _len = 0; } } @@ -196,28 +204,28 @@ int MappedName::findTagInElementName(long* tagOut, int* lenOut, std::string* pos // ----------- lenOut ----------- _len = pos - _len; } - if(typeOut) { + if (typeOut) { *typeOut = tp; } - if(tagOut) { + if (tagOut) { if (_tag == 0 && recursive) { return MappedName(*this, 0, _len) .findTagInElementName(tagOut, lenOut, postfixOut, typeOut, negative); } - if(_tag>0 || negative) { + if (_tag > 0 || negative) { *tagOut = _tag; } else { *tagOut = -_tag; } } - if(lenOut) { + if (lenOut) { *lenOut = _len; } - if(postfixOut) { + if (postfixOut) { *postfixOut = this->toString(pos); } return pos; } -} +} // namespace Data diff --git a/src/App/MappedName.h b/src/App/MappedName.h index 93c79682b67f..b7df053cc489 100644 --- a/src/App/MappedName.h +++ b/src/App/MappedName.h @@ -415,7 +415,7 @@ class AppExport MappedName } - if (startPosition < other.data.size())// if starting inside data + if (startPosition < other.data.size()) // if starting inside data { int count = size; // make sure count doesn't exceed data size and end up in postfix @@ -436,7 +436,7 @@ class AppExport MappedName startPosition = 0; size -= count; } - else// else starting inside postfix + else // else starting inside postfix { startPosition -= other.data.size(); } @@ -879,7 +879,8 @@ class AppExport MappedName return false; } return startsWith( - QByteArray::fromRawData(searchTarget, static_cast(qstrlen(searchTarget))), offset); + QByteArray::fromRawData(searchTarget, static_cast(qstrlen(searchTarget))), + offset); } /// Returns true if this MappedName starts with the search target. If there is a postfix, only @@ -902,15 +903,18 @@ class AppExport MappedName /// \param lenOut: optional pointer to receive the length field after the tagOut field. /// This gives the length of the previous hashed element name starting /// from the beginning of the give element name. - /// \param postfixOut: optional pointer to receive the postfixOut starting at the found tagOut field. - /// \param typeOut: optional pointer to receive the element typeOut character - /// \param negative: return negative tagOut as it is. If disabled, then always return positive tagOut. + /// \param postfixOut: optional pointer to receive the postfixOut starting at the found tagOut + /// field. \param typeOut: optional pointer to receive the element typeOut character \param + /// negative: return negative tagOut as it is. If disabled, then always return positive tagOut. /// Negative tagOut is sometimes used for element disambiguation. /// \param recursive: recursively find the last non-zero tagOut /// /// \return Return the end position of the tagOut field, or return -1 if not found. - int findTagInElementName(long* tagOut = nullptr, int* lenOut = nullptr, std::string* postfixOut = nullptr, - char* typeOut = nullptr, bool negative = false, + int findTagInElementName(long* tagOut = nullptr, + int* lenOut = nullptr, + std::string* postfixOut = nullptr, + char* typeOut = nullptr, + bool negative = false, bool recursive = true) const; /// Get a hash for this MappedName @@ -1043,7 +1047,7 @@ struct MappedNameRef // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) -}// namespace Data +} // namespace Data -#endif// APP_MAPPED_NAME_H +#endif // APP_MAPPED_NAME_H diff --git a/src/App/MaterialObject.cpp b/src/App/MaterialObject.cpp index 60c4f2ee1ea7..da866b7835fa 100644 --- a/src/App/MaterialObject.cpp +++ b/src/App/MaterialObject.cpp @@ -33,20 +33,22 @@ PROPERTY_SOURCE(App::MaterialObject, App::DocumentObject) MaterialObject::MaterialObject() { - ADD_PROPERTY_TYPE(Material,(),"Material",Prop_None,"Material key/value map"); - + ADD_PROPERTY_TYPE(Material, (), "Material", Prop_None, "Material key/value map"); } // Python feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(App::MaterialObjectPython, App::MaterialObject) -template<> const char* App::MaterialObjectPython::getViewProviderName() const { +template<> +const char* App::MaterialObjectPython::getViewProviderName() const +{ return "Gui::ViewProviderMaterialObjectPython"; } /// @endcond // explicit template instantiation template class AppExport FeaturePythonT; -} +} // namespace App diff --git a/src/App/MaterialObject.h b/src/App/MaterialObject.h index 177a35764e97..ad0fed4c0670 100644 --- a/src/App/MaterialObject.h +++ b/src/App/MaterialObject.h @@ -31,7 +31,7 @@ namespace App { -class AppExport MaterialObject : public DocumentObject +class AppExport MaterialObject: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::MaterialObject); @@ -43,16 +43,16 @@ class AppExport MaterialObject : public DocumentObject /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderMaterialObject"; } - }; using MaterialObjectPython = App::FeaturePythonT; -} //namespace App +} // namespace App -#endif // APP_MaterialObject_H +#endif // APP_MaterialObject_H diff --git a/src/App/MeasureManager.cpp b/src/App/MeasureManager.cpp index 825cbc63a99f..d6b4c07a81f1 100644 --- a/src/App/MeasureManager.cpp +++ b/src/App/MeasureManager.cpp @@ -28,179 +28,208 @@ #include "MeasureManager.h" -namespace App { +namespace App +{ - std::vector MeasureManager::_mMeasureHandlers; - std::vector MeasureManager::_mMeasureTypes; +std::vector MeasureManager::_mMeasureHandlers; +std::vector MeasureManager::_mMeasureTypes; - MeasureManager::MeasureManager() - { - // Constructor implementation - } +MeasureManager::MeasureManager() +{ + // Constructor implementation +} - void MeasureManager::addMeasureHandler(const char* module, MeasureTypeMethod typeCb) { - _mMeasureHandlers.emplace_back(MeasureHandler{module, typeCb}); - } +void MeasureManager::addMeasureHandler(const char* module, MeasureTypeMethod typeCb) +{ + _mMeasureHandlers.emplace_back(MeasureHandler {module, typeCb}); +} - bool MeasureManager::hasMeasureHandler(const char* module) { - for(MeasureHandler& handler : _mMeasureHandlers) { - if (strcmp(handler.module.c_str(), module) == 0) { - return true; - } +bool MeasureManager::hasMeasureHandler(const char* module) +{ + for (MeasureHandler& handler : _mMeasureHandlers) { + if (strcmp(handler.module.c_str(), module) == 0) { + return true; } - return false; } - - MeasureHandler MeasureManager::getMeasureHandler(const char* module) { - for(MeasureHandler handler : _mMeasureHandlers) { - if (!strcmp(handler.module.c_str(), module)) { - return handler; - } + return false; +} + +MeasureHandler MeasureManager::getMeasureHandler(const char* module) +{ + for (MeasureHandler handler : _mMeasureHandlers) { + if (!strcmp(handler.module.c_str(), module)) { + return handler; } - - MeasureHandler empty; - return empty; } - MeasureHandler MeasureManager::getMeasureHandler(const App::MeasureSelectionItem& selectionItem) { - auto objT = selectionItem.object; - - // Resolve App::Link - App::DocumentObject* sub = objT.getSubObject(); - if (sub->isDerivedFrom()) { - auto link = static_cast(sub); - sub = link->getLinkedObject(true); - } + MeasureHandler empty; + return empty; +} - const char* className = sub->getTypeId().getName(); - std::string mod = Base::Type::getModuleName(className); +MeasureHandler MeasureManager::getMeasureHandler(const App::MeasureSelectionItem& selectionItem) +{ + auto objT = selectionItem.object; - return getMeasureHandler(mod.c_str()); + // Resolve App::Link + App::DocumentObject* sub = objT.getSubObject(); + if (sub->isDerivedFrom()) { + auto link = static_cast(sub); + sub = link->getLinkedObject(true); } - MeasureElementType MeasureManager::getMeasureElementType(const App::MeasureSelectionItem& selectionItem) { - auto handler = getMeasureHandler(selectionItem); - if (handler.module.empty()) { - return App::MeasureElementType::INVALID; - } + const char* className = sub->getTypeId().getName(); + std::string mod = Base::Type::getModuleName(className); - auto objT = selectionItem.object; - return handler.typeCb(objT.getObject(), objT.getSubName().c_str()); - } - - void MeasureManager::addMeasureType(MeasureType* measureType) { - _mMeasureTypes.push_back(measureType); - } + return getMeasureHandler(mod.c_str()); +} - void MeasureManager::addMeasureType(std::string id, std::string label, std::string measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb) { - MeasureType* mType = new MeasureType{id, label, measureObj, validatorCb, prioritizeCb, false, nullptr}; - _mMeasureTypes.push_back(mType); +MeasureElementType +MeasureManager::getMeasureElementType(const App::MeasureSelectionItem& selectionItem) +{ + auto handler = getMeasureHandler(selectionItem); + if (handler.module.empty()) { + return App::MeasureElementType::INVALID; } - void MeasureManager::addMeasureType(const char* id, const char* label, const char* measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb) { - addMeasureType(std::string(id), std::string(label), std::string(measureObj), validatorCb, prioritizeCb); + auto objT = selectionItem.object; + return handler.typeCb(objT.getObject(), objT.getSubName().c_str()); +} + +void MeasureManager::addMeasureType(MeasureType* measureType) +{ + _mMeasureTypes.push_back(measureType); +} + +void MeasureManager::addMeasureType(std::string id, + std::string label, + std::string measureObj, + MeasureValidateMethod validatorCb, + MeasurePrioritizeMethod prioritizeCb) +{ + MeasureType* mType = + new MeasureType {id, label, measureObj, validatorCb, prioritizeCb, false, nullptr}; + _mMeasureTypes.push_back(mType); +} + +void MeasureManager::addMeasureType(const char* id, + const char* label, + const char* measureObj, + MeasureValidateMethod validatorCb, + MeasurePrioritizeMethod prioritizeCb) +{ + addMeasureType(std::string(id), + std::string(label), + std::string(measureObj), + validatorCb, + prioritizeCb); +} + +const std::vector MeasureManager::getMeasureTypes() +{ + return _mMeasureTypes; +} + + +Py::Tuple MeasureManager::getSelectionPy(const App::MeasureSelection& selection) +{ + // Convert selection to python list + Py::Tuple selectionPy(selection.size()); + + int i = 0; + for (auto it : selection) { + + Py::Dict sel; + sel.setItem("object", Py::asObject(it.object.getObject()->getPyObject())); + sel.setItem("subName", Py::String(it.object.getSubName())); + sel.setItem("pickedPoint", Py::asObject(new Base::VectorPy(it.pickedPoint))); + + selectionPy.setItem(i, sel); + + i++; } + return selectionPy; +} - const std::vector MeasureManager::getMeasureTypes() { - return _mMeasureTypes; - } +std::vector MeasureManager::getValidMeasureTypes(App::MeasureSelection selection, + std::string mode) +{ + Base::PyGILStateLocker lock; - Py::Tuple MeasureManager::getSelectionPy(const App::MeasureSelection& selection) { - // Convert selection to python list - Py::Tuple selectionPy(selection.size()); + // Convert selection to python list + Py::Tuple selectionPy = getSelectionPy(selection); - int i = 0; - for (auto it : selection) { + // Store valid measure types + std::vector validTypes; + std::pair(); - Py::Dict sel; - sel.setItem("object", Py::asObject(it.object.getObject()->getPyObject())); - sel.setItem("subName", Py::String(it.object.getSubName())); - sel.setItem("pickedPoint", Py::asObject(new Base::VectorPy(it.pickedPoint))); - selectionPy.setItem(i, sel); + // Loop through measure types and check if they work with given selection + for (App::MeasureType* mType : getMeasureTypes()) { - i++; + if (mode != "" && mType->label != mode) { + continue; } - return selectionPy; - } - - - std::vector MeasureManager::getValidMeasureTypes(App::MeasureSelection selection, std::string mode) { - Base::PyGILStateLocker lock; - - // Convert selection to python list - Py::Tuple selectionPy = getSelectionPy(selection); - // Store valid measure types - std::vector validTypes; - std::pair(); + if (mType->isPython) { + // Parse Python measure types + auto measurePyClass = Py::Object(mType->pythonClass); - // Loop through measure types and check if they work with given selection - for (App::MeasureType* mType : getMeasureTypes()){ + Py::Tuple args(1); + args.setItem(0, selectionPy); - if (mode != "" && mType->label != mode) { - continue; + Py::Object isValid; + try { + isValid = measurePyClass.callMemberFunction(std::string("isValidSelection"), args); + } + catch (const Py::Exception&) { + Base::PyException e; + e.ReportException(); + isValid = Py::False(); } + if (isValid.as_bool()) { - if (mType->isPython) { - // Parse Python measure types - auto measurePyClass = Py::Object(mType->pythonClass); - - Py::Tuple args(1); - args.setItem(0, selectionPy); - - Py::Object isValid; + // Check priority + Py::Object isPriority; try { - isValid = measurePyClass.callMemberFunction(std::string("isValidSelection"), args); - } catch (const Py::Exception&) { + isPriority = measurePyClass.callMemberFunction("isPrioritySelection", args); + } + catch (const Py::Exception&) { Base::PyException e; e.ReportException(); - isValid = Py::False(); + isPriority = Py::False(); } - if (isValid.as_bool()) { - - // Check priority - Py::Object isPriority; - try { - isPriority = measurePyClass.callMemberFunction("isPrioritySelection", args); - } catch (const Py::Exception&) { - Base::PyException e; - e.ReportException(); - isPriority = Py::False(); - } - - if (isPriority.as_bool()) { - validTypes.insert(validTypes.begin(), mType); - } else { - validTypes.push_back(mType); - } - } - } else { - // Parse c++ measure types - - if (mType->validatorCb && !mType->validatorCb(selection)) { - continue; - } - - // Check if the measurement type prioritizes the given selection - if (mType->prioritizeCb && mType->prioritizeCb(selection)) { + if (isPriority.as_bool()) { validTypes.insert(validTypes.begin(), mType); - } else { + } + else { validTypes.push_back(mType); } - } } + else { + // Parse c++ measure types - return validTypes; - } + if (mType->validatorCb && !mType->validatorCb(selection)) { + continue; + } + // Check if the measurement type prioritizes the given selection + if (mType->prioritizeCb && mType->prioritizeCb(selection)) { + validTypes.insert(validTypes.begin(), mType); + } + else { + validTypes.push_back(mType); + } + } + } + return validTypes; +} -} // namespace App +} // namespace App diff --git a/src/App/MeasureManager.h b/src/App/MeasureManager.h index 303bdd1390b7..66379c21a4f2 100644 --- a/src/App/MeasureManager.h +++ b/src/App/MeasureManager.h @@ -36,24 +36,27 @@ #include -namespace App { +namespace App +{ // Add your class methods and member variables here -enum class MeasureElementType { +enum class MeasureElementType +{ INVALID, POINT, LINE, LINESEGMENT, CIRCLE, ARC, - CURVE, // Has a length but no radius or axis + CURVE, // Has a length but no radius or axis PLANE, CYLINDER, Volume, }; -struct MeasureSelectionItem { +struct MeasureSelectionItem +{ App::SubObjectT object; Base::Vector3d pickedPoint; }; @@ -62,9 +65,10 @@ struct MeasureSelectionItem { using MeasureSelection = std::vector; using MeasureValidateMethod = std::function; using MeasurePrioritizeMethod = std::function; -using MeasureTypeMethod = std::function; +using MeasureTypeMethod = std::function; -struct MeasureType { +struct MeasureType +{ std::string identifier; std::string label; std::string measureObject; @@ -72,21 +76,24 @@ struct MeasureType { // Checks if the measurement works with a given selection MeasureValidateMethod validatorCb; - // Allows to prioritize this over other measurement types when the measurement type is picked implicitly from the selection. - // Gets called only when validatorCb returned true for the given selection + // Allows to prioritize this over other measurement types when the measurement type is picked + // implicitly from the selection. Gets called only when validatorCb returned true for the given + // selection MeasurePrioritizeMethod prioritizeCb; bool isPython; PyObject* pythonClass; }; -struct MeasureHandler { +struct MeasureHandler +{ std::string module; MeasureTypeMethod typeCb; }; -class AppExport MeasureManager { +class AppExport MeasureManager +{ public: MeasureManager(); @@ -96,11 +103,20 @@ class AppExport MeasureManager { static MeasureHandler getMeasureHandler(const App::MeasureSelectionItem& selectionItem); static MeasureElementType getMeasureElementType(const App::MeasureSelectionItem& selectionItem); static void addMeasureType(MeasureType* measureType); - static void addMeasureType(std::string id, std::string label, std::string measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb); - static void addMeasureType(const char* id, const char* label, const char* measureObj, MeasureValidateMethod validatorCb, MeasurePrioritizeMethod prioritizeCb); + static void addMeasureType(std::string id, + std::string label, + std::string measureObj, + MeasureValidateMethod validatorCb, + MeasurePrioritizeMethod prioritizeCb); + static void addMeasureType(const char* id, + const char* label, + const char* measureObj, + MeasureValidateMethod validatorCb, + MeasurePrioritizeMethod prioritizeCb); static const std::vector getMeasureTypes(); static Py::Tuple getSelectionPy(const App::MeasureSelection& selection); - static std::vector getValidMeasureTypes(App::MeasureSelection selection, std::string mode); + static std::vector getValidMeasureTypes(App::MeasureSelection selection, + std::string mode); private: @@ -109,6 +125,6 @@ class AppExport MeasureManager { }; -} // namespace App +} // namespace App -#endif // MEASUREMANAGER_H +#endif // MEASUREMANAGER_H diff --git a/src/App/MeasureManagerPyImp.cpp b/src/App/MeasureManagerPyImp.cpp index be7854b98eed..bcb5d08a6523 100644 --- a/src/App/MeasureManagerPyImp.cpp +++ b/src/App/MeasureManagerPyImp.cpp @@ -47,17 +47,17 @@ int MeasureManagerPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj* } -PyObject* MeasureManagerPy::addMeasureType(PyObject *args) +PyObject* MeasureManagerPy::addMeasureType(PyObject* args) { - PyObject *pyobj = Py_None; + PyObject* pyobj = Py_None; char *id, *label; - if (!PyArg_ParseTuple(args, "ssO", &id, &label, &pyobj)) + if (!PyArg_ParseTuple(args, "ssO", &id, &label, &pyobj)) { return nullptr; + } MeasureManager::addMeasureType( - new App::MeasureType{id, label, "", nullptr, nullptr, true, pyobj} - ); + new App::MeasureType {id, label, "", nullptr, nullptr, true, pyobj}); Py_Return; } @@ -66,7 +66,7 @@ PyObject* MeasureManagerPy::addMeasureType(PyObject *args) PyObject* MeasureManagerPy::getMeasureTypes() { Py::List types; - for (auto & it : MeasureManager::getMeasureTypes()) { + for (auto& it : MeasureManager::getMeasureTypes()) { Py::Tuple type(3); type.setItem(0, Py::String(it->identifier)); type.setItem(1, Py::String(it->label)); diff --git a/src/App/MergeDocuments.cpp b/src/App/MergeDocuments.cpp index 10453b163f72..fafcab3cc61a 100644 --- a/src/App/MergeDocuments.cpp +++ b/src/App/MergeDocuments.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -36,13 +36,17 @@ using namespace App; namespace sp = std::placeholders; -namespace App { +namespace App +{ -class XMLMergeReader : public Base::XMLReader +class XMLMergeReader: public Base::XMLReader { public: - XMLMergeReader(std::map& name, const char* FileName, std::istream& str) - : Base::XMLReader(FileName, str), nameMap(name) + XMLMergeReader(std::map& name, + const char* FileName, + std::istream& str) + : Base::XMLReader(FileName, str) + , nameMap(name) {} void addName(const char* s1, const char* s2) override @@ -52,34 +56,35 @@ class XMLMergeReader : public Base::XMLReader const char* getName(const char* name) const override { std::map::const_iterator it = nameMap.find(name); - if (it != nameMap.end()) + if (it != nameMap.end()) { return it->second.c_str(); - else + } + else { return name; + } } bool doNameMapping() const override { return true; } -protected: - +protected: private: std::map& nameMap; using PropertyTag = std::pair; std::stack propertyStack; }; -} +} // namespace App MergeDocuments::MergeDocuments(App::Document* doc) : appdoc(doc) { - //NOLINTBEGIN - connectExport = doc->signalExportObjects.connect - (std::bind(&MergeDocuments::exportObject, this, sp::_1, sp::_2)); - connectImport = doc->signalImportObjects.connect - (std::bind(&MergeDocuments::importObject, this, sp::_1, sp::_2)); - //NOLINTEND + // NOLINTBEGIN + connectExport = doc->signalExportObjects.connect( + std::bind(&MergeDocuments::exportObject, this, sp::_1, sp::_2)); + connectImport = doc->signalImportObjects.connect( + std::bind(&MergeDocuments::importObject, this, sp::_1, sp::_2)); + // NOLINTEND QCoreApplication* app = QCoreApplication::instance(); if (app && app->inherits("QApplication")) { @@ -93,17 +98,16 @@ MergeDocuments::~MergeDocuments() connectImport.disconnect(); } -unsigned int MergeDocuments::getMemSize () const +unsigned int MergeDocuments::getMemSize() const { return 0; } -std::vector -MergeDocuments::importObjects(std::istream& input) +std::vector MergeDocuments::importObjects(std::istream& input) { this->nameMap.clear(); this->stream = new zipios::ZipInputStream(input); - XMLMergeReader reader(this->nameMap,"", *stream); + XMLMergeReader reader(this->nameMap, "", *stream); reader.setVerbose(isVerbose()); std::vector objs = appdoc->importObjects(reader); @@ -113,20 +117,20 @@ MergeDocuments::importObjects(std::istream& input) return objs; } -void MergeDocuments::importObject(const std::vector& o, Base::XMLReader & r) +void MergeDocuments::importObject(const std::vector& o, Base::XMLReader& r) { objects = o; Restore(r); r.readFiles(*this->stream); } -void MergeDocuments::exportObject(const std::vector& o, Base::Writer & w) +void MergeDocuments::exportObject(const std::vector& o, Base::Writer& w) { objects = o; Save(w); } -void MergeDocuments::Save (Base::Writer & w) const +void MergeDocuments::Save(Base::Writer& w) const { // Save view provider stuff if (guiup) { @@ -134,7 +138,7 @@ void MergeDocuments::Save (Base::Writer & w) const } } -void MergeDocuments::Restore(Base::XMLReader &r) +void MergeDocuments::Restore(Base::XMLReader& r) { // Restore view provider stuff if (guiup) { @@ -142,13 +146,13 @@ void MergeDocuments::Restore(Base::XMLReader &r) } } -void MergeDocuments::SaveDocFile (Base::Writer & w) const +void MergeDocuments::SaveDocFile(Base::Writer& w) const { // Save view provider stuff appdoc->signalExportViewObjects(this->objects, w); } -void MergeDocuments::RestoreDocFile(Base::Reader & r) +void MergeDocuments::RestoreDocFile(Base::Reader& r) { // Restore view provider stuff appdoc->signalImportViewObjects(this->objects, r, this->nameMap); diff --git a/src/App/MergeDocuments.h b/src/App/MergeDocuments.h index f1cd31ec9776..faab10179aa3 100644 --- a/src/App/MergeDocuments.h +++ b/src/App/MergeDocuments.h @@ -27,36 +27,47 @@ #include #include -namespace zipios { +namespace zipios +{ class ZipInputStream; } -namespace App { +namespace App +{ class Document; class DocumentObject; -class AppExport MergeDocuments : public Base::Persistence +class AppExport MergeDocuments: public Base::Persistence { public: explicit MergeDocuments(App::Document* doc); ~MergeDocuments() override; - bool isVerbose() const { return verbose; } - void setVerbose(bool on) { verbose = on; } - unsigned int getMemSize () const override; + bool isVerbose() const + { + return verbose; + } + void setVerbose(bool on) + { + verbose = on; + } + unsigned int getMemSize() const override; std::vector importObjects(std::istream&); - void importObject(const std::vector& o, Base::XMLReader & r); - void exportObject(const std::vector& o, Base::Writer & w); - void Save (Base::Writer & w) const override; - void Restore(Base::XMLReader &r) override; - void SaveDocFile (Base::Writer & w) const override; - void RestoreDocFile(Base::Reader & r) override; + void importObject(const std::vector& o, Base::XMLReader& r); + void exportObject(const std::vector& o, Base::Writer& w); + void Save(Base::Writer& w) const override; + void Restore(Base::XMLReader& r) override; + void SaveDocFile(Base::Writer& w) const override; + void RestoreDocFile(Base::Reader& r) override; - const std::map &getNameMap() const {return nameMap;} + const std::map& getNameMap() const + { + return nameMap; + } private: - bool guiup{false}; - bool verbose{true}; - zipios::ZipInputStream* stream{nullptr}; - App::Document* appdoc{nullptr}; + bool guiup {false}; + bool verbose {true}; + zipios::ZipInputStream* stream {nullptr}; + App::Document* appdoc {nullptr}; std::vector objects; std::map nameMap; using Connection = boost::signals2::connection; @@ -64,6 +75,6 @@ class AppExport MergeDocuments : public Base::Persistence Connection connectImport; }; -} // namespace App +} // namespace App -#endif // APP_MERGEDOCUMENTS_H +#endif // APP_MERGEDOCUMENTS_H diff --git a/src/App/Metadata.cpp b/src/App/Metadata.cpp index 1a70438e23ce..4e9df6f5fed9 100644 --- a/src/App/Metadata.cpp +++ b/src/App/Metadata.cpp @@ -1,31 +1,31 @@ /************************************************************************** -* * -* Copyright (c) 2021-2023 FreeCAD Project Association * -* * -* This file is part of FreeCAD. * -* * -* FreeCAD is free software: you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as * -* published by the Free Software Foundation, either version 2.1 of the * -* License, or (at your option) any later version. * -* * -* FreeCAD is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -* Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public * -* License along with FreeCAD. If not, see * -* . * -* * -***************************************************************************/ + * * + * Copyright (c) 2021-2023 FreeCAD Project Association * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -93,7 +93,7 @@ class XMLErrorHandler: public HandlerBase throw Base::XMLBaseException(message.str()); } }; -}// namespace MetadataInternal +} // namespace MetadataInternal Metadata::Metadata(const fs::path& metadataFile) : _dom(nullptr) @@ -130,10 +130,9 @@ Metadata::Metadata(const DOMNode* domNode, int format) App::Metadata::Metadata(const std::string& rawData) : _dom(nullptr) { - MemBufInputSource buffer( - reinterpret_cast(rawData.c_str()), - rawData.size(), - "raw data (in memory)"); + MemBufInputSource buffer(reinterpret_cast(rawData.c_str()), + rawData.size(), + "raw data (in memory)"); loadFromInputSource(buffer); } @@ -294,7 +293,7 @@ XERCES_CPP_NAMESPACE::DOMElement* Metadata::dom() const void Metadata::setName(const std::string& name) { - std::string invalidCharacters = "/\\?%*:|\"<>";// Should cover all OSes + std::string invalidCharacters = "/\\?%*:|\"<>"; // Should cover all OSes if (_name.find_first_of(invalidCharacters) != std::string::npos) { throw Base::RuntimeError("Name cannot contain any of: " + invalidCharacters); } @@ -534,7 +533,8 @@ void Metadata::clearFile() } -DOMElement* appendSimpleXMLNode(DOMElement* baseNode, const std::string& nodeName, +DOMElement* appendSimpleXMLNode(DOMElement* baseNode, + const std::string& nodeName, const std::string& nodeContents) { // For convenience (and brevity of final output) don't create nodes that don't have contents @@ -665,8 +665,9 @@ bool Metadata::satisfies(const Meta::Dependency& dep) if (dep.package != _name) { return false; } - // The "condition" attribute allows an expression to enable or disable this dependency check: it must contain a valid - // FreeCAD Expression. If it evaluates to false, this dependency is bypassed (e.g. this function returns false). + // The "condition" attribute allows an expression to enable or disable this dependency check: it + // must contain a valid FreeCAD Expression. If it evaluates to false, this dependency is + // bypassed (e.g. this function returns false). if (!dep.condition.empty()) { auto injectedString = dep.condition; std::map replacements; @@ -938,11 +939,11 @@ void Metadata::parseVersion1(const DOMNode* startNode) _icon = fs::path(StrXUTF8(element->getTextContent()).str); } else if (tagString == "content") { - parseContentNodeVersion1(element);// Recursive call + parseContentNodeVersion1(element); // Recursive call } else { - // If none of this node's nodeChildren have nodeChildren of their own, it is a simple element and we - // can handle it as a GenericMetadata object + // If none of this node's nodeChildren have nodeChildren of their own, it is a simple + // element and we can handle it as a GenericMetadata object auto nodeChildren = element->getChildNodes(); bool hasGrandchildren = false; for (XMLSize_t j = 0; j < nodeChildren->getLength() && !hasGrandchildren; ++j) { @@ -970,15 +971,15 @@ void Metadata::parseContentNodeVersion1(const DOMElement* contentNode) } Meta::Contact::Contact(std::string name, std::string email) - : name(std::move(name)), - email(std::move(email)) + : name(std::move(name)) + , email(std::move(email)) { // This has to be provided manually since we have another constructor } Meta::Contact::Contact(const XERCES_CPP_NAMESPACE::DOMElement* elem) { - if (!elem){ + if (!elem) { return; } auto emailAttribute = elem->getAttribute(XUTF8Str("email").unicodeForm()); @@ -992,15 +993,15 @@ bool App::Meta::Contact::operator==(const Contact& rhs) const } Meta::License::License(std::string name, fs::path file) - : name(std::move(name)), - file(std::move(file)) + : name(std::move(name)) + , file(std::move(file)) { // This has to be provided manually since we have another constructor } Meta::License::License(const XERCES_CPP_NAMESPACE::DOMElement* elem) { - if (!elem){ + if (!elem) { return; } auto fileAttribute = elem->getAttribute(XUTF8Str("file").unicodeForm()); @@ -1016,13 +1017,13 @@ bool App::Meta::License::operator==(const License& rhs) const } App::Meta::Url::Url() - : location(""), - type(App::Meta::UrlType::website) + : location("") + , type(App::Meta::UrlType::website) {} Meta::Url::Url(std::string location, UrlType type) - : location(std::move(location)), - type(type) + : location(std::move(location)) + , type(type) { // This has to be provided manually since we have another constructor } @@ -1070,14 +1071,14 @@ bool App::Meta::Url::operator==(const Url& rhs) const } App::Meta::Dependency::Dependency() - : optional(false), - dependencyType(App::Meta::DependencyType::automatic) + : optional(false) + , dependencyType(App::Meta::DependencyType::automatic) {} App::Meta::Dependency::Dependency(std::string pkg) - : package(std::move(pkg)), - optional(false), - dependencyType(App::Meta::DependencyType::automatic) + : package(std::move(pkg)) + , optional(false) + , dependencyType(App::Meta::DependencyType::automatic) {} Meta::Dependency::Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem) @@ -1090,7 +1091,7 @@ Meta::Dependency::Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem) condition = StrXUTF8(elem->getAttribute(XUTF8Str("condition").unicodeForm())).str; std::string opt_string = StrXUTF8(elem->getAttribute(XUTF8Str("optional").unicodeForm())).str; if (opt_string == "true" - || opt_string == "True") {// Support Python capitalization in this one case... + || opt_string == "True") { // Support Python capitalization in this one case... optional = true; } else { @@ -1128,10 +1129,10 @@ bool App::Meta::Dependency::operator==(const Dependency& rhs) const Meta::Version::Version() = default; Meta::Version::Version(int major, int minor, int patch, std::string suffix) - : major(major), - minor(minor), - patch(patch), - suffix(std::move(suffix)) + : major(major) + , minor(minor) + , patch(patch) + , suffix(std::move(suffix)) {} Meta::Version::Version(const std::string& versionString) @@ -1207,8 +1208,8 @@ Meta::GenericMetadata::GenericMetadata(const XERCES_CPP_NAMESPACE::DOMElement* e contents = StrXUTF8(elem->getTextContent()).str; for (XMLSize_t i = 0; i < elem->getAttributes()->getLength(); ++i) { auto attr = elem->getAttributes()->item(i); - attributes.insert( - std::make_pair(StrXUTF8(attr->getNodeName()).str, StrXUTF8(attr->getTextContent()).str)); + attributes.insert(std::make_pair(StrXUTF8(attr->getNodeName()).str, + StrXUTF8(attr->getTextContent()).str)); } } diff --git a/src/App/Metadata.h b/src/App/Metadata.h index ff30828ce418..fa5f14717c99 100644 --- a/src/App/Metadata.h +++ b/src/App/Metadata.h @@ -1,24 +1,24 @@ /************************************************************************** -* * -* Copyright (c) 2021-2023 FreeCAD Project Association * -* * -* This file is part of FreeCAD. * -* * -* FreeCAD is free software: you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as * -* published by the Free Software Foundation, either version 2.1 of the * -* License, or (at your option) any later version. * -* * -* FreeCAD is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -* Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public * -* License along with FreeCAD. If not, see * -* . * -* * -***************************************************************************/ + * * + * Copyright (c) 2021-2023 FreeCAD Project Association * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ #ifndef BASE_METADATAREADER_H #define BASE_METADATAREADER_H @@ -43,32 +43,36 @@ namespace Meta { /** - * \struct Contact - * \brief A person or company representing a point of contact for the package (either author or maintainer). - */ -struct AppExport Contact { + * \struct Contact + * \brief A person or company representing a point of contact for the package (either author or + * maintainer). + */ +struct AppExport Contact +{ Contact() = default; - Contact(std::string name, std::string email); + Contact(std::string name, std::string email); explicit Contact(const XERCES_CPP_NAMESPACE::DOMElement* elem); - std::string name; //< Contact name - required - std::string email;//< Contact email - may be optional + std::string name; //< Contact name - required + std::string email; //< Contact email - may be optional bool operator==(const Contact& rhs) const; }; /** - * \struct License - * \brief A license that covers some or all of this package. - * - * Many licenses also require the inclusion of the complete license text, specified in this struct - * using the "file" member. - */ -struct AppExport License { + * \struct License + * \brief A license that covers some or all of this package. + * + * Many licenses also require the inclusion of the complete license text, specified in this struct + * using the "file" member. + */ +struct AppExport License +{ License() = default; License(std::string name, boost::filesystem::path file); explicit License(const XERCES_CPP_NAMESPACE::DOMElement* elem); - std::string name;//< Short name of license, e.g. "LGPL2", "MIT", "Mozilla Public License", etc. + std::string + name; //< Short name of license, e.g. "LGPL2", "MIT", "Mozilla Public License", etc. boost::filesystem::path - file;//< Optional path to the license file, relative to the XML file's location + file; //< Optional path to the license file, relative to the XML file's location bool operator==(const License& rhs) const; }; @@ -83,32 +87,35 @@ enum class UrlType }; /** - * \struct Url - * \brief A URL, including type information (e.g. website, repository, or bugtracker, in package.xml) - */ -struct AppExport Url { + * \struct Url + * \brief A URL, including type information (e.g. website, repository, or bugtracker, in + * package.xml) + */ +struct AppExport Url +{ Url(); Url(std::string location, UrlType type); explicit Url(const XERCES_CPP_NAMESPACE::DOMElement* elem); - std::string location;//< The actual URL, including protocol - UrlType type; //< What kind of URL this is - std::string branch; //< If it's a repository, which branch to use + std::string location; //< The actual URL, including protocol + UrlType type; //< What kind of URL this is + std::string branch; //< If it's a repository, which branch to use bool operator==(const Url& rhs) const; }; /** - * \struct Version - * A semantic version structure providing comparison operators and conversion to and from std::string - */ -struct AppExport Version { + * \struct Version + * A semantic version structure providing comparison operators and conversion to and from + * std::string + */ +struct AppExport Version +{ Version(); - explicit Version(int major, int minor = 0, int patch = 0, - std::string suffix = std::string()); + explicit Version(int major, int minor = 0, int patch = 0, std::string suffix = std::string()); explicit Version(const std::string& semanticString); - int major{}; - int minor{}; - int patch{}; + int major {}; + int minor {}; + int patch {}; std::string suffix; std::string str() const; @@ -122,9 +129,9 @@ struct AppExport Version { }; /** - * \enum DependencyType - * The type of dependency. - */ + * \enum DependencyType + * The type of dependency. + */ enum class DependencyType { automatic, @@ -134,81 +141,83 @@ enum class DependencyType }; /** - * \struct Dependency - * \brief Another package that this package depends on, conflicts with, or replaces - */ -struct AppExport Dependency { + * \struct Dependency + * \brief Another package that this package depends on, conflicts with, or replaces + */ +struct AppExport Dependency +{ Dependency(); - explicit Dependency(std::string pkg); + explicit Dependency(std::string pkg); explicit Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem); - std::string - package;//< Required: must exactly match the contents of the "name" element in the referenced package's package.xml file. - std::string - version_lt;//< Optional: The dependency to the package is restricted to versions less than the stated version number. - std::string - version_lte;//< Optional: The dependency to the package is restricted to versions less or equal than the stated version number. - std::string - version_eq;//< Optional: The dependency to the package is restricted to a version equal than the stated version number. - std::string - version_gte;//< Optional: The dependency to the package is restricted to versions greater or equal than the stated version number. - std::string - version_gt;//< Optional: The dependency to the package is restricted to versions greater than the stated version number. - std::string condition; //< Optional: Conditional expression as documented in REP149. - bool optional; //< Optional: Whether this dependency is considered "optional" - DependencyType dependencyType;//< Optional: defaults to "automatic" + std::string package; //< Required: must exactly match the contents of the "name" element in the + //referenced package's package.xml file. + std::string version_lt; //< Optional: The dependency to the package is restricted to versions + //less than the stated version number. + std::string version_lte; //< Optional: The dependency to the package is restricted to versions + //less or equal than the stated version number. + std::string version_eq; //< Optional: The dependency to the package is restricted to a version + //equal than the stated version number. + std::string version_gte; //< Optional: The dependency to the package is restricted to versions + //greater or equal than the stated version number. + std::string version_gt; //< Optional: The dependency to the package is restricted to versions + //greater than the stated version number. + std::string condition; //< Optional: Conditional expression as documented in REP149. + bool optional; //< Optional: Whether this dependency is considered "optional" + DependencyType dependencyType; //< Optional: defaults to "automatic" bool operator==(const Dependency& rhs) const; }; /** - * \struct GenericMetadata - * A structure to hold unrecognized single-level metadata. - * - * Most unrecognized metadata is simple: when parsing the XML, if the parser finds a tag it - * does not recognize, and that tag has no children, it is parsed into this data structure - * for convenient access by client code. - */ -struct AppExport GenericMetadata { + * \struct GenericMetadata + * A structure to hold unrecognized single-level metadata. + * + * Most unrecognized metadata is simple: when parsing the XML, if the parser finds a tag it + * does not recognize, and that tag has no children, it is parsed into this data structure + * for convenient access by client code. + */ +struct AppExport GenericMetadata +{ GenericMetadata() = default; explicit GenericMetadata(const XERCES_CPP_NAMESPACE::DOMElement* elem); - explicit GenericMetadata(std::string contents); - std::string contents; //< The contents of the tag - std::map attributes;//< The XML attributes of the tag + explicit GenericMetadata(std::string contents); + std::string contents; //< The contents of the tag + std::map attributes; //< The XML attributes of the tag }; -}// namespace Meta +} // namespace Meta /** - * \class Metadata - * \brief Reads data from a metadata file. - * - * The metadata format is based on https://ros.org/reps/rep-0149.html, modified for FreeCAD - * use. Full format documentation is available at the FreeCAD Wiki: - * https://wiki.freecad.org/Package_Metadata - */ + * \class Metadata + * \brief Reads data from a metadata file. + * + * The metadata format is based on https://ros.org/reps/rep-0149.html, modified for FreeCAD + * use. Full format documentation is available at the FreeCAD Wiki: + * https://wiki.freecad.org/Package_Metadata + */ class AppExport Metadata { public: Metadata(); /** - * Read the data from a file on disk - * - * This constructor takes a path to an XML file and loads the XML from that file as - * metadata. - */ + * Read the data from a file on disk + * + * This constructor takes a path to an XML file and loads the XML from that file as + * metadata. + */ explicit Metadata(const boost::filesystem::path& metadataFile); /** - * Construct a Metadata object from a DOM node. - * - * This node may have any tag name: it is only accessed via its children, which are - * expected to follow the standard Metadata format for the contents of the element. - */ + * Construct a Metadata object from a DOM node. + * + * This node may have any tag name: it is only accessed via its children, which are + * expected to follow the standard Metadata format for the contents of the element. + */ Metadata(const XERCES_CPP_NAMESPACE::DOMNode* domNode, int format); /** - * Treat the incoming rawData as metadata to be parsed. - */ + * Treat the incoming rawData as metadata to be parsed. + */ explicit Metadata(const std::string& rawData); ~Metadata(); @@ -218,69 +227,69 @@ class AppExport Metadata // Recognized Metadata ////////////////////////////////////////////////////////////// - std::string name() const; //< A short name for this package, often used as a menu entry. - std::string type() const; //< The type for this package. - Meta::Version version() const;//< Version string in semantic triplet format, e.g. "1.2.3". + std::string name() const; //< A short name for this package, often used as a menu entry. + std::string type() const; //< The type for this package. + Meta::Version version() const; //< Version string in semantic triplet format, e.g. "1.2.3". std::string date() - const;//< Date string -- currently arbitrary (when C++20 is well-supported we can revisit) - std::string description() const;//< Text-only description of the package. No markup. + const; //< Date string -- currently arbitrary (when C++20 is well-supported we can revisit) + std::string description() const; //< Text-only description of the package. No markup. std::vector - maintainer() const;//< Must be at least one, and must specify an email address. + maintainer() const; //< Must be at least one, and must specify an email address. std::vector - license() const;//< Must be at least one, and most licenses require including a license file. - std::vector url() - const;//< Any number of URLs may be specified, but at least one repository URL must be included at the package level. + license() const; //< Must be at least one, and most licenses require including a license file. + std::vector url() const; //< Any number of URLs may be specified, but at least one + //repository URL must be included at the package level. std::vector - author() const;//< Any number of authors may be specified, and email addresses are optional. + author() const; //< Any number of authors may be specified, and email addresses are optional. std::vector - depend() const;//< Zero or more packages this package requires prior to use. + depend() const; //< Zero or more packages this package requires prior to use. std::vector - conflict() const;//< Zero of more packages this package conflicts with. + conflict() const; //< Zero of more packages this package conflicts with. std::vector - replace() const;//< Zero or more packages this package is intended to replace. - std::vector tag() const;//< Zero or more text tags related to this package. - boost::filesystem::path icon() const;//< Path to an icon file. + replace() const; //< Zero or more packages this package is intended to replace. + std::vector tag() const; //< Zero or more text tags related to this package. + boost::filesystem::path icon() const; //< Path to an icon file. std::string - classname() const;//< Recognized for convenience -- generally only used by Workbenches. + classname() const; //< Recognized for convenience -- generally only used by Workbenches. boost::filesystem::path - subdirectory() const;//< Optional, override the default subdirectory name for this item. + subdirectory() const; //< Optional, override the default subdirectory name for this item. std::vector - file() const;//< Arbitrary files associated with this package or content item. - Meta::Version freecadmin() const;//< The minimum FreeCAD version. - Meta::Version freecadmax() const;//< The maximum FreeCAD version. - Meta::Version pythonmin() const; //< The minimum Python version. + file() const; //< Arbitrary files associated with this package or content item. + Meta::Version freecadmin() const; //< The minimum FreeCAD version. + Meta::Version freecadmax() const; //< The maximum FreeCAD version. + Meta::Version pythonmin() const; //< The minimum Python version. /** - * Access the metadata for the content elements of this package - * - * In addition to the overall package metadata, this class reads in metadata contained in a - * element. Each entry in the content element is an element representing some - * type of package content (e.g. add-on, macro, theme, etc.). This class places no restriction - * on the types, it is up to client code to place requirements on the metadata included - * here. - * - * For example, themes might be specified: - * - * - * High Contrast - * - * - */ + * Access the metadata for the content elements of this package + * + * In addition to the overall package metadata, this class reads in metadata contained in a + * element. Each entry in the content element is an element representing some + * type of package content (e.g. add-on, macro, theme, etc.). This class places no restriction + * on the types, it is up to client code to place requirements on the metadata included + * here. + * + * For example, themes might be specified: + * + * + * High Contrast + * + * + */ std::multimap content() const; /** - * Convenience accessor for unrecognized simple metadata. - * - * If the XML parser encounters tags that it does not recognize, and those tags have - * no children, a GenericMetadata object is created. Those objects can be accessed using - * operator[], which returns a (potentially empty) vector containing all instances of the - * given tag. It cannot be used to *create* a new tag, however. See addGenericMetadata(). - */ + * Convenience accessor for unrecognized simple metadata. + * + * If the XML parser encounters tags that it does not recognize, and those tags have + * no children, a GenericMetadata object is created. Those objects can be accessed using + * operator[], which returns a (potentially empty) vector containing all instances of the + * given tag. It cannot be used to *create* a new tag, however. See addGenericMetadata(). + */ std::vector operator[](const std::string& tag) const; /** - * Directly access the DOM tree to support unrecognized multi-level metadata - */ + * Directly access the DOM tree to support unrecognized multi-level metadata + */ XERCES_CPP_NAMESPACE::DOMElement* dom() const; @@ -333,19 +342,19 @@ class AppExport Metadata void clearFile(); /** - * Write the metadata to an XML file - */ + * Write the metadata to an XML file + */ void write(const boost::filesystem::path& file) const; /** - * Determine whether this package satisfies the given dependency - */ + * Determine whether this package satisfies the given dependency + */ bool satisfies(const Meta::Dependency&); /** - * Determine whether the current metadata specifies support for the currently-running version of FreeCAD. - * Does not interrogate content items, which must be queried individually. - */ + * Determine whether the current metadata specifies support for the currently-running version of + * FreeCAD. Does not interrogate content items, which must be queried individually. + */ bool supportsCurrentFreeCAD() const; private: @@ -384,6 +393,6 @@ class AppExport Metadata void appendToElement(XERCES_CPP_NAMESPACE::DOMElement* root) const; }; -}// namespace App +} // namespace App #endif diff --git a/src/App/MetadataPyImp.cpp b/src/App/MetadataPyImp.cpp index a2241a0e6e67..953f2799dc02 100644 --- a/src/App/MetadataPyImp.cpp +++ b/src/App/MetadataPyImp.cpp @@ -1,24 +1,24 @@ /************************************************************************** -* * -* Copyright (c) 2022 FreeCAD Project Association * -* * -* This file is part of FreeCAD. * -* * -* FreeCAD is free software: you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as * -* published by the Free Software Foundation, either version 2.1 of the * -* License, or (at your option) any later version. * -* * -* FreeCAD is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * -* Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Lesser General Public * -* License along with FreeCAD. If not, see * -* . * -* * -**************************************************************************/ + * * + * Copyright (c) 2022 FreeCAD Project Association * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ #include "PreCompiled.h" @@ -55,13 +55,13 @@ std::string MetadataPy::representation() const return str.str(); } -PyObject *MetadataPy::PyMake(struct _typeobject *, PyObject *, PyObject *)// Python wrapper +PyObject* MetadataPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { return new MetadataPy(nullptr); } // constructor method -int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/) +int MetadataPy::PyInit(PyObject* args, PyObject* /*kwd*/) { if (PyArg_ParseTuple(args, "")) { setTwinPointer(new Metadata()); @@ -75,9 +75,8 @@ int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/) try { // NB: This is making a copy of the buffer for simplicity, but that shouldn't be // necessary. Use either a string_view or a span to avoid the copy in the future. - auto md = new Metadata( - std::string(static_cast(dataBuffer.buf), dataBuffer.len) - ); + auto md = + new Metadata(std::string(static_cast(dataBuffer.buf), dataBuffer.len)); setTwinPointer(md); return 0; } @@ -89,7 +88,7 @@ int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/) // Main class constructor -- takes a file path, loads the metadata from it PyErr_Clear(); - char *filename; + char* filename; if (PyArg_ParseTuple(args, "et", "utf-8", &filename)) { try { std::string utf8Name = std::string(filename); @@ -99,19 +98,19 @@ int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/) setTwinPointer(md); return 0; } - catch (const Base::XMLBaseException &e) { + catch (const Base::XMLBaseException& e) { e.setPyException(); return -1; } - catch (const XMLException &toCatch) { - char *message = XMLString::transcode(toCatch.getMessage()); + catch (const XMLException& toCatch) { + char* message = XMLString::transcode(toCatch.getMessage()); std::string what = message; XMLString::release(&message); PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str()); return -1; } - catch (const DOMException &toCatch) { - char *message = XMLString::transcode(toCatch.getMessage()); + catch (const DOMException& toCatch) { + char* message = XMLString::transcode(toCatch.getMessage()); std::string what = message; XMLString::release(&message); PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str()); @@ -125,14 +124,15 @@ int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/) // Copy constructor PyErr_Clear(); - PyObject *o; + PyObject* o; if (PyArg_ParseTuple(args, "O!", &(App::MetadataPy::Type), &o)) { - App::Metadata *a = static_cast(o)->getMetadataPtr(); + App::Metadata* a = static_cast(o)->getMetadataPtr(); setTwinPointer(new Metadata(*a)); return 0; } - PyErr_SetString(Base::PyExc_FC_GeneralError, "metadata object or path to metadata file expected"); + PyErr_SetString(Base::PyExc_FC_GeneralError, + "metadata object or path to metadata file expected"); return -1; } @@ -143,14 +143,16 @@ Py::Object MetadataPy::getName() const void MetadataPy::setName(Py::Object args) { - const char *name = nullptr; + const char* name = nullptr; if (!PyArg_Parse(args.ptr(), "z", &name)) { throw Py::Exception(); } - if (name) + if (name) { getMetadataPtr()->setName(name); - else + } + else { getMetadataPtr()->setName(""); + } } Py::Object MetadataPy::getVersion() const @@ -160,13 +162,16 @@ Py::Object MetadataPy::getVersion() const void MetadataPy::setVersion(Py::Object args) { - const char *name = nullptr; - if (!PyArg_Parse(args.ptr(), "z", &name)) + const char* name = nullptr; + if (!PyArg_Parse(args.ptr(), "z", &name)) { throw Py::Exception(); - if (name && name[0] != '\0') + } + if (name && name[0] != '\0') { getMetadataPtr()->setVersion(App::Meta::Version(std::string(name))); - else + } + else { getMetadataPtr()->setVersion(App::Meta::Version()); + } } Py::Object MetadataPy::getDate() const @@ -176,12 +181,16 @@ Py::Object MetadataPy::getDate() const void MetadataPy::setDate(Py::Object args) { - const char *date = nullptr; - if (!PyArg_Parse(args.ptr(), "z", &date)) + const char* date = nullptr; + if (!PyArg_Parse(args.ptr(), "z", &date)) { throw Py::Exception(); - if (date) getMetadataPtr()->setDate(date); - else + } + if (date) { + getMetadataPtr()->setDate(date); + } + else { getMetadataPtr()->setDate(""); + } } Py::Object MetadataPy::getDescription() const @@ -191,9 +200,10 @@ Py::Object MetadataPy::getDescription() const void MetadataPy::setDescription(Py::Object args) { - const char *description = nullptr; - if (!PyArg_Parse(args.ptr(), "s", &description)) + const char* description = nullptr; + if (!PyArg_Parse(args.ptr(), "s", &description)) { throw Py::Exception(); + } getMetadataPtr()->setDescription(description); } @@ -204,9 +214,10 @@ Py::Object MetadataPy::getType() const void MetadataPy::setType(Py::Object args) { - const char *type = nullptr; - if (!PyArg_Parse(args.ptr(), "s", &type)) + const char* type = nullptr; + if (!PyArg_Parse(args.ptr(), "s", &type)) { throw Py::Exception(); + } getMetadataPtr()->setType(type); } @@ -214,7 +225,7 @@ Py::Object MetadataPy::getMaintainer() const { auto maintainers = getMetadataPtr()->maintainer(); Py::List pyMaintainers; - for (const auto &m : maintainers) { + for (const auto& m : maintainers) { Py::Dict pyMaintainer; pyMaintainer["name"] = Py::String(m.name); pyMaintainer["email"] = Py::String(m.email); @@ -225,13 +236,14 @@ Py::Object MetadataPy::getMaintainer() const void MetadataPy::setMaintainer(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearMaintainer(); Py::List maintainers(list); - for (const auto &m : maintainers) { + for (const auto& m : maintainers) { Py::Dict pyMaintainer(m); std::string name = pyMaintainer["name"].str(); std::string email = pyMaintainer["email"].str(); @@ -239,23 +251,25 @@ void MetadataPy::setMaintainer(Py::Object args) } } -PyObject *MetadataPy::addMaintainer(PyObject *args) +PyObject* MetadataPy::addMaintainer(PyObject* args) { - const char *name = nullptr; - const char *email = nullptr; - if (!PyArg_ParseTuple(args, "ss", &name, &email)) + const char* name = nullptr; + const char* email = nullptr; + if (!PyArg_ParseTuple(args, "ss", &name, &email)) { throw Py::Exception(); + } getMetadataPtr()->addMaintainer(App::Meta::Contact(name, email)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeMaintainer(PyObject *args) +PyObject* MetadataPy::removeMaintainer(PyObject* args) { - const char *name = nullptr; - const char *email = nullptr; - if (!PyArg_ParseTuple(args, "ss", &name, &email)) + const char* name = nullptr; + const char* email = nullptr; + if (!PyArg_ParseTuple(args, "ss", &name, &email)) { throw Py::Exception(); + } getMetadataPtr()->removeMaintainer(App::Meta::Contact(name, email)); Py_INCREF(Py_None); return Py_None; @@ -266,7 +280,7 @@ Py::Object MetadataPy::getAuthor() const { auto authors = getMetadataPtr()->author(); Py::List pyAuthors; - for (const auto &a : authors) { + for (const auto& a : authors) { Py::Dict pyAuthor; pyAuthor["name"] = Py::String(a.name); pyAuthor["email"] = Py::String(a.email); @@ -277,13 +291,14 @@ Py::Object MetadataPy::getAuthor() const void MetadataPy::setAuthor(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearAuthor(); Py::List authors(list); - for (const auto &a : authors) { + for (const auto& a : authors) { Py::Dict pyAuthor(a); std::string name = pyAuthor["name"].str(); std::string email = pyAuthor["email"].str(); @@ -291,23 +306,25 @@ void MetadataPy::setAuthor(Py::Object args) } } -PyObject *MetadataPy::addAuthor(PyObject *args) +PyObject* MetadataPy::addAuthor(PyObject* args) { - const char *name = nullptr; - const char *email = nullptr; - if (!PyArg_ParseTuple(args, "ss", &name, &email)) + const char* name = nullptr; + const char* email = nullptr; + if (!PyArg_ParseTuple(args, "ss", &name, &email)) { throw Py::Exception(); + } getMetadataPtr()->addAuthor(App::Meta::Contact(name, email)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeAuthor(PyObject *args) +PyObject* MetadataPy::removeAuthor(PyObject* args) { - const char *name = nullptr; - const char *email = nullptr; - if (!PyArg_ParseTuple(args, "ss", &name, &email)) + const char* name = nullptr; + const char* email = nullptr; + if (!PyArg_ParseTuple(args, "ss", &name, &email)) { throw Py::Exception(); + } getMetadataPtr()->removeAuthor(App::Meta::Contact(name, email)); Py_INCREF(Py_None); return Py_None; @@ -317,7 +334,7 @@ Py::Object MetadataPy::getLicense() const { auto licenses = getMetadataPtr()->license(); Py::List pyLicenses; - for (const auto &lic : licenses) { + for (const auto& lic : licenses) { Py::Dict pyLicense; pyLicense["name"] = Py::String(lic.name); pyLicense["file"] = Py::String(lic.file.string()); @@ -328,13 +345,14 @@ Py::Object MetadataPy::getLicense() const void MetadataPy::setLicense(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearLicense(); Py::List licenses(list); - for (const auto &l : licenses) { + for (const auto& l : licenses) { Py::Dict pyLicense(l); std::string name = pyLicense["name"].str(); std::string path = pyLicense["file"].str(); @@ -342,23 +360,25 @@ void MetadataPy::setLicense(Py::Object args) } } -PyObject *MetadataPy::addLicense(PyObject *args) +PyObject* MetadataPy::addLicense(PyObject* args) { - const char *shortCode = nullptr; - const char *path = nullptr; - if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) + const char* shortCode = nullptr; + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) { throw Py::Exception(); + } getMetadataPtr()->addLicense(App::Meta::License(shortCode, path)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeLicense(PyObject *args) +PyObject* MetadataPy::removeLicense(PyObject* args) { - const char *shortCode = nullptr; - const char *path = nullptr; - if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) + const char* shortCode = nullptr; + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) { throw Py::Exception(); + } getMetadataPtr()->removeLicense(App::Meta::License(shortCode, path)); Py_INCREF(Py_None); return Py_None; @@ -368,20 +388,35 @@ Py::Object MetadataPy::getUrls() const { auto urls = getMetadataPtr()->url(); Py::List pyUrls; - for (const auto &url : urls) { + for (const auto& url : urls) { Py::Dict pyUrl; pyUrl["location"] = Py::String(url.location); switch (url.type) { - case Meta::UrlType::website: pyUrl["type"] = Py::String("website"); break; - case Meta::UrlType::repository: pyUrl["type"] = Py::String("repository"); break; - case Meta::UrlType::bugtracker: pyUrl["type"] = Py::String("bugtracker"); break; - case Meta::UrlType::readme: pyUrl["type"] = Py::String("readme"); break; - case Meta::UrlType::documentation: pyUrl["type"] = Py::String("documentation"); break; - case Meta::UrlType::discussion: pyUrl["type"] = Py::String("discussion"); break; - default: pyUrl["type"] = Py::String("unknown"); break; + case Meta::UrlType::website: + pyUrl["type"] = Py::String("website"); + break; + case Meta::UrlType::repository: + pyUrl["type"] = Py::String("repository"); + break; + case Meta::UrlType::bugtracker: + pyUrl["type"] = Py::String("bugtracker"); + break; + case Meta::UrlType::readme: + pyUrl["type"] = Py::String("readme"); + break; + case Meta::UrlType::documentation: + pyUrl["type"] = Py::String("documentation"); + break; + case Meta::UrlType::discussion: + pyUrl["type"] = Py::String("discussion"); + break; + default: + pyUrl["type"] = Py::String("unknown"); + break; } - if (url.type == Meta::UrlType::repository) + if (url.type == Meta::UrlType::repository) { pyUrl["branch"] = Py::String(url.branch); + } pyUrls.append(pyUrl); } return pyUrls; @@ -389,13 +424,14 @@ Py::Object MetadataPy::getUrls() const void MetadataPy::setUrls(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearUrl(); Py::List urls(list); - for (const auto &url : urls) { + for (const auto& url : urls) { Py::Dict pyUrl(url); std::string location = pyUrl["location"].str(); std::string typeAsString = pyUrl["type"].str(); @@ -431,52 +467,60 @@ void MetadataPy::setUrls(Py::Object args) App::Meta::Url urlFromStrings(const char* urlTypeCharStar, const char* link, const char* branch) { std::string urlTypeString(urlTypeCharStar); - App::Meta::UrlType urlType{App::Meta::UrlType::documentation}; - if (urlTypeString == "repository") + App::Meta::UrlType urlType {App::Meta::UrlType::documentation}; + if (urlTypeString == "repository") { urlType = App::Meta::UrlType::repository; - else if (urlTypeString == "bugtracker") + } + else if (urlTypeString == "bugtracker") { urlType = App::Meta::UrlType::bugtracker; - else if (urlTypeString == "documentation") + } + else if (urlTypeString == "documentation") { urlType = App::Meta::UrlType::documentation; - else if (urlTypeString == "readme") + } + else if (urlTypeString == "readme") { urlType = App::Meta::UrlType::readme; - else if (urlTypeString == "website") + } + else if (urlTypeString == "website") { urlType = App::Meta::UrlType::website; + } App::Meta::Url url(link, urlType); - if (urlType == App::Meta::UrlType::repository) + if (urlType == App::Meta::UrlType::repository) { url.branch = std::string(branch); + } return url; } -PyObject *MetadataPy::addUrl(PyObject *args) +PyObject* MetadataPy::addUrl(PyObject* args) { - const char *urlTypeCharStar = nullptr; - const char *link = nullptr; - const char *branch = nullptr; - if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) + const char* urlTypeCharStar = nullptr; + const char* link = nullptr; + const char* branch = nullptr; + if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) { throw Py::Exception(); + } getMetadataPtr()->addUrl(urlFromStrings(urlTypeCharStar, link, branch)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeUrl(PyObject *args) +PyObject* MetadataPy::removeUrl(PyObject* args) { - const char *urlTypeCharStar = nullptr; - const char *link = nullptr; - const char *branch = nullptr; - if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) + const char* urlTypeCharStar = nullptr; + const char* link = nullptr; + const char* branch = nullptr; + if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) { throw Py::Exception(); + } getMetadataPtr()->removeUrl(urlFromStrings(urlTypeCharStar, link, branch)); Py_INCREF(Py_None); return Py_None; } -Py::Object dependencyToPyObject(const Meta::Dependency &d) +Py::Object dependencyToPyObject(const Meta::Dependency& d) { Py::Dict pyDependency; pyDependency["package"] = Py::String(d.package); @@ -489,7 +533,7 @@ Py::Object dependencyToPyObject(const Meta::Dependency &d) pyDependency["optional"] = Py::Boolean(d.optional); switch (d.dependencyType) { case App::Meta::DependencyType::automatic: - pyDependency["type"] = Py::String ("automatic"); + pyDependency["type"] = Py::String("automatic"); break; case App::Meta::DependencyType::addon: pyDependency["type"] = Py::String("addon"); @@ -504,34 +548,45 @@ Py::Object dependencyToPyObject(const Meta::Dependency &d) return pyDependency; } -Meta::Dependency pyObjectToDependency(const Py::Object &d) +Meta::Dependency pyObjectToDependency(const Py::Object& d) { Py::Dict pyDependency(d); Meta::Dependency result; result.package = pyDependency["package"].str(); - if (pyDependency.hasKey("version_lt")) + if (pyDependency.hasKey("version_lt")) { result.version_lt = pyDependency["version_lt"].str(); - if (pyDependency.hasKey("version_lte")) + } + if (pyDependency.hasKey("version_lte")) { result.version_lte = pyDependency["version_lte"].str(); - if (pyDependency.hasKey("version_eq")) + } + if (pyDependency.hasKey("version_eq")) { result.version_eq = pyDependency["version_eq"].str(); - if (pyDependency.hasKey("version_gt")) + } + if (pyDependency.hasKey("version_gt")) { result.version_gt = pyDependency["version_gt"].str(); - if (pyDependency.hasKey("version_gte")) + } + if (pyDependency.hasKey("version_gte")) { result.version_gte = pyDependency["version_gte"].str(); - if (pyDependency.hasKey("condition")) + } + if (pyDependency.hasKey("condition")) { result.condition = pyDependency["condition"].str(); - if (pyDependency.hasKey("optional")) + } + if (pyDependency.hasKey("optional")) { result.optional = Py::Boolean(pyDependency["optional"]).as_bool(); + } if (pyDependency.hasKey("type")) { - if (pyDependency["type"].str() == Py::String("automatic")) + if (pyDependency["type"].str() == Py::String("automatic")) { result.dependencyType = App::Meta::DependencyType::automatic; - else if (pyDependency["type"].str() == Py::String("internal")) + } + else if (pyDependency["type"].str() == Py::String("internal")) { result.dependencyType = App::Meta::DependencyType::internal; - else if (pyDependency["type"].str() == Py::String("addon")) + } + else if (pyDependency["type"].str() == Py::String("addon")) { result.dependencyType = App::Meta::DependencyType::addon; - else if (pyDependency["type"].str() == Py::String("python")) + } + else if (pyDependency["type"].str() == Py::String("python")) { result.dependencyType = App::Meta::DependencyType::python; + } } return result; } @@ -540,7 +595,7 @@ Py::Object MetadataPy::getDepend() const { auto dependencies = getMetadataPtr()->depend(); Py::List pyDependencies; - for (const auto &d : dependencies) { + for (const auto& d : dependencies) { pyDependencies.append(dependencyToPyObject(d)); } return pyDependencies; @@ -548,34 +603,37 @@ Py::Object MetadataPy::getDepend() const void MetadataPy::setDepend(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearDepend(); Py::List deps(list); - for (const auto &dep : deps) { + for (const auto& dep : deps) { Py::Dict pyDep(dep); getMetadataPtr()->addDepend(pyObjectToDependency(pyDep)); } } -PyObject *MetadataPy::addDepend(PyObject *args) +PyObject* MetadataPy::addDepend(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->addDepend(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeDepend(PyObject *args) +PyObject* MetadataPy::removeDepend(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->removeDepend(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); @@ -586,7 +644,7 @@ Py::Object MetadataPy::getConflict() const { auto dependencies = getMetadataPtr()->conflict(); Py::List pyDependencies; - for (const auto &d : dependencies) { + for (const auto& d : dependencies) { pyDependencies.append(dependencyToPyObject(d)); } return pyDependencies; @@ -594,34 +652,37 @@ Py::Object MetadataPy::getConflict() const void MetadataPy::setConflict(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearConflict(); Py::List deps(list); - for (const auto &dep : deps) { + for (const auto& dep : deps) { Py::Dict pyDep(dep); getMetadataPtr()->addConflict(pyObjectToDependency(pyDep)); } } -PyObject *MetadataPy::addConflict(PyObject *args) +PyObject* MetadataPy::addConflict(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->addConflict(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeConflict(PyObject *args) +PyObject* MetadataPy::removeConflict(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->removeConflict(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); @@ -632,7 +693,7 @@ Py::Object MetadataPy::getReplace() const { auto dependencies = getMetadataPtr()->replace(); Py::List pyDependencies; - for (const auto &d : dependencies) { + for (const auto& d : dependencies) { pyDependencies.append(dependencyToPyObject(d)); } return pyDependencies; @@ -640,34 +701,37 @@ Py::Object MetadataPy::getReplace() const void MetadataPy::setReplace(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearReplace(); Py::List deps(list); - for (const auto &dep : deps) { + for (const auto& dep : deps) { Py::Dict pyDep(dep); getMetadataPtr()->addReplace(pyObjectToDependency(pyDep)); } } -PyObject *MetadataPy::addReplace(PyObject *args) +PyObject* MetadataPy::addReplace(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->addReplace(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeReplace(PyObject *args) +PyObject* MetadataPy::removeReplace(PyObject* args) { - PyObject *dictionary = nullptr; - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) + PyObject* dictionary = nullptr; + if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) { throw Py::Exception(); + } Py::Dict pyDep(dictionary); getMetadataPtr()->removeReplace(pyObjectToDependency(pyDep)); Py_INCREF(Py_None); @@ -680,7 +744,7 @@ Py::Object MetadataPy::getTag() const { auto tags = getMetadataPtr()->tag(); Py::List pyTags; - for (const auto &t : tags) { + for (const auto& t : tags) { pyTags.append(Py::String(t)); } return pyTags; @@ -688,33 +752,36 @@ Py::Object MetadataPy::getTag() const void MetadataPy::setTag(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearTag(); Py::List tags(list); - for (const auto &tag : tags) { + for (const auto& tag : tags) { Py::String pyTag(tag); getMetadataPtr()->addTag(pyTag.as_std_string()); } } -PyObject *MetadataPy::addTag(PyObject *args) +PyObject* MetadataPy::addTag(PyObject* args) { - const char *tag = nullptr; - if (!PyArg_ParseTuple(args, "s", &tag)) + const char* tag = nullptr; + if (!PyArg_ParseTuple(args, "s", &tag)) { throw Py::Exception(); + } getMetadataPtr()->addTag(tag); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeTag(PyObject *args) +PyObject* MetadataPy::removeTag(PyObject* args) { - const char *tag = nullptr; - if (!PyArg_ParseTuple(args, "s", &tag)) + const char* tag = nullptr; + if (!PyArg_ParseTuple(args, "s", &tag)) { throw Py::Exception(); + } getMetadataPtr()->removeTag(tag); Py_INCREF(Py_None); return Py_None; @@ -727,9 +794,10 @@ Py::Object MetadataPy::getIcon() const void MetadataPy::setIcon(Py::Object args) { - const char *name; - if (!PyArg_Parse(args.ptr(), "s", &name)) + const char* name; + if (!PyArg_Parse(args.ptr(), "s", &name)) { throw Py::Exception(); + } getMetadataPtr()->setIcon(name); } @@ -740,9 +808,10 @@ Py::Object MetadataPy::getClassname() const void MetadataPy::setClassname(Py::Object args) { - const char *name; - if (!PyArg_Parse(args.ptr(), "s", &name)) + const char* name; + if (!PyArg_Parse(args.ptr(), "s", &name)) { throw Py::Exception(); + } getMetadataPtr()->setClassname(name); } @@ -753,9 +822,10 @@ Py::Object MetadataPy::getSubdirectory() const void MetadataPy::setSubdirectory(Py::Object args) { - const char *name; - if (!PyArg_Parse(args.ptr(), "s", &name)) + const char* name; + if (!PyArg_Parse(args.ptr(), "s", &name)) { throw Py::Exception(); + } getMetadataPtr()->setSubdirectory(name); } @@ -763,7 +833,7 @@ Py::Object MetadataPy::getFile() const { auto files = getMetadataPtr()->file(); Py::List pyFiles; - for (const auto &f : files) { + for (const auto& f : files) { pyFiles.append(Py::String(f.string())); } return pyFiles; @@ -771,33 +841,36 @@ Py::Object MetadataPy::getFile() const void MetadataPy::setFile(Py::Object args) { - PyObject *list = nullptr; - if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) + PyObject* list = nullptr; + if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) { throw Py::Exception(); + } getMetadataPtr()->clearTag(); Py::List files(list); - for (const auto &file : files) { + for (const auto& file : files) { Py::String pyFile(file); getMetadataPtr()->addFile(pyFile.as_std_string()); } } -PyObject *MetadataPy::addFile(PyObject *args) +PyObject* MetadataPy::addFile(PyObject* args) { - const char *file = nullptr; - if (!PyArg_ParseTuple(args, "s", &file)) + const char* file = nullptr; + if (!PyArg_ParseTuple(args, "s", &file)) { throw Py::Exception(); + } getMetadataPtr()->addFile(file); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeFile(PyObject *args) +PyObject* MetadataPy::removeFile(PyObject* args) { - const char *file = nullptr; - if (!PyArg_ParseTuple(args, "s", &file)) + const char* file = nullptr; + if (!PyArg_ParseTuple(args, "s", &file)) { throw Py::Exception(); + } getMetadataPtr()->removeFile(file); Py_INCREF(Py_None); return Py_None; @@ -808,16 +881,16 @@ Py::Object MetadataPy::getContent() const { auto content = getMetadataPtr()->content(); std::set keys; - for (const auto &item : content) { + for (const auto& item : content) { keys.insert(item.first); } // For the Python, we'll use a dictionary of lists to store the content components: Py::Dict pyContent; - for (const auto &key : keys) { + for (const auto& key : keys) { Py::List pyContentForKey; auto elements = content.equal_range(key); - for (auto &element = elements.first; element != elements.second; ++element) { + for (auto& element = elements.first; element != elements.second; ++element) { auto contentMetadataItem = new MetadataPy(new Metadata(element->second)); pyContentForKey.append(Py::asObject(contentMetadataItem)); } @@ -828,36 +901,37 @@ Py::Object MetadataPy::getContent() const void MetadataPy::setContent(Py::Object arg) { - PyObject *obj = nullptr; - if (!PyArg_Parse(arg.ptr(), "O!", &PyList_Type, &obj)) + PyObject* obj = nullptr; + if (!PyArg_Parse(arg.ptr(), "O!", &PyList_Type, &obj)) { throw Py::Exception(); + } getMetadataPtr()->clearContent(); Py::Dict outerDict(obj); - for (const auto &pyContentType : outerDict) { + for (const auto& pyContentType : outerDict) { auto contentType = Py::String(pyContentType.first).as_std_string(); auto contentList = Py::List(pyContentType.second); for (const auto& contentItem : contentList) { - auto item = static_cast(contentItem.ptr()); + auto item = static_cast(contentItem.ptr()); getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr())); } } - } -PyObject *MetadataPy::getGenericMetadata(PyObject *args) +PyObject* MetadataPy::getGenericMetadata(PyObject* args) { - const char *name; - if (!PyArg_ParseTuple(args, "s", &name)) + const char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { return nullptr; + } auto gm = (*getMetadataPtr())[name]; Py::List pyGenericMetadata; - for (const auto &item : gm) { + for (const auto& item : gm) { Py::Dict pyItem; pyItem["contents"] = Py::String(item.contents); Py::Dict pyAttributes; - for (const auto &attribute : item.attributes) { + for (const auto& attribute : item.attributes) { pyAttributes[attribute.first] = Py::String(attribute.second); } pyItem["attributes"] = pyAttributes; @@ -873,14 +947,17 @@ Py::Object MetadataPy::getFreeCADMin() const void MetadataPy::setFreeCADMin(Py::Object args) { - char *version = nullptr; - PyObject *p = args.ptr(); - if (!PyArg_Parse(p, "z", &version)) + char* version = nullptr; + PyObject* p = args.ptr(); + if (!PyArg_Parse(p, "z", &version)) { throw Py::Exception(); - if (version) + } + if (version) { getMetadataPtr()->setFreeCADMin(App::Meta::Version(version)); - else + } + else { getMetadataPtr()->setFreeCADMin(App::Meta::Version()); + } } Py::Object MetadataPy::getFreeCADMax() const @@ -890,15 +967,18 @@ Py::Object MetadataPy::getFreeCADMax() const void MetadataPy::setFreeCADMax(Py::Object args) { - char *version = nullptr; - PyObject *p = args.ptr(); - if (!PyArg_Parse(p, "z", &version)) + char* version = nullptr; + PyObject* p = args.ptr(); + if (!PyArg_Parse(p, "z", &version)) { throw Py::Exception(); + } - if (version) + if (version) { getMetadataPtr()->setFreeCADMax(App::Meta::Version(version)); - else + } + else { getMetadataPtr()->setFreeCADMax(App::Meta::Version()); + } } Py::Object MetadataPy::getPythonMin() const @@ -908,30 +988,39 @@ Py::Object MetadataPy::getPythonMin() const void MetadataPy::setPythonMin(Py::Object args) { - char *version = nullptr; - PyObject *p = args.ptr(); - if (!PyArg_Parse(p, "z", &version)) throw Py::Exception(); - if (version) getMetadataPtr()->setPythonMin(App::Meta::Version(version)); - else + char* version = nullptr; + PyObject* p = args.ptr(); + if (!PyArg_Parse(p, "z", &version)) { + throw Py::Exception(); + } + if (version) { + getMetadataPtr()->setPythonMin(App::Meta::Version(version)); + } + else { getMetadataPtr()->setPythonMin(App::Meta::Version()); + } } -PyObject *MetadataPy::getFirstSupportedFreeCADVersion(PyObject *p) +PyObject* MetadataPy::getFirstSupportedFreeCADVersion(PyObject* p) { - if (!PyArg_ParseTuple(p, "")) + if (!PyArg_ParseTuple(p, "")) { return nullptr; + } // Short-circuit: if the toplevel sets a version, then the lower-levels are overridden - if (getMetadataPtr()->freecadmin() != App::Meta::Version()) + if (getMetadataPtr()->freecadmin() != App::Meta::Version()) { return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmin().str())); + } auto content = getMetadataPtr()->content(); auto result = App::Meta::Version(); - for (const auto &item : content) { + for (const auto& item : content) { auto minVersion = item.second.freecadmin(); - if (minVersion != App::Meta::Version()) - if (result == App::Meta::Version() || minVersion < result) + if (minVersion != App::Meta::Version()) { + if (result == App::Meta::Version() || minVersion < result) { result = minVersion; + } + } } if (result != App::Meta::Version()) { return Py::new_reference_to(Py::String(result.str())); @@ -942,22 +1031,26 @@ PyObject *MetadataPy::getFirstSupportedFreeCADVersion(PyObject *p) } } -PyObject *MetadataPy::getLastSupportedFreeCADVersion(PyObject *p) +PyObject* MetadataPy::getLastSupportedFreeCADVersion(PyObject* p) { - if (!PyArg_ParseTuple(p, "")) + if (!PyArg_ParseTuple(p, "")) { return nullptr; + } // Short-circuit: if the toplevel sets a version, then the lower-levels are overridden - if (getMetadataPtr()->freecadmax() != App::Meta::Version()) + if (getMetadataPtr()->freecadmax() != App::Meta::Version()) { return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmax().str())); + } auto content = getMetadataPtr()->content(); auto result = App::Meta::Version(); - for (const auto &item : content) { + for (const auto& item : content) { auto maxVersion = item.second.freecadmax(); - if (maxVersion != App::Meta::Version()) - if (result == App::Meta::Version() || maxVersion > result) + if (maxVersion != App::Meta::Version()) { + if (result == App::Meta::Version() || maxVersion > result) { result = maxVersion; + } + } } if (result != App::Meta::Version()) { return Py::new_reference_to(Py::String(result.str())); @@ -968,10 +1061,11 @@ PyObject *MetadataPy::getLastSupportedFreeCADVersion(PyObject *p) } } -PyObject *MetadataPy::supportsCurrentFreeCAD(PyObject *p) +PyObject* MetadataPy::supportsCurrentFreeCAD(PyObject* p) { - if (!PyArg_ParseTuple(p, "")) + if (!PyArg_ParseTuple(p, "")) { return nullptr; + } bool result = getMetadataPtr()->supportsCurrentFreeCAD(); return Py::new_reference_to(Py::Boolean(result)); @@ -979,28 +1073,32 @@ PyObject *MetadataPy::supportsCurrentFreeCAD(PyObject *p) PyObject* MetadataPy::addContentItem(PyObject* arg) { - char *contentType = nullptr; - PyObject *contentItem = nullptr; - if (!PyArg_ParseTuple(arg, "sO!", &contentType, &(App::MetadataPy::Type), &contentItem)) + char* contentType = nullptr; + PyObject* contentItem = nullptr; + if (!PyArg_ParseTuple(arg, "sO!", &contentType, &(App::MetadataPy::Type), &contentItem)) { return nullptr; + } - if (!contentItem || !contentType) + if (!contentItem || !contentType) { return nullptr; - auto item = static_cast(contentItem); + } + auto item = static_cast(contentItem); getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr())); Py_INCREF(Py_None); return Py_None; } -PyObject *MetadataPy::removeContentItem(PyObject *arg) +PyObject* MetadataPy::removeContentItem(PyObject* arg) { - char *contentType = nullptr; - char *contentName = nullptr; - if (!PyArg_ParseTuple(arg, "ss", &contentType, &contentName)) + char* contentType = nullptr; + char* contentName = nullptr; + if (!PyArg_ParseTuple(arg, "ss", &contentType, &contentName)) { return nullptr; - if (contentType && contentName) + } + if (contentType && contentName) { getMetadataPtr()->removeContentItem(contentType, contentName); + } Py_INCREF(Py_None); return Py_None; @@ -1008,9 +1106,10 @@ PyObject *MetadataPy::removeContentItem(PyObject *arg) PyObject* MetadataPy::write(PyObject* args) { - char *filename = nullptr; - if (!PyArg_ParseTuple(args, "s", &filename)) + char* filename = nullptr; + if (!PyArg_ParseTuple(args, "s", &filename)) { return nullptr; + } getMetadataPtr()->write(filename); Py_INCREF(Py_None); @@ -1018,12 +1117,12 @@ PyObject* MetadataPy::write(PyObject* args) } -PyObject *MetadataPy::getCustomAttributes(const char * /*attr*/) const +PyObject* MetadataPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } -int MetadataPy::setCustomAttributes(const char * /*attr*/, PyObject * /*obj*/) +int MetadataPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } diff --git a/src/App/Origin.cpp b/src/App/Origin.cpp index a79951669aa6..afc3c1349210 100644 --- a/src/App/Origin.cpp +++ b/src/App/Origin.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -36,7 +36,7 @@ #ifndef M_PI -# define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846 #endif using namespace App; @@ -44,100 +44,116 @@ using namespace App; PROPERTY_SOURCE(App::Origin, App::DocumentObject) -Origin::Origin() : extension(this) { - ADD_PROPERTY_TYPE ( OriginFeatures, (nullptr), 0, App::Prop_Hidden, - "Axis and baseplanes controlled by the origin" ); +Origin::Origin() + : extension(this) +{ + ADD_PROPERTY_TYPE(OriginFeatures, + (nullptr), + 0, + App::Prop_Hidden, + "Axis and baseplanes controlled by the origin"); - setStatus(App::NoAutoExpand,true); + setStatus(App::NoAutoExpand, true); extension.initExtension(this); } Origin::~Origin() = default; -App::OriginFeature *Origin::getOriginFeature( const char *role) const { - const auto & features = OriginFeatures.getValues (); - auto featIt = std::find_if (features.begin(), features.end(), - [role] (App::DocumentObject *obj) { - return obj->isDerivedFrom ( App::OriginFeature::getClassTypeId () ) && - strcmp (static_cast(obj)->Role.getValue(), role) == 0; - } ); +App::OriginFeature* Origin::getOriginFeature(const char* role) const +{ + const auto& features = OriginFeatures.getValues(); + auto featIt = std::find_if(features.begin(), features.end(), [role](App::DocumentObject* obj) { + return obj->isDerivedFrom(App::OriginFeature::getClassTypeId()) + && strcmp(static_cast(obj)->Role.getValue(), role) == 0; + }); if (featIt != features.end()) { - return static_cast(*featIt); - } else { + return static_cast(*featIt); + } + else { std::stringstream err; - err << "Origin \"" << getFullName () << "\" doesn't contain feature with role \"" - << role << '"'; - throw Base::RuntimeError ( err.str().c_str () ); + err << "Origin \"" << getFullName() << "\" doesn't contain feature with role \"" << role + << '"'; + throw Base::RuntimeError(err.str().c_str()); } } -App::Line *Origin::getAxis( const char *role ) const { - App::OriginFeature *feat = getOriginFeature (role); - if ( feat->isDerivedFrom(App::Line::getClassTypeId () ) ) { - return static_cast (feat); - } else { +App::Line* Origin::getAxis(const char* role) const +{ + App::OriginFeature* feat = getOriginFeature(role); + if (feat->isDerivedFrom(App::Line::getClassTypeId())) { + return static_cast(feat); + } + else { std::stringstream err; - err << "Origin \"" << getFullName () << "\" contains bad Axis object for role \"" - << role << '"'; - throw Base::RuntimeError ( err.str().c_str () ); + err << "Origin \"" << getFullName() << "\" contains bad Axis object for role \"" << role + << '"'; + throw Base::RuntimeError(err.str().c_str()); } } -App::Plane *Origin::getPlane( const char *role ) const { - App::OriginFeature *feat = getOriginFeature (role); - if ( feat->isDerivedFrom(App::Plane::getClassTypeId () ) ) { - return static_cast (feat); - } else { +App::Plane* Origin::getPlane(const char* role) const +{ + App::OriginFeature* feat = getOriginFeature(role); + if (feat->isDerivedFrom(App::Plane::getClassTypeId())) { + return static_cast(feat); + } + else { std::stringstream err; - err << "Origin \"" << getFullName () << "\" contains bad Plane object for role \"" - << role << '"'; - throw Base::RuntimeError ( err.str().c_str () ); + err << "Origin \"" << getFullName() << "\" contains bad Plane object for role \"" << role + << '"'; + throw Base::RuntimeError(err.str().c_str()); } } -bool Origin::hasObject (const DocumentObject *obj) const { - const auto & features = OriginFeatures.getValues (); - return std::find (features.begin(), features.end(), obj) != features.end (); +bool Origin::hasObject(const DocumentObject* obj) const +{ + const auto& features = OriginFeatures.getValues(); + return std::find(features.begin(), features.end(), obj) != features.end(); } -short Origin::mustExecute() const { - if (OriginFeatures.isTouched ()) { +short Origin::mustExecute() const +{ + if (OriginFeatures.isTouched()) { return 1; - } else { + } + else { return DocumentObject::mustExecute(); } } -App::DocumentObjectExecReturn *Origin::execute() { - try { // try to find all base axis and planes in the origin - for (const char* role: AxisRoles) { - App::Line *axis = getAxis (role); +App::DocumentObjectExecReturn* Origin::execute() +{ + try { // try to find all base axis and planes in the origin + for (const char* role : AxisRoles) { + App::Line* axis = getAxis(role); assert(axis); (void)axis; } - for (const char* role: PlaneRoles) { - App::Plane *plane = getPlane (role); + for (const char* role : PlaneRoles) { + App::Plane* plane = getPlane(role); assert(plane); (void)plane; } - } catch (const Base::Exception &ex) { - setError (); - return new App::DocumentObjectExecReturn ( ex.what () ); + } + catch (const Base::Exception& ex) { + setError(); + return new App::DocumentObjectExecReturn(ex.what()); } - return DocumentObject::execute (); + return DocumentObject::execute(); } -void Origin::setupObject () { - const static struct { +void Origin::setupObject() +{ + const static struct + { const Base::Type type; - const char *role; - const QString label; + const char* role; + const QString label; Base::Rotation rot; - } - setupData [] = { + } setupData[] = { // clang-format off {App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()}, {App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1,1,1), M_PI*2/3)}, @@ -148,39 +164,40 @@ void Origin::setupObject () { // clang-format on }; - App::Document *doc = getDocument (); + App::Document* doc = getDocument(); - std::vector links; - for (auto data: setupData) { - std::string objName = doc->getUniqueObjectName ( data.role ); - App::DocumentObject *featureObj = doc->addObject ( data.type.getName(), objName.c_str () ); + std::vector links; + for (auto data : setupData) { + std::string objName = doc->getUniqueObjectName(data.role); + App::DocumentObject* featureObj = doc->addObject(data.type.getName(), objName.c_str()); - assert ( featureObj && featureObj->isDerivedFrom ( App::OriginFeature::getClassTypeId () ) ); + assert(featureObj && featureObj->isDerivedFrom(App::OriginFeature::getClassTypeId())); - QByteArray byteArray = data.label.toUtf8(); + QByteArray byteArray = data.label.toUtf8(); featureObj->Label.setValue(byteArray.constData()); - App::OriginFeature *feature = static_cast ( featureObj ); - feature->Placement.setValue ( Base::Placement ( Base::Vector3d (), data.rot ) ); - feature->Role.setValue ( data.role ); + App::OriginFeature* feature = static_cast(featureObj); + feature->Placement.setValue(Base::Placement(Base::Vector3d(), data.rot)); + feature->Role.setValue(data.role); - links.push_back (feature); + links.push_back(feature); } - OriginFeatures.setValues (links); + OriginFeatures.setValues(links); } -void Origin::unsetupObject () { - const auto &objsLnk = OriginFeatures.getValues (); +void Origin::unsetupObject() +{ + const auto& objsLnk = OriginFeatures.getValues(); // Copy to set to assert we won't call methode more then one time for each object - std::set objs (objsLnk.begin(), objsLnk.end()); + std::set objs(objsLnk.begin(), objsLnk.end()); // Remove all controlled objects - for (auto obj: objs ) { + for (auto obj : objs) { // Check that previous deletes wasn't inderectly removed one of our objects - const auto &objsLnk = OriginFeatures.getValues (); - if ( std::find(objsLnk.begin(), objsLnk.end(), obj) != objsLnk.end()) { - if ( ! obj->isRemoving() ) { - obj->getDocument()->removeObject (obj->getNameInDocument()); + const auto& objsLnk = OriginFeatures.getValues(); + if (std::find(objsLnk.begin(), objsLnk.end(), obj) != objsLnk.end()) { + if (!obj->isRemoving()) { + obj->getDocument()->removeObject(obj->getNameInDocument()); } } } @@ -194,19 +211,25 @@ Origin::OriginExtension::OriginExtension(Origin* obj) Group.setStatus(Property::Transient, true); } -void Origin::OriginExtension::initExtension(ExtensionContainer* obj) { +void Origin::OriginExtension::initExtension(ExtensionContainer* obj) +{ App::GroupExtension::initExtension(obj); } -bool Origin::OriginExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyobj, Base::Matrix4D *mat, bool, int depth) const { +bool Origin::OriginExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyobj, + Base::Matrix4D* mat, + bool, + int depth) const +{ if (!subname || subname[0] == '\0') { return false; } // mapping of object name to role name std::string name(subname); - for (int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { if (name.rfind(Origin::AxisRoles[i], 0) == 0) { name = Origin::AxisRoles[i]; break; @@ -219,14 +242,17 @@ bool Origin::OriginExtension::extensionGetSubObject(DocumentObject *&ret, const try { ret = obj->getOriginFeature(name.c_str()); - if (!ret) + if (!ret) { return false; - const char *dot = strchr(subname, '.'); - if (dot) - subname = dot+1; - else + } + const char* dot = strchr(subname, '.'); + if (dot) { + subname = dot + 1; + } + else { subname = ""; - ret = ret->getSubObject(subname, pyobj, mat, true, depth+1); + } + ret = ret->getSubObject(subname, pyobj, mat, true, depth + 1); return true; } catch (const Base::Exception& e) { diff --git a/src/App/Origin.h b/src/App/Origin.h index ff4d1372aa1f..0f7f2110e45f 100644 --- a/src/App/Origin.h +++ b/src/App/Origin.h @@ -35,7 +35,7 @@ namespace App /** Base class of all geometric document objects. */ -class AppExport Origin : public App::DocumentObject +class AppExport Origin: public App::DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::Origin); Q_DECLARE_TR_FUNCTIONS(App::Origin) @@ -46,7 +46,8 @@ class AppExport Origin : public App::DocumentObject ~Origin() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderOrigin"; } @@ -56,58 +57,67 @@ class AppExport Origin : public App::DocumentObject */ ///@{ // returns X axis - App::Line *getX () const { - return getAxis (AxisRoles[0]); + App::Line* getX() const + { + return getAxis(AxisRoles[0]); } // returns Y axis - App::Line *getY () const { - return getAxis (AxisRoles[1]); + App::Line* getY() const + { + return getAxis(AxisRoles[1]); } // returns Z axis - App::Line *getZ () const { - return getAxis (AxisRoles[2]); + App::Line* getZ() const + { + return getAxis(AxisRoles[2]); } // returns XY plane - App::Plane *getXY () const { - return getPlane (PlaneRoles[0]); + App::Plane* getXY() const + { + return getPlane(PlaneRoles[0]); } // returns XZ plane - App::Plane *getXZ () const { - return getPlane (PlaneRoles[1]); + App::Plane* getXZ() const + { + return getPlane(PlaneRoles[1]); } // returns YZ plane - App::Plane *getYZ () const { - return getPlane (PlaneRoles[2]); + App::Plane* getYZ() const + { + return getPlane(PlaneRoles[2]); } /// Returns all axis objects to iterate on them - std::vector axes() const { - return { getX(), getY(), getZ() }; + std::vector axes() const + { + return {getX(), getY(), getZ()}; } /// Returns all base planes objects to iterate on them - std::vector planes() const { - return { getXY(), getXZ(), getYZ() }; + std::vector planes() const + { + return {getXY(), getXZ(), getYZ()}; } /// Returns all controlled objects (both planes and axis) to iterate on them - std::vector baseObjects() const { - return { getX(), getY(), getZ(), getXY(), getXZ(), getYZ() }; + std::vector baseObjects() const + { + return {getX(), getY(), getZ(), getXY(), getXZ(), getYZ()}; } /// Returns an axis by it's name - App::OriginFeature *getOriginFeature( const char* role ) const; + App::OriginFeature* getOriginFeature(const char* role) const; /// Returns an axis by it's name - App::Line *getAxis( const char* role ) const; + App::Line* getAxis(const char* role) const; /// Returns an axis by it's name - App::Plane *getPlane( const char* role ) const; + App::Plane* getPlane(const char* role) const; ///@} /// Returns true if the given object is part of the origin - bool hasObject (const DocumentObject *obj) const; + bool hasObject(const DocumentObject* obj) const; /// Returns the default bounding box of the origin (use this if you confused what should be s ) // TODO Delete me if not really needed (2015-09-01, Fat-Zer) @@ -126,27 +136,33 @@ class AppExport Origin : public App::DocumentObject protected: /// Checks integrity of the Origin - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; /// Creates all corresponding Axes and Planes objects for the origin if they aren't linked yet - void setupObject () override; + void setupObject() override; /// Removes all planes and axis if they are still linked to the document - void unsetupObject () override; + void unsetupObject() override; private: struct SetupData; - void setupOriginFeature (App::PropertyLink &featProp, const SetupData &data); + void setupOriginFeature(App::PropertyLink& featProp, const SetupData& data); - class OriginExtension : public GeoFeatureGroupExtension { + class OriginExtension: public GeoFeatureGroupExtension + { Origin* obj; + public: explicit OriginExtension(Origin* obj); void initExtension(ExtensionContainer* obj) override; - bool extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **, Base::Matrix4D *, bool, int) const override; + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject**, + Base::Matrix4D*, + bool, + int) const override; }; OriginExtension extension; }; -} //namespace App +} // namespace App -#endif // APP_Origin_H +#endif // APP_Origin_H diff --git a/src/App/OriginFeature.cpp b/src/App/OriginFeature.cpp index 2171207687f8..a3b79e000c98 100644 --- a/src/App/OriginFeature.cpp +++ b/src/App/OriginFeature.cpp @@ -35,7 +35,7 @@ PROPERTY_SOURCE(App::Line, App::OriginFeature) OriginFeature::OriginFeature() { - ADD_PROPERTY_TYPE ( Role, (""), 0, App::Prop_ReadOnly, "Role of the feature in the Origin" ) ; + ADD_PROPERTY_TYPE(Role, (""), 0, App::Prop_ReadOnly, "Role of the feature in the Origin"); // Set placement to read-only Placement.setStatus(Property::Hidden, true); @@ -43,18 +43,20 @@ OriginFeature::OriginFeature() OriginFeature::~OriginFeature() = default; -Origin * OriginFeature::getOrigin () { - App::Document *doc = getDocument(); - auto origins = doc->getObjectsOfType ( App::Origin::getClassTypeId() ); +Origin* OriginFeature::getOrigin() +{ + App::Document* doc = getDocument(); + auto origins = doc->getObjectsOfType(App::Origin::getClassTypeId()); - auto originIt= std::find_if (origins.begin(), origins.end(), [this] (DocumentObject *origin) { - assert ( origin->isDerivedFrom ( App::Origin::getClassTypeId() ) ); - return static_cast (origin)->hasObject (this); - } ); + auto originIt = std::find_if(origins.begin(), origins.end(), [this](DocumentObject* origin) { + assert(origin->isDerivedFrom(App::Origin::getClassTypeId())); + return static_cast(origin)->hasObject(this); + }); if (originIt == origins.end()) { return nullptr; - } else { - assert ( (*originIt)->isDerivedFrom ( App::Origin::getClassTypeId() ) ); - return static_cast (*originIt); + } + else { + assert((*originIt)->isDerivedFrom(App::Origin::getClassTypeId())); + return static_cast(*originIt); } } diff --git a/src/App/OriginFeature.h b/src/App/OriginFeature.h index e8dc7fa22d1c..f499da900f8e 100644 --- a/src/App/OriginFeature.h +++ b/src/App/OriginFeature.h @@ -36,6 +36,7 @@ class Origin; class AppExport OriginFeature: public App::GeoFeature { PROPERTY_HEADER_WITH_OVERRIDE(App::OriginFeature); + public: /// additional information about the feature usage (e.g. "BasePlane-XY" or "Axis-X" in a Origin) PropertyString Role; @@ -45,25 +46,31 @@ class AppExport OriginFeature: public App::GeoFeature ~OriginFeature() override; /// Finds the origin object this plane belongs to - App::Origin *getOrigin (); + App::Origin* getOrigin(); }; -class AppExport Plane: public App::OriginFeature { +class AppExport Plane: public App::OriginFeature +{ PROPERTY_HEADER_WITH_OVERRIDE(App::OriginFeature); + public: - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderPlane"; } }; -class AppExport Line: public App::OriginFeature { +class AppExport Line: public App::OriginFeature +{ PROPERTY_HEADER_WITH_OVERRIDE(App::OriginFeature); + public: - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderLine"; } }; -} //namespace App +} // namespace App #endif /* end of include guard: ORIGINFEATURE_H */ diff --git a/src/App/OriginGroupExtension.cpp b/src/App/OriginGroupExtension.cpp index 077c0e262f61..ed7ad3547b68 100644 --- a/src/App/OriginGroupExtension.cpp +++ b/src/App/OriginGroupExtension.cpp @@ -38,139 +38,172 @@ using namespace App; EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtension) -OriginGroupExtension::OriginGroupExtension () { +OriginGroupExtension::OriginGroupExtension() +{ initExtensionType(OriginGroupExtension::getExtensionClassTypeId()); - EXTENSION_ADD_PROPERTY_TYPE ( Origin, (nullptr), 0, App::Prop_Hidden, "Origin linked to the group" ); + EXTENSION_ADD_PROPERTY_TYPE(Origin, + (nullptr), + 0, + App::Prop_Hidden, + "Origin linked to the group"); Origin.setScope(LinkScope::Child); } -OriginGroupExtension::~OriginGroupExtension () = default; +OriginGroupExtension::~OriginGroupExtension() = default; -App::Origin *OriginGroupExtension::getOrigin () const { - App::DocumentObject *originObj = Origin.getValue (); +App::Origin* OriginGroupExtension::getOrigin() const +{ + App::DocumentObject* originObj = Origin.getValue(); - if ( !originObj ) { + if (!originObj) { std::stringstream err; - err << "Can't find Origin for \"" << getExtendedObject()->getFullName () << "\""; - throw Base::RuntimeError ( err.str().c_str () ); - - } else if (! originObj->isDerivedFrom ( App::Origin::getClassTypeId() ) ) { + err << "Can't find Origin for \"" << getExtendedObject()->getFullName() << "\""; + throw Base::RuntimeError(err.str().c_str()); + } + else if (!originObj->isDerivedFrom(App::Origin::getClassTypeId())) { std::stringstream err; - err << "Bad object \"" << originObj->getFullName () << "\"(" << originObj->getTypeId().getName() - << ") linked to the Origin of \"" << getExtendedObject()->getFullName () << "\""; - throw Base::RuntimeError ( err.str().c_str () ); - } else { - return static_cast ( originObj ); + err << "Bad object \"" << originObj->getFullName() << "\"(" + << originObj->getTypeId().getName() << ") linked to the Origin of \"" + << getExtendedObject()->getFullName() << "\""; + throw Base::RuntimeError(err.str().c_str()); + } + else { + return static_cast(originObj); } } -bool OriginGroupExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +bool OriginGroupExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { - App::DocumentObject *originObj = Origin.getValue (); - const char *dot; - if(originObj && originObj->isAttachedToDocument() && - subname && (dot=strchr(subname,'.'))) - { + App::DocumentObject* originObj = Origin.getValue(); + const char* dot; + if (originObj && originObj->isAttachedToDocument() && subname && (dot = strchr(subname, '.'))) { bool found; - if(subname[0] == '$') - found = std::string(subname+1,dot)==originObj->Label.getValue(); - else - found = std::string(subname,dot)==originObj->getNameInDocument(); - if(found) { - if(mat && transform) + if (subname[0] == '$') { + found = std::string(subname + 1, dot) == originObj->Label.getValue(); + } + else { + found = std::string(subname, dot) == originObj->getNameInDocument(); + } + if (found) { + if (mat && transform) { *mat *= const_cast(this)->placement().getValue().toMatrix(); - ret = originObj->getSubObject(dot+1,pyObj,mat,true,depth+1); + } + ret = originObj->getSubObject(dot + 1, pyObj, mat, true, depth + 1); return true; } } - return GeoFeatureGroupExtension::extensionGetSubObject(ret,subname,pyObj,mat,transform,depth); + return GeoFeatureGroupExtension::extensionGetSubObject(ret, + subname, + pyObj, + mat, + transform, + depth); } -App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObject* obj) { +App::DocumentObject* OriginGroupExtension::getGroupOfObject(const DocumentObject* obj) +{ - if(!obj) + if (!obj) { return nullptr; + } bool isOriginFeature = obj->isDerivedFrom(App::OriginFeature::getClassTypeId()); auto list = obj->getInList(); for (auto o : list) { - if(o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) + if (o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) { return o; + } else if (isOriginFeature && o->isDerivedFrom(App::Origin::getClassTypeId())) { auto result = getGroupOfObject(o); - if(result) + if (result) { return result; + } } } return nullptr; } -short OriginGroupExtension::extensionMustExecute() { - if (Origin.isTouched ()) { +short OriginGroupExtension::extensionMustExecute() +{ + if (Origin.isTouched()) { return 1; - } else { + } + else { return GeoFeatureGroupExtension::extensionMustExecute(); } } -App::DocumentObjectExecReturn *OriginGroupExtension::extensionExecute() { - try { // try to find all base axis and planes in the origin - getOrigin (); - } catch (const Base::Exception &ex) { - //getExtendedObject()->setError (); - return new App::DocumentObjectExecReturn ( ex.what () ); +App::DocumentObjectExecReturn* OriginGroupExtension::extensionExecute() +{ + try { // try to find all base axis and planes in the origin + getOrigin(); + } + catch (const Base::Exception& ex) { + // getExtendedObject()->setError (); + return new App::DocumentObjectExecReturn(ex.what()); } - return GeoFeatureGroupExtension::extensionExecute (); + return GeoFeatureGroupExtension::extensionExecute(); } -App::DocumentObject *OriginGroupExtension::getLocalizedOrigin(App::Document *doc) { - App::DocumentObject *originObject = doc->addObject ( "App::Origin", "Origin" ); +App::DocumentObject* OriginGroupExtension::getLocalizedOrigin(App::Document* doc) +{ + App::DocumentObject* originObject = doc->addObject("App::Origin", "Origin"); QByteArray byteArray = tr("Origin").toUtf8(); originObject->Label.setValue(byteArray.constData()); return originObject; } -void OriginGroupExtension::onExtendedSetupObject () { - App::Document *doc = getExtendedObject()->getDocument (); +void OriginGroupExtension::onExtendedSetupObject() +{ + App::Document* doc = getExtendedObject()->getDocument(); - App::DocumentObject *originObj = getLocalizedOrigin(doc); + App::DocumentObject* originObj = getLocalizedOrigin(doc); - assert ( originObj && originObj->isDerivedFrom ( App::Origin::getClassTypeId () ) ); - Origin.setValue (originObj); + assert(originObj && originObj->isDerivedFrom(App::Origin::getClassTypeId())); + Origin.setValue(originObj); - GeoFeatureGroupExtension::onExtendedSetupObject (); + GeoFeatureGroupExtension::onExtendedSetupObject(); } -void OriginGroupExtension::onExtendedUnsetupObject () { - App::DocumentObject *origin = Origin.getValue (); - if (origin && !origin->isRemoving ()) { - origin->getDocument ()->removeObject (origin->getNameInDocument()); +void OriginGroupExtension::onExtendedUnsetupObject() +{ + App::DocumentObject* origin = Origin.getValue(); + if (origin && !origin->isRemoving()) { + origin->getDocument()->removeObject(origin->getNameInDocument()); } - GeoFeatureGroupExtension::onExtendedUnsetupObject (); + GeoFeatureGroupExtension::onExtendedUnsetupObject(); } -void OriginGroupExtension::extensionOnChanged(const Property* p) { - if(p == &Origin) { - App::DocumentObject *owner = getExtendedObject(); - App::DocumentObject *origin = Origin.getValue(); +void OriginGroupExtension::extensionOnChanged(const Property* p) +{ + if (p == &Origin) { + App::DocumentObject* owner = getExtendedObject(); + App::DocumentObject* origin = Origin.getValue(); // Document::Importing indicates the object is being imported (i.e. // copied). So check the Origin ownership here to prevent copy without // dependency if (origin && owner && owner->getDocument() - && owner->getDocument()->testStatus(Document::Importing)) { + && owner->getDocument()->testStatus(Document::Importing)) { for (auto o : origin->getInList()) { - if(o != owner && o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) { - App::Document *document = owner->getDocument(); - // Temporarily reset 'Restoring' status to allow document to auto label new objects - Base::ObjectStatusLocker guard( - Document::Restoring, document, false); + if (o != owner + && o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) { + App::Document* document = owner->getDocument(); + // Temporarily reset 'Restoring' status to allow document to auto label new + // objects + Base::ObjectStatusLocker guard(Document::Restoring, + document, + false); Origin.setValue(getLocalizedOrigin(document)); FC_WARN("Reset origin in " << owner->getFullName()); return; @@ -183,83 +216,99 @@ void OriginGroupExtension::extensionOnChanged(const Property* p) { void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj) { - //we get all links and replace the origin objects if needed (subnames need not to change, they - //would stay the same) - std::vector< App::DocumentObject* > result; + // we get all links and replace the origin objects if needed (subnames need not to change, they + // would stay the same) + std::vector result; std::vector list; obj->getPropertyList(list); - for(App::Property* prop : list) { - if(prop->isDerivedFrom()) { + for (App::Property* prop : list) { + if (prop->isDerivedFrom()) { auto p = static_cast(prop); - if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId())) + if (!p->getValue() + || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId())) { continue; + } - p->setValue(getOrigin()->getOriginFeature(static_cast(p->getValue())->Role.getValue())); + p->setValue(getOrigin()->getOriginFeature( + static_cast(p->getValue())->Role.getValue())); } - else if(prop->isDerivedFrom()) { + else if (prop->isDerivedFrom()) { auto p = static_cast(prop); auto vec = p->getValues(); std::vector result; bool changed = false; - for(App::DocumentObject* o : vec) { - if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId())) + for (App::DocumentObject* o : vec) { + if (!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId())) { result.push_back(o); + } else { - result.push_back(getOrigin()->getOriginFeature(static_cast(o)->Role.getValue())); + result.push_back(getOrigin()->getOriginFeature( + static_cast(o)->Role.getValue())); changed = true; } } - if(changed) + if (changed) { static_cast(prop)->setValues(result); + } } - else if(prop->isDerivedFrom()) { + else if (prop->isDerivedFrom()) { auto p = static_cast(prop); - if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId())) + if (!p->getValue() + || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId())) { continue; + } std::vector subValues = p->getSubValues(); - p->setValue(getOrigin()->getOriginFeature(static_cast(p->getValue())->Role.getValue()), subValues); + p->setValue(getOrigin()->getOriginFeature( + static_cast(p->getValue())->Role.getValue()), + subValues); } - else if(prop->isDerivedFrom()) { + else if (prop->isDerivedFrom()) { auto p = static_cast(prop); auto vec = p->getSubListValues(); bool changed = false; - for(auto &v : vec) { - if(v.first && v.first->isDerivedFrom(App::OriginFeature::getClassTypeId())) { - v.first = getOrigin()->getOriginFeature(static_cast(v.first)->Role.getValue()); + for (auto& v : vec) { + if (v.first && v.first->isDerivedFrom(App::OriginFeature::getClassTypeId())) { + v.first = getOrigin()->getOriginFeature( + static_cast(v.first)->Role.getValue()); changed = true; } } - if(changed) + if (changed) { p->setSubListValues(vec); + } } } } -std::vector< DocumentObject* > OriginGroupExtension::addObjects(std::vector objs) { +std::vector OriginGroupExtension::addObjects(std::vector objs) +{ - for(auto obj : objs) + for (auto obj : objs) { relinkToOrigin(obj); + } return App::GeoFeatureGroupExtension::addObjects(objs); } -bool OriginGroupExtension::hasObject(const DocumentObject* obj, bool recursive) const { +bool OriginGroupExtension::hasObject(const DocumentObject* obj, bool recursive) const +{ - if(Origin.getValue() && (obj == getOrigin() || getOrigin()->hasObject(obj))) + if (Origin.getValue() && (obj == getOrigin() || getOrigin()->hasObject(obj))) { return true; + } return App::GroupExtension::hasObject(obj, recursive); } - // Python feature --------------------------------------------------------- -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::OriginGroupExtensionPython, App::OriginGroupExtension) // explicit template instantiation template class AppExport ExtensionPythonT>; -} +} // namespace App diff --git a/src/App/OriginGroupExtension.h b/src/App/OriginGroupExtension.h index 58a0341c98b3..779c67d783de 100644 --- a/src/App/OriginGroupExtension.h +++ b/src/App/OriginGroupExtension.h @@ -26,26 +26,28 @@ #include "GeoFeatureGroupExtension.h" #include "QCoreApplication" -namespace App { +namespace App +{ class Origin; /** * Represents an abstract placeable group of objects with an associated Origin */ -class AppExport OriginGroupExtension : public App::GeoFeatureGroupExtension +class AppExport OriginGroupExtension: public App::GeoFeatureGroupExtension { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::OriginGroupExtension); Q_DECLARE_TR_FUNCTIONS(App::OriginGroupExtension) public: - OriginGroupExtension (); - ~OriginGroupExtension () override; + OriginGroupExtension(); + ~OriginGroupExtension() override; /// Returns the origin link or throws an exception - App::Origin *getOrigin () const; + App::Origin* getOrigin() const; /// returns the type name of the ViewProvider - virtual const char* getViewProviderName () const { + virtual const char* getViewProviderName() const + { return "Gui::ViewProviderOriginGroup"; } @@ -54,10 +56,10 @@ class AppExport OriginGroupExtension : public App::GeoFeatureGroupExtension * In case this object is not part of any geoFeatureGroup, 0 is returned. * @param obj the object to search for */ - static DocumentObject* getGroupOfObject (const DocumentObject* obj); + static DocumentObject* getGroupOfObject(const DocumentObject* obj); /// Returns true on changing OriginFeature set - short extensionMustExecute () override; + short extensionMustExecute() override; /// Origin linked to the group PropertyLink Origin; @@ -68,26 +70,30 @@ class AppExport OriginGroupExtension : public App::GeoFeatureGroupExtension std::vector addObjects(std::vector obj) override; bool hasObject(const DocumentObject* obj, bool recursive = false) const override; - bool extensionGetSubObject(DocumentObject *&ret, const char *subname, PyObject **pyObj, - Base::Matrix4D *mat, bool transform, int depth) const override; + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const override; void extensionOnChanged(const Property* p) override; protected: /// Checks integrity of the Origin - App::DocumentObjectExecReturn *extensionExecute () override; + App::DocumentObjectExecReturn* extensionExecute() override; /// Creates the corresponding Origin object - void onExtendedSetupObject () override; + void onExtendedSetupObject() override; /// Removes all planes and axis if they are still linked to the document - void onExtendedUnsetupObject () override; + void onExtendedUnsetupObject() override; private: /// Creates a localized Origin object - App::DocumentObject *getLocalizedOrigin(App::Document *doc); + App::DocumentObject* getLocalizedOrigin(App::Document* doc); }; using OriginGroupExtensionPython = ExtensionPythonT>; -} /* App */ +} // namespace App #endif /* end of include guard: ORIGINGROUP_H_QHTU73IF */ diff --git a/src/App/OriginGroupExtensionPy.xml b/src/App/OriginGroupExtensionPy.xml index 8a44fa579d11..2b66cdf7f5a4 100644 --- a/src/App/OriginGroupExtensionPy.xml +++ b/src/App/OriginGroupExtensionPy.xml @@ -16,4 +16,3 @@ - diff --git a/src/App/OriginGroupExtensionPyImp.cpp b/src/App/OriginGroupExtensionPyImp.cpp index a7fc7c387010..f4021550ce54 100644 --- a/src/App/OriginGroupExtensionPyImp.cpp +++ b/src/App/OriginGroupExtensionPyImp.cpp @@ -35,7 +35,7 @@ std::string OriginGroupExtensionPy::representation() const return {""}; } -PyObject *OriginGroupExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* OriginGroupExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -44,5 +44,3 @@ int OriginGroupExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* { return 0; } - - diff --git a/src/App/Part.cpp b/src/App/Part.cpp index 07e80a78ee0f..68feeaa88b25 100644 --- a/src/App/Part.cpp +++ b/src/App/Part.cpp @@ -42,7 +42,7 @@ PROPERTY_SOURCE_WITH_EXTENSIONS(App::Part, App::GeoFeature) Part::Part() { - ADD_PROPERTY(Type,("")); + ADD_PROPERTY(Type, ("")); ADD_PROPERTY_TYPE(Material, (nullptr), 0, App::Prop_None, "The Material for this Part"); ADD_PROPERTY_TYPE(Meta, (), 0, App::Prop_None, "Map with additional meta information"); @@ -62,22 +62,25 @@ Part::Part() Part::~Part() = default; -static App::Part *_getPartOfObject(const DocumentObject *obj, - std::set *objset) +static App::Part* _getPartOfObject(const DocumentObject* obj, + std::set* objset) { // as a Part is a geofeaturegroup it must directly link to all // objects it contains, even if they are in additional groups etc. // But we still must call 'hasObject()' to exclude link brought in by // expressions. for (auto inObj : obj->getInList()) { - if (objset && !objset->insert(inObj).second) + if (objset && !objset->insert(inObj).second) { continue; + } auto group = inObj->getExtensionByType(true); - if(group && group->hasObject(obj)) { - if(inObj->isDerivedFrom(App::Part::getClassTypeId())) + if (group && group->hasObject(obj)) { + if (inObj->isDerivedFrom(App::Part::getClassTypeId())) { return static_cast(inObj); - else if (objset) + } + else if (objset) { return _getPartOfObject(inObj, objset); + } // Only one parent geofeature group per object, so break break; } @@ -86,35 +89,41 @@ static App::Part *_getPartOfObject(const DocumentObject *obj, return nullptr; } -App::Part *Part::getPartOfObject (const DocumentObject* obj, bool recursive) { - if (!recursive) +App::Part* Part::getPartOfObject(const DocumentObject* obj, bool recursive) +{ + if (!recursive) { return _getPartOfObject(obj, nullptr); - std::set objset; + } + std::set objset; objset.insert(obj); return _getPartOfObject(obj, &objset); } -PyObject *Part::getPyObject() +PyObject* Part::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new PartPy(this),true); + PythonObject = Py::Object(new PartPy(this), true); } return Py::new_reference_to(PythonObject); } -void Part::handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property *prop) +void Part::handleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + App::Property* prop) { // Migrate Material from App::PropertyMap to App::PropertyLink if (!strcmp(TypeName, "App::PropertyMap")) { App::PropertyMap oldvalue; oldvalue.Restore(reader); if (oldvalue.getSize()) { - auto oldprop = static_cast(addDynamicProperty("App::PropertyMap", "Material_old", "Base")); + auto oldprop = static_cast( + addDynamicProperty("App::PropertyMap", "Material_old", "Base")); oldprop->setValues(oldvalue.getValues()); } - } else { + } + else { App::GeoFeature::handleChangedPropertyType(reader, TypeName, prop); } } @@ -124,21 +133,21 @@ void Part::handleChangedPropertyType(Base::XMLReader &reader, const char *TypeNa // Not quite sure yet making Part derivable in Python is good Idea! // JR 2014 -//namespace App { +// namespace App { ///// @cond DOXERR -//PROPERTY_SOURCE_TEMPLATE(App::PartPython, App::Part) -//template<> const char* App::PartPython::getViewProviderName(void) const { -// return "Gui::ViewProviderPartPython"; -//} -//template<> PyObject* App::PartPython::getPyObject(void) { -// if (PythonObject.is(Py::_None())) { -// // ref counter is set to 1 -// PythonObject = Py::Object(new FeaturePythonPyT(this),true); -// } -// return Py::new_reference_to(PythonObject); -//} +// PROPERTY_SOURCE_TEMPLATE(App::PartPython, App::Part) +// template<> const char* App::PartPython::getViewProviderName(void) const { +// return "Gui::ViewProviderPartPython"; +// } +// template<> PyObject* App::PartPython::getPyObject(void) { +// if (PythonObject.is(Py::_None())) { +// // ref counter is set to 1 +// PythonObject = Py::Object(new FeaturePythonPyT(this),true); +// } +// return Py::new_reference_to(PythonObject); +// } ///// @endcond // //// explicit template instantiation -//template class AppExport FeaturePythonT; -//} +// template class AppExport FeaturePythonT; +// } diff --git a/src/App/Part.h b/src/App/Part.h index a40212fd728e..312f20b518dd 100644 --- a/src/App/Part.h +++ b/src/App/Part.h @@ -35,7 +35,7 @@ namespace App /** Base class of all geometric document objects. */ -class AppExport Part : public App::GeoFeature, public App::OriginGroupExtension +class AppExport Part: public App::GeoFeature, public App::OriginGroupExtension { PROPERTY_HEADER_WITH_EXTENSIONS(App::Part); @@ -44,26 +44,26 @@ class AppExport Part : public App::GeoFeature, public App::OriginGroupExtension PropertyString Type; /** @name base properties of all Assembly Items - * These properties correspond mostly to the meta information - * in the App::Document class - */ + * These properties correspond mostly to the meta information + * in the App::Document class + */ //@{ /// Id e.g. Part number - App::PropertyString Id; + App::PropertyString Id; /// unique identifier of the Item - App::PropertyUUID Uid; + App::PropertyUUID Uid; /// material descriptions - App::PropertyLink Material; + App::PropertyLink Material; /// Meta descriptions - App::PropertyMap Meta; + App::PropertyMap Meta; /** License string - * Holds the short license string for the Item, e.g. CC-BY - * for the Creative Commons license suit. - */ - App::PropertyString License; + * Holds the short license string for the Item, e.g. CC-BY + * for the Creative Commons license suit. + */ + App::PropertyString License; /// License description/contract URL - App::PropertyString LicenseURL; + App::PropertyString LicenseURL; //@} /** @name Visual properties */ @@ -80,12 +80,15 @@ class AppExport Part : public App::GeoFeature, public App::OriginGroupExtension ~Part() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderPart"; } - void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property *prop) override; + void handleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + App::Property* prop) override; /** * Returns the part which contains this object. @@ -93,14 +96,14 @@ class AppExport Part : public App::GeoFeature, public App::OriginGroupExtension * @param obj the object to search for * @param recursive: whether to recursively find any grand parent Part container */ - static App::Part* getPartOfObject (const DocumentObject* obj, bool recursive=true); + static App::Part* getPartOfObject(const DocumentObject* obj, bool recursive = true); - PyObject *getPyObject() override; + PyObject* getPyObject() override; }; -//using PartPython = App::FeaturePythonT; +// using PartPython = App::FeaturePythonT; -} //namespace App +} // namespace App -#endif // APP_Part_H +#endif // APP_Part_H diff --git a/src/App/PartPyImp.cpp b/src/App/PartPyImp.cpp index e595a18c82ac..ddfba841830e 100644 --- a/src/App/PartPyImp.cpp +++ b/src/App/PartPyImp.cpp @@ -35,7 +35,7 @@ std::string PartPy::representation() const return {""}; } -PyObject *PartPy::getCustomAttributes(const char* /*attr*/) const +PyObject* PartPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -44,4 +44,3 @@ int PartPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - diff --git a/src/App/Path.cpp b/src/App/Path.cpp index 39773c08925e..0665a316b6f8 100644 --- a/src/App/Path.cpp +++ b/src/App/Path.cpp @@ -28,7 +28,6 @@ using namespace App; -Path::Path(const std::vector &PathVector) - : _PathVector(PathVector) -{ -} +Path::Path(const std::vector& PathVector) + : _PathVector(PathVector) +{} diff --git a/src/App/Path.h b/src/App/Path.h index eb77a65af947..f40eab4f83f7 100644 --- a/src/App/Path.h +++ b/src/App/Path.h @@ -36,21 +36,22 @@ namespace App class AppExport Path { protected: - std::vector _PathVector; + std::vector _PathVector; public: /// Constructor Path() = default; - explicit Path(const std::vector & PathVector); + explicit Path(const std::vector& PathVector); virtual ~Path() = default; - const std::vector & getVector() const { + const std::vector& getVector() const + { return _PathVector; } }; -} //namespace App +} // namespace App -#endif // APP_Path_H +#endif // APP_Path_H diff --git a/src/App/Placement.cpp b/src/App/Placement.cpp index 6a47e88c8fa5..b3c0dabf2a92 100644 --- a/src/App/Placement.cpp +++ b/src/App/Placement.cpp @@ -42,16 +42,14 @@ Placement::Placement() = default; Placement::~Placement() = default; - // Python feature --------------------------------------------------------- -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::PlacementPython, App::Placement) -template<> const char* App::PlacementPython::getViewProviderName() const { - return "Gui::ViewProviderPlacementPython"; +template<> +const char* App::PlacementPython::getViewProviderName() const +{ + return "Gui::ViewProviderPlacementPython"; } template class AppExport FeaturePythonT; -} - - - - +} // namespace App diff --git a/src/App/Placement.h b/src/App/Placement.h index 39b18f99207f..fc1ebf07fec9 100644 --- a/src/App/Placement.h +++ b/src/App/Placement.h @@ -37,21 +37,20 @@ class AppExport Placement: public App::GeoFeature PROPERTY_HEADER_WITH_OVERRIDE(App::Placement); public: - /// Constructor - Placement(); - ~Placement() override; - - /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { - return "Gui::ViewProviderPlacement"; - } - - + /// Constructor + Placement(); + ~Placement() override; + + /// returns the type name of the ViewProvider + const char* getViewProviderName() const override + { + return "Gui::ViewProviderPlacement"; + } }; using PlacementPython = App::FeaturePythonT; -} //namespace App +} // namespace App #endif diff --git a/src/App/PreCompiled.cpp b/src/App/PreCompiled.cpp index cd345efad89d..7b200a1bf252 100644 --- a/src/App/PreCompiled.cpp +++ b/src/App/PreCompiled.cpp @@ -22,4 +22,3 @@ #include "PreCompiled.h" - diff --git a/src/App/PreCompiled.h b/src/App/PreCompiled.h index b421ee048b11..57cafc2a352e 100644 --- a/src/App/PreCompiled.h +++ b/src/App/PreCompiled.h @@ -27,12 +27,13 @@ // point at which warnings of overly long specifiers disabled #ifdef _MSC_VER -#pragma warning( disable : 4251 ) -#pragma warning( disable : 4273 ) -#pragma warning( disable : 4275 ) -#pragma warning( disable : 4482 ) // nonstandard extension used: enum 'App::ObjectStatus' used in qualified name -#pragma warning( disable : 4503 ) -#pragma warning( disable : 4786 ) // specifier longer then 255 chars +#pragma warning(disable : 4251) +#pragma warning(disable : 4273) +#pragma warning(disable : 4275) +#pragma warning(disable : 4482) // nonstandard extension used: enum 'App::ObjectStatus' used in + // qualified name +#pragma warning(disable : 4503) +#pragma warning(disable : 4786) // specifier longer then 255 chars #endif #ifdef FC_OS_WIN32 @@ -52,15 +53,15 @@ #include #ifdef FC_OS_WIN32 -# include -# include -# include +#include +#include +#include #endif #if defined(FC_OS_LINUX) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) -# include -# include -# include +#include +#include +#include #endif // Streams @@ -100,6 +101,6 @@ #include #include -#endif //_PreComp_ +#endif //_PreComp_ -#endif // APP_PRECOMPILED_H +#endif // APP_PRECOMPILED_H diff --git a/src/App/ProgramOptionsUtilities.h b/src/App/ProgramOptionsUtilities.h index 8024cf3a90c5..cba3bcaf0ba2 100644 --- a/src/App/ProgramOptionsUtilities.h +++ b/src/App/ProgramOptionsUtilities.h @@ -1,25 +1,25 @@ /*************************************************************************** -* Copyright (c) 2002 Jürgen Riegel * -* * -* 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 Library General Public License (LGPL) * -* as published by the Free Software Foundation; either version 2 of * -* the License, or (at your option) any later version. * -* for detail see the LICENCE text file. * -* * -* FreeCAD is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with FreeCAD; if not, write to the Free Software * -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -* USA * -* * -***************************************************************************/ + * Copyright (c) 2002 Jürgen Riegel * + * * + * 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 Library General Public License (LGPL) * + * as published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * for detail see the LICENCE text file. * + * * + * FreeCAD is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with FreeCAD; if not, write to the Free Software * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * USA * + * * + ***************************************************************************/ #ifndef PROGRAMOPTIONSUTILITIES_H #define PROGRAMOPTIONSUTILITIES_H @@ -28,12 +28,13 @@ #include #include -namespace App::Util{ +namespace App::Util +{ std::pair customSyntax(std::string_view strIn) { - if(strIn.size() < 2) { - return{}; + if (strIn.size() < 2) { + return {}; } char leadChr {strIn[0]}; @@ -53,7 +54,7 @@ std::pair customSyntax(std::string_view strIn) } #endif - if(rest == "widgetcount"){ + if (rest == "widgetcount") { return {rest, ""}; } @@ -73,11 +74,11 @@ std::pair customSyntax(std::string_view strIn) "title", "visual"}; - if(std::find(knowns.begin(), knowns.end(), rest) != knowns.end()) { + if (std::find(knowns.begin(), knowns.end(), rest) != knowns.end()) { return {rest, "null"}; } return {}; } -} // namespace -#endif// PROGRAMOPTIONSUTILITIES_H +} // namespace App::Util +#endif // PROGRAMOPTIONSUTILITIES_H diff --git a/src/App/ProjectFile.cpp b/src/App/ProjectFile.cpp index 28269368bc31..03dbac3df11a 100644 --- a/src/App/ProjectFile.cpp +++ b/src/App/ProjectFile.cpp @@ -64,12 +64,13 @@ XERCES_CPP_NAMESPACE_USE #endif using namespace App; -namespace { +namespace +{ class DocumentMetadata { public: explicit DocumentMetadata(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* xmlDocument) - : xmlDocument{xmlDocument} + : xmlDocument {xmlDocument} {} ProjectFile::Metadata getMetadata() const @@ -103,11 +104,13 @@ class DocumentMetadata private: void readProgramVersion() { - if (DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("Document").unicodeForm())) { + if (DOMNodeList* nodes = + xmlDocument->getElementsByTagName(XStr("Document").unicodeForm())) { for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNode* nameAttr = node->getAttributes()->getNamedItem(XStr("ProgramVersion").unicodeForm()); + DOMNode* nameAttr = + node->getAttributes()->getNamedItem(XStr("ProgramVersion").unicodeForm()); if (nameAttr) { std::string value = StrX(nameAttr->getNodeValue()).c_str(); metadata.programVersion = value; @@ -163,12 +166,14 @@ class DocumentMetadata static std::string readValue(DOMNode* node) { if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - if (DOMElement* child = static_cast(node)->getFirstElementChild()) { // NOLINT - if (DOMNode* nameAttr = child->getAttributes()->getNamedItem(XStr("value").unicodeForm())) { - std::string value = StrX(nameAttr->getNodeValue()).c_str(); - return value; - } - } + if (DOMElement* child = + static_cast(node)->getFirstElementChild()) { // NOLINT + if (DOMNode* nameAttr = + child->getAttributes()->getNamedItem(XStr("value").unicodeForm())) { + std::string value = StrX(nameAttr->getNodeValue()).c_str(); + return value; + } + } } return {}; @@ -178,7 +183,7 @@ class DocumentMetadata XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* xmlDocument; ProjectFile::Metadata metadata; }; -} +} // namespace ProjectFile::ProjectFile() : xmlDocument(nullptr) @@ -259,8 +264,8 @@ std::list ProjectFile::getObjects() const for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("Object").unicodeForm()); // NOLINT + DOMNodeList* objectList = static_cast(node)->getElementsByTagName( + XStr("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = @@ -291,8 +296,8 @@ std::list ProjectFile::getObjectsOfType(const Base::Type& typeId) c for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("Object").unicodeForm()); // NOLINT + DOMNodeList* objectList = static_cast(node)->getElementsByTagName( + XStr("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = @@ -311,9 +316,7 @@ std::list ProjectFile::getObjectsOfType(const Base::Type& typeId) c return names; } -bool ProjectFile::restoreObject(const std::string& name, - App::PropertyContainer* obj, - bool verbose) +bool ProjectFile::restoreObject(const std::string& name, App::PropertyContainer* obj, bool verbose) { Base::FileInfo fi(stdFile); Base::ifstream file(fi, std::ios::in | std::ios::binary); @@ -367,8 +370,8 @@ Base::Type ProjectFile::getTypeId(const std::string& name) const for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("Object").unicodeForm()); // NOLINT + DOMNodeList* objectList = static_cast(node)->getElementsByTagName( + XStr("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = @@ -388,8 +391,7 @@ Base::Type ProjectFile::getTypeId(const std::string& name) const return Base::Type::badType(); } -std::list -ProjectFile::getPropertyFiles(const std::string& name) const +std::list ProjectFile::getPropertyFiles(const std::string& name) const { // // @@ -409,8 +411,8 @@ ProjectFile::getPropertyFiles(const std::string& name) const for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("Object").unicodeForm()); // NOLINT + DOMNodeList* objectList = static_cast(node)->getElementsByTagName( + XStr("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* nameAttr = @@ -488,8 +490,8 @@ std::list ProjectFile::getInputFiles(const std::string& name) const for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("Object").unicodeForm()); // NOLINT + DOMNodeList* objectList = static_cast(node)->getElementsByTagName( + XStr("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* nameAttr = @@ -646,8 +648,7 @@ std::string ProjectFile::replaceInputFiles(const std::map& props) +std::string ProjectFile::replacePropertyFiles(const std::map& props) { // create a new zip file with the name '.' std::string uuid = Base::Uuid::createUuid(); diff --git a/src/App/ProjectFile.h b/src/App/ProjectFile.h index 597ccc72c89a..b9086c8d1220 100644 --- a/src/App/ProjectFile.h +++ b/src/App/ProjectFile.h @@ -35,7 +35,12 @@ #ifndef XERCES_CPP_NAMESPACE_BEGIN #define XERCES_CPP_NAMESPACE_QUALIFIER using namespace XERCES_CPP_NAMESPACE; -namespace XERCES_CPP_NAMESPACE { class DOMNode; class DOMElement; class DOMDocument; } +namespace XERCES_CPP_NAMESPACE +{ +class DOMNode; +class DOMElement; +class DOMDocument; +} // namespace XERCES_CPP_NAMESPACE #else XERCES_CPP_NAMESPACE_BEGIN class DOMDocument; @@ -210,6 +215,6 @@ class AppExport ProjectFile }; -} // namespace APP +} // namespace App #endif // APP_PROJECTFILE_H diff --git a/src/App/Range.cpp b/src/App/Range.cpp index 83bcc9d3b56e..22d243dcf7d3 100644 --- a/src/App/Range.cpp +++ b/src/App/Range.cpp @@ -40,7 +40,8 @@ using namespace App; const int App::CellAddress::MAX_ROWS = 16384; const int App::CellAddress::MAX_COLUMNS = 26 * 26 + 26; -namespace App { +namespace App +{ // From a given cell address the '$' must be at within the first // few characters bool maybeAbsolute(std::string_view address) @@ -50,9 +51,9 @@ bool maybeAbsolute(std::string_view address) address = address.substr(0, MAX_COLUMNS_LETTERS + 1); return address.find("$") != std::string_view::npos; } -} +} // namespace App -Range::Range(const char * range, bool normalize) +Range::Range(const char* range, bool normalize) { std::string from; std::string to; @@ -97,7 +98,7 @@ Range::Range(int _row_begin, int _col_begin, int _row_end, int _col_end, bool no col_curr = col_begin; } -Range::Range(const CellAddress &from, const CellAddress &to, bool normalize) +Range::Range(const CellAddress& from, const CellAddress& to, bool normalize) : row_begin(from.row()) , col_begin(from.col()) , row_end(to.row()) @@ -128,8 +129,9 @@ bool Range::next() return true; } if (col_curr < col_end) { - if (row_curr == row_end + 1) + if (row_curr == row_end + 1) { return false; + } row_curr = row_begin; ++col_curr; return true; @@ -138,14 +140,14 @@ bool Range::next() } /** - * @brief Decode a row specification into a 0-based integer. - * - * @param rowstr Row specified as a string, with "1" being the first row. - * - * @returns The row. - */ - -int App::decodeRow(const std::string &rowstr, bool silent) + * @brief Decode a row specification into a 0-based integer. + * + * @param rowstr Row specified as a string, with "1" being the first row. + * + * @returns The row. + */ + +int App::decodeRow(const std::string& rowstr, bool silent) { int row = validRow(rowstr); @@ -159,10 +161,11 @@ int App::decodeRow(const std::string &rowstr, bool silent) /** * Assumes well-formed input. A through ZZZ. 0-based output */ -int columnStringToNum(const std::string &colstr) { +int columnStringToNum(const std::string& colstr) +{ double out {0}; int pos {0}; - for (auto chr = colstr.crbegin(); chr != colstr.crend(); chr++){ + for (auto chr = colstr.crbegin(); chr != colstr.crend(); chr++) { out += (*chr - 'A' + 1) * std::pow(26, pos++); } @@ -170,15 +173,15 @@ int columnStringToNum(const std::string &colstr) { } /** - * @brief Decode a column name string into a 0-based integer. - * - * @param colstr input string. - * - * @returns The column. - * - */ - -int App::decodeColumn( const std::string &colstr, bool silent ) + * @brief Decode a column name string into a 0-based integer. + * + * @param colstr input string. + * + * @returns The column. + * + */ + +int App::decodeColumn(const std::string& colstr, bool silent) { if (validColumn(colstr)) { return columnStringToNum(colstr); @@ -192,19 +195,19 @@ int App::decodeColumn( const std::string &colstr, bool silent ) } /** - * @brief Determine whether a row specification is valid or not. - * - * @param rowstr Row specified as a string, with "1" being the first row. - * - * @returns 0 or positive on success, -1 on error. - */ - -int App::validRow(const std::string &rowstr) + * @brief Determine whether a row specification is valid or not. + * + * @param rowstr Row specified as a string, with "1" being the first row. + * + * @returns 0 or positive on success, -1 on error. + */ + +int App::validRow(const std::string& rowstr) { - char * end; + char* end; int i = strtol(rowstr.c_str(), &end, 10); - if (i <=0 || i > CellAddress::MAX_ROWS || *end) { + if (i <= 0 || i > CellAddress::MAX_ROWS || *end) { return -1; } @@ -212,30 +215,30 @@ int App::validRow(const std::string &rowstr) } /** - * @brief Determine if a string is a valid column specification. - * - * @param colstr input string. - * - * @returns true if valid, false if not. - * - */ - -bool App::validColumn( const std::string &colstr ) + * @brief Determine if a string is a valid column specification. + * + * @param colstr input string. + * + * @returns true if valid, false if not. + * + */ + +bool App::validColumn(const std::string& colstr) { return boost::regex_match(colstr, boost::regex("[A-Z]{1,3}")); } /** - * @brief Convert a string address into integer \a row and \a column. - * row and col are 0-based. - * - * This function will throw an exception if the specified \a address is invalid. - * - * @param strAddress Address to parse. - * - */ - -App::CellAddress App::stringToAddress(const char * strAddress, bool silent) + * @brief Convert a string address into integer \a row and \a column. + * row and col are 0-based. + * + * This function will throw an exception if the specified \a address is invalid. + * + * @param strAddress Address to parse. + * + */ + +App::CellAddress App::stringToAddress(const char* strAddress, bool silent) { assert(strAddress); @@ -243,24 +246,24 @@ App::CellAddress App::stringToAddress(const char * strAddress, bool silent) boost::cmatch cm; if (boost::regex_match(strAddress, cm, e)) { - bool absCol = (cm[1].first[0]=='$'); - std::string r,c; + bool absCol = (cm[1].first[0] == '$'); + std::string r, c; if (absCol) { - c = std::string(cm[1].first+1,cm[1].second); + c = std::string(cm[1].first + 1, cm[1].second); } else { - c = std::string(cm[1].first,cm[1].second); + c = std::string(cm[1].first, cm[1].second); } - bool absRow = (cm[2].first[0]=='$'); + bool absRow = (cm[2].first[0] == '$'); if (absRow) { - r = std::string(cm[2].first+1,cm[2].second); + r = std::string(cm[2].first + 1, cm[2].second); } else { - r = std::string(cm[2].first,cm[2].second); + r = std::string(cm[2].first, cm[2].second); } - return CellAddress(decodeRow(r,silent), decodeColumn(c,silent), absRow, absCol); + return CellAddress(decodeRow(r, silent), decodeColumn(c, silent), absRow, absCol); } else if (silent) { return CellAddress(); @@ -270,10 +273,10 @@ App::CellAddress App::stringToAddress(const char * strAddress, bool silent) } /** - * @brief Convert given \a cell address into its string representation. - * - * @returns Address given as a string. - */ + * @brief Convert given \a cell address into its string representation. + * + * @returns Address given as a string. + */ std::string App::CellAddress::toString(Cell cell) const { @@ -311,7 +314,8 @@ std::string App::CellAddress::toString(Cell cell) const * If the passed string is a valid and absolute cell address it will be assigned to this instance. * \return True if it's an absolute cell address and false otherwise */ -bool App::CellAddress::parseAbsoluteAddress(const char *address) { +bool App::CellAddress::parseAbsoluteAddress(const char* address) +{ if (maybeAbsolute(address)) { CellAddress addr = stringToAddress(address, true); if (addr.isValid()) { @@ -321,4 +325,3 @@ bool App::CellAddress::parseAbsoluteAddress(const char *address) { } return false; } - diff --git a/src/App/Range.h b/src/App/Range.h index 57b2f2ca8ad0..d30dce59dfc0 100644 --- a/src/App/Range.h +++ b/src/App/Range.h @@ -29,19 +29,22 @@ #include #endif -namespace App { +namespace App +{ struct CellAddress; -AppExport CellAddress stringToAddress(const char *strAddress, bool silent=false); -AppExport int decodeColumn(const std::string &colstr, bool silent=false); -AppExport int decodeRow(const std::string &rowstr, bool silent=false); -AppExport bool validColumn(const std::string &colstr); -AppExport int validRow(const std::string &rowstr); +AppExport CellAddress stringToAddress(const char* strAddress, bool silent = false); +AppExport int decodeColumn(const std::string& colstr, bool silent = false); +AppExport int decodeRow(const std::string& rowstr, bool silent = false); +AppExport bool validColumn(const std::string& colstr); +AppExport int validRow(const std::string& rowstr); -struct AppExport CellAddress { +struct AppExport CellAddress +{ // See call of ENABLE_BITMASK_OPERATORS - enum class Cell { + enum class Cell + { Absolute = 1, ShowRow = 2, ShowColumn = 4, @@ -49,41 +52,79 @@ struct AppExport CellAddress { ShowFull = Absolute | ShowRow | ShowColumn }; - explicit CellAddress(int row = -1, int col = -1, bool absRow=false, bool absCol=false) - : _row(row), _col(col), _absRow(absRow), _absCol(absCol) - { } + explicit CellAddress(int row = -1, int col = -1, bool absRow = false, bool absCol = false) + : _row(row) + , _col(col) + , _absRow(absRow) + , _absCol(absCol) + {} - explicit CellAddress(const char * address) { + explicit CellAddress(const char* address) + { *this = stringToAddress(address); } - explicit CellAddress(const std::string & address) { + explicit CellAddress(const std::string& address) + { *this = stringToAddress(address.c_str()); } - bool parseAbsoluteAddress(const char *txt); + bool parseAbsoluteAddress(const char* txt); - inline int row() const { return _row; } + inline int row() const + { + return _row; + } - inline int col() const { return _col; } + inline int col() const + { + return _col; + } - void setRow(int r, bool clip=false) { _row = (clip && r>=MAX_ROWS) ? MAX_ROWS-1 : r; } + void setRow(int r, bool clip = false) + { + _row = (clip && r >= MAX_ROWS) ? MAX_ROWS - 1 : r; + } - void setCol(int c, bool clip=false) { _col = (clip && c>=MAX_COLUMNS) ? MAX_COLUMNS-1 : c; } + void setCol(int c, bool clip = false) + { + _col = (clip && c >= MAX_COLUMNS) ? MAX_COLUMNS - 1 : c; + } - inline bool operator<(const CellAddress & other) const { return asInt() < other.asInt(); } + inline bool operator<(const CellAddress& other) const + { + return asInt() < other.asInt(); + } - inline bool operator>(const CellAddress & other) const { return asInt() > other.asInt(); } + inline bool operator>(const CellAddress& other) const + { + return asInt() > other.asInt(); + } - inline bool operator==(const CellAddress & other) const { return asInt() == other.asInt(); } + inline bool operator==(const CellAddress& other) const + { + return asInt() == other.asInt(); + } - inline bool operator!=(const CellAddress & other) const { return asInt() != other.asInt(); } + inline bool operator!=(const CellAddress& other) const + { + return asInt() != other.asInt(); + } - inline bool isValid() { return (row() >=0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); } + inline bool isValid() + { + return (row() >= 0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); + } - inline bool isAbsoluteRow() const { return _absRow; } + inline bool isAbsoluteRow() const + { + return _absRow; + } - inline bool isAbsoluteCol() const { return _absCol; } + inline bool isAbsoluteCol() const + { + return _absCol; + } std::string toString(Cell = Cell::ShowFull) const; @@ -94,8 +135,10 @@ struct AppExport CellAddress { static const int MAX_COLUMNS; protected: - - inline unsigned int asInt() const { return ((_row << 16) | _col); } + inline unsigned int asInt() const + { + return ((_row << 16) | _col); + } short _row; short _col; @@ -115,13 +158,14 @@ struct AppExport CellAddress { * */ -class AppExport Range { +class AppExport Range +{ public: - explicit Range(const char *range, bool normalize=false); + explicit Range(const char* range, bool normalize = false); - Range(int _row_begin, int _col_begin, int _row_end, int _col_end, bool normalize=false); + Range(int _row_begin, int _col_begin, int _row_end, int _col_end, bool normalize = false); - Range(const CellAddress & from, const CellAddress & to, bool normalize=false); + Range(const CellAddress& from, const CellAddress& to, bool normalize = false); bool next(); @@ -129,49 +173,87 @@ class AppExport Range { void normalize(); /** Current row */ - inline int row() const { return row_curr; } + inline int row() const + { + return row_curr; + } /** Current column */ - inline int column() const { return col_curr; } + inline int column() const + { + return col_curr; + } /** Row count */ - inline int rowCount() const { return row_end - row_begin + 1; } + inline int rowCount() const + { + return row_end - row_begin + 1; + } /** Column count */ - inline int colCount() const { return col_end - col_begin + 1; } + inline int colCount() const + { + return col_end - col_begin + 1; + } /** Position of start of range */ - inline CellAddress from() const { return CellAddress(row_begin, col_begin); } + inline CellAddress from() const + { + return CellAddress(row_begin, col_begin); + } /** Position of end of range */ - inline CellAddress to() const { return CellAddress(row_end, col_end); } + inline CellAddress to() const + { + return CellAddress(row_end, col_end); + } /** Start of range as a string */ - inline std::string fromCellString() const { return CellAddress(row_begin, col_begin).toString(); } + inline std::string fromCellString() const + { + return CellAddress(row_begin, col_begin).toString(); + } /** End of range as a string */ - inline std::string toCellString() const { return CellAddress(row_end, col_end).toString(); } + inline std::string toCellString() const + { + return CellAddress(row_end, col_end).toString(); + } /** Current cell as a string */ - inline std::string address() const { return CellAddress(row_curr, col_curr).toString(); } + inline std::string address() const + { + return CellAddress(row_curr, col_curr).toString(); + } /** The raneg as a string */ - inline std::string rangeString() const { - return CellAddress(row_begin, col_begin).toString() + ":" + CellAddress(row_end, col_end).toString(); + inline std::string rangeString() const + { + return CellAddress(row_begin, col_begin).toString() + ":" + + CellAddress(row_end, col_end).toString(); } - CellAddress operator*() const { return CellAddress(row_curr, col_curr); } + CellAddress operator*() const + { + return CellAddress(row_curr, col_curr); + } - inline bool operator<(const Range & other) const { - if(from() < other.from()) + inline bool operator<(const Range& other) const + { + if (from() < other.from()) { return true; - if(from() > other.from()) + } + if (from() > other.from()) { return false; + } return to() < other.to(); } /** Number of elements in range */ - inline int size() const { return (row_end - row_begin + 1) * (col_end - col_begin + 1); } + inline int size() const + { + return (row_end - row_begin + 1) * (col_end - col_begin + 1); + } private: int row_curr, col_curr; @@ -179,8 +261,8 @@ class AppExport Range { int row_end, col_end; }; -} +} // namespace App ENABLE_BITMASK_OPERATORS(App::CellAddress::Cell) -#endif // RANGE_H +#endif // RANGE_H diff --git a/src/App/Resources/translations/App_hr.ts b/src/App/Resources/translations/App_hr.ts index 65cef49df05f..a52952ced25b 100644 --- a/src/App/Resources/translations/App_hr.ts +++ b/src/App/Resources/translations/App_hr.ts @@ -7,7 +7,7 @@ Stores the last user choice of whether to apply CopyOnChange setup to all links that reference the same configurable object - Pamti posljednji izbor korisnika o tome treba li primijeniti postavljanje CopyOnChange + Pamti posljednji izbor korisnika o tome treba li primijeniti postavljanje CopyOnChange na sve veze koje referenciraju isti konfigurabilni objekt diff --git a/src/App/Resources/translations/App_tr.ts b/src/App/Resources/translations/App_tr.ts index 449fc8c94563..8376aad26ca3 100644 --- a/src/App/Resources/translations/App_tr.ts +++ b/src/App/Resources/translations/App_tr.ts @@ -7,7 +7,7 @@ Stores the last user choice of whether to apply CopyOnChange setup to all links that reference the same configurable object - Aynı yapılandırılabilir nesneye baÅŸvuran tüm baÄŸlantılara CopyOnChange kurulumunun uygulanıp + Aynı yapılandırılabilir nesneye baÅŸvuran tüm baÄŸlantılara CopyOnChange kurulumunun uygulanıp uygulanmayacağına iliÅŸkin son kullanıcı seçimini saklar diff --git a/src/App/SafeMode.cpp b/src/App/SafeMode.cpp index 63fbd7cd9020..72a065b5c542 100644 --- a/src/App/SafeMode.cpp +++ b/src/App/SafeMode.cpp @@ -30,9 +30,10 @@ #include "SafeMode.h" -static QTemporaryDir * tempDir = nullptr; +static QTemporaryDir* tempDir = nullptr; -static bool _createTemporaryBaseDir() { +static bool _createTemporaryBaseDir() +{ tempDir = new QTemporaryDir(); if (!tempDir->isValid()) { delete tempDir; @@ -43,7 +44,7 @@ static bool _createTemporaryBaseDir() { static void _replaceDirs() { - auto &config = App::GetApplication().Config(); + auto& config = App::GetApplication().Config(); auto const temp_base = tempDir->path().toStdString(); auto const dirs = { @@ -70,10 +71,12 @@ void SafeMode::StartSafeMode() } } -bool SafeMode::SafeModeEnabled() { +bool SafeMode::SafeModeEnabled() +{ return tempDir; } -void SafeMode::Destruct() { +void SafeMode::Destruct() +{ delete tempDir; } diff --git a/src/App/SafeMode.h b/src/App/SafeMode.h index 95a3749c3d4e..e2353d0e4ad5 100644 --- a/src/App/SafeMode.h +++ b/src/App/SafeMode.h @@ -23,8 +23,9 @@ #pragma once -namespace SafeMode { - AppExport bool SafeModeEnabled(); - AppExport void StartSafeMode(); - AppExport void Destruct(); -}; +namespace SafeMode +{ +AppExport bool SafeModeEnabled(); +AppExport void StartSafeMode(); +AppExport void Destruct(); +}; // namespace SafeMode diff --git a/src/App/StringHasher.cpp b/src/App/StringHasher.cpp index dd8960f93cfc..7cdc892dd168 100644 --- a/src/App/StringHasher.cpp +++ b/src/App/StringHasher.cpp @@ -210,7 +210,7 @@ void StringHasher::compact() pendings.pop_front(); // Try to erase the map entry for this StringID if (_hashes->right.erase(sid.value()) == 0U) { - continue;// If nothing was erased, there's nothing more to do + continue; // If nothing was erased, there's nothing more to do } sid._sid->_hasher = nullptr; sid._sid->unref(); @@ -403,10 +403,10 @@ StringIDRef StringHasher::getID(const Data::MappedName& name, const QVector 0) {// If the data had an index + if (res.id > 0) { // If the data had an index if (res.index != 0) { indexed.setIndex(res.index); - newStringID._data.resize(newStringID._data.lastIndexOf(':')+1); + newStringID._data.resize(newStringID._data.lastIndexOf(':') + 1); } int offset = newStringID.isPostfixEncoded() ? 1 : 0; // Search for the SID with that index @@ -612,7 +612,7 @@ void StringHasher::RestoreDocFile(Base::Reader& reader) void StringHasher::restoreStreamNew(std::istream& stream, std::size_t count) { - Base::TextInputStream asciiStream (stream); + Base::TextInputStream asciiStream(stream); _hashes->clear(); std::string content; boost::io::ios_flags_saver ifs(stream); @@ -708,8 +708,9 @@ void StringHasher::restoreStreamNew(std::istream& stream, std::size_t count) FC_THROWM(Base::RuntimeError, "Missing string prefix id"); } d._data = d._sids[offset]._sid->toString(0).c_str(); - if (d.isPrefixIDIndex()) + if (d.isPrefixIDIndex()) { d._data += ":"; + } } else { stream >> content; @@ -777,7 +778,7 @@ size_t StringHasher::count() const { size_t count = 0; for (auto& hasher : _hashes->right) { - if (hasher.second->isMarked() || hasher.second->isPersistent() ) { + if (hasher.second->isMarked() || hasher.second->isPersistent()) { ++count; } } @@ -808,8 +809,9 @@ void StringHasher::Restore(Base::XMLReader& reader) std::size_t count = reader.getAttributeAsUnsigned("count"); if (newTag) { try { - restoreStreamNew(reader.beginCharStream(), count); - } catch (const Base::Exception &e) { + restoreStreamNew(reader.beginCharStream(), count); + } + catch (const Base::Exception& e) { e.ReportException(); FC_ERR("Failed to restore string table: full-document recompute strongly recommended."); } diff --git a/src/App/StringHasher.h b/src/App/StringHasher.h index 1b65b3479529..bc4491d02b85 100644 --- a/src/App/StringHasher.h +++ b/src/App/StringHasher.h @@ -76,7 +76,7 @@ using StringHasherRef = Base::Reference; */ class AppExport StringID: public Base::BaseClass, public Base::Handled { - TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT + TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT public: /// Flag of the stored string data @@ -119,15 +119,15 @@ class AppExport StringID: public Base::BaseClass, public Base::Handled * User code is not supposed to create StringID directly, but through StringHasher::getID() */ StringID(long id, QByteArray data, const Flags& flags = Flag::None) - : _id(id), - _data(std::move(data)), - _flags(flags) + : _id(id) + , _data(std::move(data)) + , _flags(flags) {} /// Constructs an empty StringID StringID() - : _id(0), - _flags(Flag::None) + : _id(0) + , _flags(Flag::None) {} StringID(const StringID& other) = delete; @@ -327,8 +327,8 @@ class StringIDRef /// Default construction results in an empty StringIDRef object: it will evaluate to boolean /// "false" if queried. StringIDRef() - : _sid(nullptr), - _index(0) + : _sid(nullptr) + , _index(0) {} /// Standard construction from a heap-allocated StringID. This reference-counting class manages @@ -337,8 +337,8 @@ class StringIDRef /// \param stringID A pointer to a StringID allocated with "new" /// \param index (optional) An index value to store along with the StringID. Defaults to zero. StringIDRef(StringID* stringID, int index = 0) - : _sid(stringID), - _index(index) + : _sid(stringID) + , _index(index) { if (_sid) { _sid->ref(); @@ -347,8 +347,8 @@ class StringIDRef /// Copy construction results in an incremented reference count for the stored StringID StringIDRef(const StringIDRef& other) - : _sid(other._sid), - _index(other._index) + : _sid(other._sid) + , _index(other._index) { if (_sid) { _sid->ref(); @@ -358,15 +358,15 @@ class StringIDRef /// Move construction does NOT increase the reference count of the StringID (instead, it /// invalidates the pointer in the moved object). StringIDRef(StringIDRef&& other) noexcept - : _sid(other._sid), - _index(other._index) + : _sid(other._sid) + , _index(other._index) { other._sid = nullptr; } StringIDRef(const StringIDRef& other, int index) - : _sid(other._sid), - _index(index) + : _sid(other._sid) + , _index(index) { if (_sid) { _sid->ref(); @@ -582,12 +582,12 @@ class StringIDRef bool isMarked() const { - return _sid && _sid->isMarked();// NOLINT + return _sid && _sid->isMarked(); // NOLINT } bool isFromSameHasher(const StringHasherRef& hasher) const { - return _sid && _sid->isFromSameHasher(hasher);// NOLINT + return _sid && _sid->isFromSameHasher(hasher); // NOLINT } StringHasherRef getHasher() const @@ -633,7 +633,7 @@ class StringIDRef class AppExport StringHasher: public Base::Persistence, public Base::Handled { - TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT + TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT public: StringHasher(); @@ -778,10 +778,11 @@ class AppExport StringHasher: public Base::Persistence, public Base::Handled void restoreStreamNew(std::istream& stream, std::size_t count); private: - std::unique_ptr _hashes;///< Bidirectional map of StringID and its index (a long int). + std::unique_ptr + _hashes; ///< Bidirectional map of StringID and its index (a long int). mutable std::string _filename; }; -}// namespace App +} // namespace App ENABLE_BITMASK_OPERATORS(App::StringID::Flag) ENABLE_BITMASK_OPERATORS(App::StringHasher::Option) @@ -828,6 +829,6 @@ inline void StringID::setPersistent(bool enable) { _flags.setFlag(Flag::Persistent, enable); } -}// namespace App +} // namespace App -#endif// APP_STRING_ID_H +#endif // APP_STRING_ID_H diff --git a/src/App/StringHasherPy.xml b/src/App/StringHasherPy.xml index d7df2b0e256f..ff7d8e1dbf32 100644 --- a/src/App/StringHasherPy.xml +++ b/src/App/StringHasherPy.xml @@ -1,13 +1,13 @@ - @@ -25,7 +25,7 @@ If the input is text, return a StringID object that is unique within this hasher StringID object is reference counted. The hasher may only save hash ID's that are used. If the input is an integer, then the hasher will try to find the StringID object stored -with the same integer value. +with the same integer value. base64: indicate if the input 'txt' is base64 encoded binary data @@ -68,4 +68,3 @@ base64: indicate if the input 'txt' is base64 encoded binary data - diff --git a/src/App/StringHasherPyImp.cpp b/src/App/StringHasherPyImp.cpp index cae36bce9f0e..4581bf5fed28 100644 --- a/src/App/StringHasherPyImp.cpp +++ b/src/App/StringHasherPyImp.cpp @@ -1,24 +1,24 @@ /**************************************************************************** -* Copyright (c) 2018 Zheng Lei (realthunder) * -* * -* 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 * -* * -****************************************************************************/ + * Copyright (c) 2018 Zheng Lei (realthunder) * + * * + * 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" @@ -38,7 +38,7 @@ std::string StringHasherPy::representation() const return str.str(); } -PyObject *StringHasherPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* StringHasherPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { return new StringHasherPy(new StringHasher); } @@ -46,7 +46,7 @@ PyObject *StringHasherPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // constructor method int StringHasherPy::PyInit(PyObject* args, PyObject* kwds) { - static const std::array kwlist {nullptr}; + static const std::array kwlist {nullptr}; if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "", kwlist)) { return -1; } @@ -55,9 +55,9 @@ int StringHasherPy::PyInit(PyObject* args, PyObject* kwds) } -PyObject* StringHasherPy::isSame(PyObject *args) +PyObject* StringHasherPy::isSame(PyObject* args) { - PyObject *other; + PyObject* other; if (!PyArg_ParseTuple(args, "O!", &StringHasherPy::Type, &other)) { return nullptr; } @@ -65,16 +65,17 @@ PyObject* StringHasherPy::isSame(PyObject *args) auto otherHasher = static_cast(other)->getStringHasherPtr(); bool same = getStringHasherPtr() == otherHasher; - return PyBool_FromLong(same ? 1 : 0); + return PyBool_FromLong(same ? 1 : 0); } -PyObject* StringHasherPy::getID(PyObject *args) +PyObject* StringHasherPy::getID(PyObject* args) { long id; int index = 0; if (PyArg_ParseTuple(args, "l|i", &id, &index)) { if (id > 0) { - PY_TRY { + PY_TRY + { auto sid = getStringHasherPtr()->getID(id, index); if (!sid) { Py_Return; @@ -91,19 +92,20 @@ PyObject* StringHasherPy::getID(PyObject *args) } PyErr_Clear(); - PyObject *value = nullptr; - PyObject *base64 = Py_False; + PyObject* value = nullptr; + PyObject* base64 = Py_False; if (PyArg_ParseTuple(args, "O!|O!", &PyUnicode_Type, &value, &PyBool_Type, &base64)) { - PY_TRY { + PY_TRY + { std::string txt = PyUnicode_AsUTF8(value); QByteArray data; StringIDRef sid; if (PyObject_IsTrue(base64)) { - data = QByteArray::fromBase64(QByteArray::fromRawData(txt.c_str(),txt.size())); - sid = getStringHasherPtr()->getID(data,true); + data = QByteArray::fromBase64(QByteArray::fromRawData(txt.c_str(), txt.size())); + sid = getStringHasherPtr()->getID(data, true); } else { - sid = getStringHasherPtr()->getID(txt.c_str(),txt.size()); + sid = getStringHasherPtr()->getID(txt.c_str(), txt.size()); } return sid.getPyObject(); @@ -111,8 +113,9 @@ PyObject* StringHasherPy::getID(PyObject *args) PY_CATCH; } - PyErr_SetString(PyExc_TypeError, "Positive integer and optional integer or " - "string and optional boolean is required"); + PyErr_SetString(PyExc_TypeError, + "Positive integer and optional integer or " + "string and optional boolean is required"); return nullptr; } @@ -149,14 +152,14 @@ void StringHasherPy::setThreshold(Py::Long value) Py::Dict StringHasherPy::getTable() const { Py::Dict dict; - for (const auto &v : getStringHasherPtr()->getIDMap()) { + for (const auto& v : getStringHasherPtr()->getIDMap()) { dict.setItem(Py::Long(v.first), Py::String(v.second.dataToText())); } return dict; } -PyObject *StringHasherPy::getCustomAttributes(const char* /*attr*/) const +PyObject* StringHasherPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/App/StringIDPy.xml b/src/App/StringIDPy.xml index eb43002f4007..de77d7c97a62 100644 --- a/src/App/StringIDPy.xml +++ b/src/App/StringIDPy.xml @@ -1,13 +1,13 @@ - @@ -62,4 +62,3 @@ - diff --git a/src/App/StringIDPyImp.cpp b/src/App/StringIDPyImp.cpp index 549b71f1c8c4..d81b2f29df99 100644 --- a/src/App/StringIDPyImp.cpp +++ b/src/App/StringIDPyImp.cpp @@ -1,24 +1,24 @@ /*************************************************************************** -* Copyright (c) 2018 Zheng Lei (realthunder) * -* * -* 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 * -* * -****************************************************************************/ + * Copyright (c) 2018 Zheng Lei (realthunder) * + * * + * 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" @@ -35,16 +35,16 @@ std::string StringIDPy::representation() const return getStringIDPtr()->toString(this->_index); } -PyObject* StringIDPy::isSame(PyObject *args) +PyObject* StringIDPy::isSame(PyObject* args) { - PyObject *other = nullptr; + PyObject* other = nullptr; if (!PyArg_ParseTuple(args, "O!", &StringIDPy::Type, &other)) { return nullptr; } - auto *otherPy = static_cast(other); - bool same = (otherPy->getStringIDPtr() == this->getStringIDPtr()) - && (otherPy->_index == this->_index); + auto* otherPy = static_cast(other); + bool same = + (otherPy->getStringIDPtr() == this->getStringIDPtr()) && (otherPy->_index == this->_index); return PyBool_FromLong(same ? 1 : 0); } @@ -57,7 +57,7 @@ Py::Long StringIDPy::getValue() const Py::List StringIDPy::getRelated() const { Py::List list; - for (const auto &id : getStringIDPtr()->relatedIDs()) { + for (const auto& id : getStringIDPtr()->relatedIDs()) { list.append(Py::Long(id.value())); } @@ -89,7 +89,7 @@ void StringIDPy::setIndex(Py::Long index) this->_index = index; } -PyObject *StringIDPy::getCustomAttributes(const char* /*attr*/) const +PyObject* StringIDPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/App/SuppressibleExtension.cpp b/src/App/SuppressibleExtension.cpp index 9c2348f8bee4..5add18392b3c 100644 --- a/src/App/SuppressibleExtension.cpp +++ b/src/App/SuppressibleExtension.cpp @@ -29,7 +29,8 @@ #include "SuppressibleExtensionPy.h" -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE(App::SuppressibleExtension, App::DocumentObjectExtension) @@ -43,19 +44,24 @@ template class AppExport ExtensionPythonT -class SuppressibleExtensionPythonT : public ExtensionT { +class SuppressibleExtensionPythonT: public ExtensionT +{ public: - SuppressibleExtensionPythonT() = default; ~SuppressibleExtensionPythonT() override = default; }; -using SuppressibleExtensionPython = ExtensionPythonT>; +using SuppressibleExtensionPython = + ExtensionPythonT>; -} //namespace App +} // namespace App -#endif // SUPPRESSIBLEEXTENSION_H +#endif // SUPPRESSIBLEEXTENSION_H diff --git a/src/App/SuppressibleExtensionPyImp.cpp b/src/App/SuppressibleExtensionPyImp.cpp index 3a2c99a11718..d6e4053f8a80 100644 --- a/src/App/SuppressibleExtensionPyImp.cpp +++ b/src/App/SuppressibleExtensionPyImp.cpp @@ -38,7 +38,7 @@ std::string SuppressibleExtensionPy::representation() const return {""}; } -PyObject *SuppressibleExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* SuppressibleExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/App/TextDocument.cpp b/src/App/TextDocument.cpp index 24cb355e3b1a..7d3d30d0bfbb 100644 --- a/src/App/TextDocument.cpp +++ b/src/App/TextDocument.cpp @@ -33,17 +33,17 @@ PROPERTY_SOURCE(App::TextDocument, App::DocumentObject) TextDocument::TextDocument() { - ADD_PROPERTY_TYPE( - Text, (""), 0, App::Prop_Hidden, - "Content of the document."); + ADD_PROPERTY_TYPE(Text, (""), 0, App::Prop_Hidden, "Content of the document."); } void TextDocument::onChanged(const Property* prop) { - if (prop == &Text) + if (prop == &Text) { textChanged(); - else if (prop == &Label) + } + else if (prop == &Label) { labelChanged(); + } DocumentObject::onChanged(prop); } @@ -52,12 +52,12 @@ const char* TextDocument::getViewProviderName() const return "Gui::ViewProviderTextDocument"; } -boost::signals2::connection TextDocument::connectText(const TextSlot &sub) +boost::signals2::connection TextDocument::connectText(const TextSlot& sub) { return textChanged.connect(sub); } -boost::signals2::connection TextDocument::connectLabel(const TextSlot &sub) +boost::signals2::connection TextDocument::connectLabel(const TextSlot& sub) { return labelChanged.connect(sub); } diff --git a/src/App/TextDocument.h b/src/App/TextDocument.h index 702313eb3f24..fb475921980c 100644 --- a/src/App/TextDocument.h +++ b/src/App/TextDocument.h @@ -31,10 +31,12 @@ namespace App { -class AppExport TextDocument : public App::DocumentObject { +class AppExport TextDocument: public App::DocumentObject +{ PROPERTY_HEADER_WITH_OVERRIDE(App::TextDocument); + public: - using TextSignal = boost::signals2::signal; + using TextSignal = boost::signals2::signal; using TextSlot = TextSignal::slot_type; PropertyString Text; @@ -45,15 +47,15 @@ class AppExport TextDocument : public App::DocumentObject { void onChanged(const Property* prop) override; const char* getViewProviderName() const override; - boost::signals2::connection connectText(const TextSlot &sub); - boost::signals2::connection connectLabel(const TextSlot &sub); + boost::signals2::connection connectText(const TextSlot& sub); + boost::signals2::connection connectLabel(const TextSlot& sub); private: TextSignal textChanged; TextSignal labelChanged; }; -} +} // namespace App #endif diff --git a/src/App/TransactionalObject.cpp b/src/App/TransactionalObject.cpp index 2e4bf944e2f3..5e9340dddd1d 100644 --- a/src/App/TransactionalObject.cpp +++ b/src/App/TransactionalObject.cpp @@ -46,8 +46,7 @@ const char* TransactionalObject::detachFromDocument() return ""; } -void TransactionalObject::onBeforeChangeProperty(Document *doc, const Property *prop) +void TransactionalObject::onBeforeChangeProperty(Document* doc, const Property* prop) { doc->onBeforeChangeProperty(this, prop); } - diff --git a/src/App/TransactionalObject.h b/src/App/TransactionalObject.h index 97d47be216dd..dd4c86fdef44 100644 --- a/src/App/TransactionalObject.h +++ b/src/App/TransactionalObject.h @@ -34,7 +34,7 @@ class TransactionObject; /** Base class of transactional objects */ -class AppExport TransactionalObject : public App::ExtensionContainer +class AppExport TransactionalObject: public App::ExtensionContainer { PROPERTY_HEADER_WITH_OVERRIDE(App::TransactionalObject); @@ -44,11 +44,12 @@ class AppExport TransactionalObject : public App::ExtensionContainer ~TransactionalObject() override; virtual bool isAttachedToDocument() const; virtual const char* detachFromDocument(); + protected: - void onBeforeChangeProperty(Document *doc, const Property *prop); + void onBeforeChangeProperty(Document* doc, const Property* prop); }; -} //namespace App +} // namespace App -#endif // APP_TRANSACTIONALOBJECT_H +#endif // APP_TRANSACTIONALOBJECT_H diff --git a/src/App/Transactions.cpp b/src/App/Transactions.cpp index 5100c3992c59..ebf1c47fe779 100644 --- a/src/App/Transactions.cpp +++ b/src/App/Transactions.cpp @@ -25,7 +25,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -39,7 +39,7 @@ #include "Property.h" -FC_LOG_LEVEL_INIT("App",true,true) +FC_LOG_LEVEL_INIT("App", true, true) using namespace App; using namespace std; @@ -51,7 +51,9 @@ TYPESYSTEM_SOURCE(App::Transaction, Base::Persistence) Transaction::Transaction(int id) { - if(!id) id = getNewID(); + if (!id) { + id = getNewID(); + } transID = id; } @@ -61,8 +63,8 @@ Transaction::Transaction(int id) */ Transaction::~Transaction() { - auto &index = _Objects.get<0>(); - for (const auto & It : index) { + auto& index = _Objects.get<0>(); + for (const auto& It : index) { if (It.second->status == TransactionObject::New) { // If an object has been removed from the document the transaction // status is 'New'. The 'pcNameInDocument' member serves as criterion @@ -97,29 +99,32 @@ Transaction::~Transaction() static std::atomic _TransactionID; -int Transaction::getNewID() { +int Transaction::getNewID() +{ int id = ++_TransactionID; - if(id) + if (id) { return id; + } // wrap around? really? return ++_TransactionID; } -int Transaction::getLastID() { +int Transaction::getLastID() +{ return _TransactionID; } -unsigned int Transaction::getMemSize () const +unsigned int Transaction::getMemSize() const { return 0; } -void Transaction::Save (Base::Writer &/*writer*/) const +void Transaction::Save(Base::Writer& /*writer*/) const { assert(0); } -void Transaction::Restore(Base::XMLReader &/*reader*/) +void Transaction::Restore(Base::XMLReader& /*reader*/) { assert(0); } @@ -134,18 +139,17 @@ bool Transaction::isEmpty() const return _Objects.empty(); } -bool Transaction::hasObject(const TransactionalObject *Obj) const +bool Transaction::hasObject(const TransactionalObject* Obj) const { return !!_Objects.get<1>().count(Obj); } -void Transaction::addOrRemoveProperty(TransactionalObject *Obj, - const Property* pcProp, bool add) +void Transaction::addOrRemoveProperty(TransactionalObject* Obj, const Property* pcProp, bool add) { - auto &index = _Objects.get<1>(); + auto& index = _Objects.get<1>(); auto pos = index.find(Obj); - TransactionObject *To; + TransactionObject* To; if (pos != index.end()) { To = pos->second; @@ -153,44 +157,49 @@ void Transaction::addOrRemoveProperty(TransactionalObject *Obj, else { To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); To->status = TransactionObject::Chn; - index.emplace(Obj,To); + index.emplace(Obj, To); } - To->addOrRemoveProperty(pcProp,add); + To->addOrRemoveProperty(pcProp, add); } //************************************************************************** // separator for other implementation aspects -void Transaction::apply(Document &Doc, bool forward) +void Transaction::apply(Document& Doc, bool forward) { std::string errMsg; try { - auto &index = _Objects.get<0>(); - for(auto &info : index) + auto& index = _Objects.get<0>(); + for (auto& info : index) { info.second->applyDel(Doc, const_cast(info.first)); - for(auto &info : index) + } + for (auto& info : index) { info.second->applyNew(Doc, const_cast(info.first)); - for(auto &info : index) + } + for (auto& info : index) { info.second->applyChn(Doc, const_cast(info.first), forward); - }catch(Base::Exception &e) { + } + } + catch (Base::Exception& e) { e.ReportException(); errMsg = e.what(); - }catch(std::exception &e) { + } + catch (std::exception& e) { errMsg = e.what(); - }catch(...) { + } + catch (...) { errMsg = "Unknown exception"; } - if(!errMsg.empty()) { - FC_ERR("Exception on " << (forward?"redo":"undo") << " '" - << Name << "':" << errMsg); + if (!errMsg.empty()) { + FC_ERR("Exception on " << (forward ? "redo" : "undo") << " '" << Name << "':" << errMsg); } } -void Transaction::addObjectNew(TransactionalObject *Obj) +void Transaction::addObjectNew(TransactionalObject* Obj) { - auto &index = _Objects.get<1>(); + auto& index = _Objects.get<1>(); auto pos = index.find(Obj); if (pos != index.end()) { if (pos->second->status == TransactionObject::Del) { @@ -205,21 +214,21 @@ void Transaction::addObjectNew(TransactionalObject *Obj) pos->second->status = TransactionObject::New; pos->second->_NameInDocument = Obj->detachFromDocument(); // move item at the end to make sure the order of removal is kept - auto &seq = _Objects.get<0>(); - seq.relocate(seq.end(),_Objects.project<0>(pos)); + auto& seq = _Objects.get<0>(); + seq.relocate(seq.end(), _Objects.project<0>(pos)); } } else { - TransactionObject *To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); + TransactionObject* To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); To->status = TransactionObject::New; To->_NameInDocument = Obj->detachFromDocument(); - index.emplace(Obj,To); + index.emplace(Obj, To); } } -void Transaction::addObjectDel(const TransactionalObject *Obj) +void Transaction::addObjectDel(const TransactionalObject* Obj) { - auto &index = _Objects.get<1>(); + auto& index = _Objects.get<1>(); auto pos = index.find(Obj); // is it created in this transaction ? @@ -232,18 +241,18 @@ void Transaction::addObjectDel(const TransactionalObject *Obj) pos->second->status = TransactionObject::Del; } else { - TransactionObject *To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); + TransactionObject* To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); To->status = TransactionObject::Del; - index.emplace(Obj,To); + index.emplace(Obj, To); } } -void Transaction::addObjectChange(const TransactionalObject *Obj, const Property *Prop) +void Transaction::addObjectChange(const TransactionalObject* Obj, const Property* Prop) { - auto &index = _Objects.get<1>(); + auto& index = _Objects.get<1>(); auto pos = index.find(Obj); - TransactionObject *To; + TransactionObject* To; if (pos != index.end()) { To = pos->second; @@ -251,7 +260,7 @@ void Transaction::addObjectChange(const TransactionalObject *Obj, const Property else { To = TransactionFactory::instance().createTransaction(Obj->getTypeId()); To->status = TransactionObject::Chn; - index.emplace(Obj,To); + index.emplace(Obj, To); } To->setProperty(Prop); @@ -280,27 +289,26 @@ TransactionObject::TransactionObject() = default; */ TransactionObject::~TransactionObject() { - for(auto &v : _PropChangeMap) + for (auto& v : _PropChangeMap) { delete v.second.property; + } } -void TransactionObject::applyDel(Document & /*Doc*/, TransactionalObject * /*pcObj*/) -{ -} +void TransactionObject::applyDel(Document& /*Doc*/, TransactionalObject* /*pcObj*/) +{} -void TransactionObject::applyNew(Document & /*Doc*/, TransactionalObject * /*pcObj*/) -{ -} +void TransactionObject::applyNew(Document& /*Doc*/, TransactionalObject* /*pcObj*/) +{} -void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, bool /* Forward */) +void TransactionObject::applyChn(Document& /*Doc*/, TransactionalObject* pcObj, bool /* Forward */) { if (status == New || status == Chn) { // Property change order is not preserved, as it is recursive in nature - for(auto &v : _PropChangeMap) { - auto &data = v.second; + for (auto& v : _PropChangeMap) { + auto& data = v.second; auto prop = const_cast(data.propertyOrig); - if(!data.property) { + if (!data.property) { // here means we are undoing/redoing and property add operation pcObj->removeDynamicProperty(v.second.name.c_str()); continue; @@ -310,9 +318,10 @@ void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, // been destroies. We must prepare for the case where user removed // a dynamic property but does not recordered as transaction. auto name = pcObj->getPropertyName(prop); - if(!name || (!data.name.empty() && data.name != name) || data.propertyType != prop->getTypeId()) { + if (!name || (!data.name.empty() && data.name != name) + || data.propertyType != prop->getTypeId()) { // Here means the original property is not found, probably removed - if(data.name.empty()) { + if (data.name.empty()) { // not a dynamic property, nothing to do continue; } @@ -322,14 +331,18 @@ void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, // a new property, the property key inside redo stack will not // match. So we search by name first. prop = pcObj->getDynamicPropertyByName(data.name.c_str()); - if(!prop) { + if (!prop) { // Still not found, re-create the property - prop = pcObj->addDynamicProperty( - data.propertyType.getName(), - data.name.c_str(), data.group.c_str(), data.doc.c_str(), - data.attr, data.readonly, data.hidden); - if(!prop) + prop = pcObj->addDynamicProperty(data.propertyType.getName(), + data.name.c_str(), + data.group.c_str(), + data.doc.c_str(), + data.attr, + data.readonly, + data.hidden); + if (!prop) { continue; + } prop->setStatusValue(data.property->getStatus()); } } @@ -349,22 +362,25 @@ void TransactionObject::applyChn(Document & /*Doc*/, TransactionalObject *pcObj, // } try { prop->Paste(*data.property); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); FC_ERR("exception while restoring " << prop->getFullName() << ": " << e.what()); - } catch (std::exception &e) { + } + catch (std::exception& e) { FC_ERR("exception while restoring " << prop->getFullName() << ": " << e.what()); - } catch (...) - {} + } + catch (...) { + } } } } void TransactionObject::setProperty(const Property* pcProp) { - auto &data = _PropChangeMap[pcProp->getID()]; - if(!data.property && data.name.empty()) { - static_cast(data) = + auto& data = _PropChangeMap[pcProp->getID()]; + if (!data.property && data.name.empty()) { + static_cast(data) = pcProp->getContainer()->getDynamicPropertyData(pcProp); data.propertyOrig = pcProp; data.property = pcProp->Copy(); @@ -376,27 +392,29 @@ void TransactionObject::setProperty(const Property* pcProp) void TransactionObject::addOrRemoveProperty(const Property* pcProp, bool add) { (void)add; - if(!pcProp || !pcProp->getContainer()) + if (!pcProp || !pcProp->getContainer()) { return; + } - auto &data = _PropChangeMap[pcProp->getID()]; - if(!data.name.empty()) { - if(!add && !data.property) { + auto& data = _PropChangeMap[pcProp->getID()]; + if (!data.name.empty()) { + if (!add && !data.property) { // this means add and remove the same property inside a single // transaction, so they cancel each other out. _PropChangeMap.erase(pcProp->getID()); } return; } - if(data.property) { + if (data.property) { delete data.property; data.property = nullptr; } data.propertyOrig = pcProp; - static_cast(data) = + static_cast(data) = pcProp->getContainer()->getDynamicPropertyData(pcProp); - if(add) + if (add) { data.property = nullptr; + } else { data.property = pcProp->Copy(); data.propertyType = pcProp->getTypeId(); @@ -404,17 +422,17 @@ void TransactionObject::addOrRemoveProperty(const Property* pcProp, bool add) } } -unsigned int TransactionObject::getMemSize () const +unsigned int TransactionObject::getMemSize() const { return 0; } -void TransactionObject::Save (Base::Writer &/*writer*/) const +void TransactionObject::Save(Base::Writer& /*writer*/) const { assert(0); } -void TransactionObject::Restore(Base::XMLReader &/*reader*/) +void TransactionObject::Restore(Base::XMLReader& /*reader*/) { assert(0); } @@ -441,18 +459,19 @@ TransactionDocumentObject::TransactionDocumentObject() = default; */ TransactionDocumentObject::~TransactionDocumentObject() = default; -void TransactionDocumentObject::applyDel(Document &Doc, TransactionalObject *pcObj) +void TransactionDocumentObject::applyDel(Document& Doc, TransactionalObject* pcObj) { if (status == Del) { DocumentObject* obj = static_cast(pcObj); #ifndef USE_OLD_DAG - //Make sure the backlinks of all linked objects are updated. As the links of the removed - //object are never set to [] they also do not remove the backlink. But as they are - //not in the document anymore we need to remove them anyway to ensure a correct graph + // Make sure the backlinks of all linked objects are updated. As the links of the removed + // object are never set to [] they also do not remove the backlink. But as they are + // not in the document anymore we need to remove them anyway to ensure a correct graph auto list = obj->getOutList(); - for (auto link : list) + for (auto link : list) { link->_removeBackLink(obj); + } #endif // simply filling in the saved object @@ -460,17 +479,18 @@ void TransactionDocumentObject::applyDel(Document &Doc, TransactionalObject *pcO } } -void TransactionDocumentObject::applyNew(Document &Doc, TransactionalObject *pcObj) +void TransactionDocumentObject::applyNew(Document& Doc, TransactionalObject* pcObj) { if (status == New) { DocumentObject* obj = static_cast(pcObj); Doc._addObject(obj, _NameInDocument.c_str()); #ifndef USE_OLD_DAG - //make sure the backlinks of all linked objects are updated + // make sure the backlinks of all linked objects are updated auto list = obj->getOutList(); - for (auto link : list) + for (auto link : list) { link->_addBackLink(obj); + } #endif } } @@ -484,8 +504,9 @@ App::TransactionFactory* App::TransactionFactory::self = nullptr; TransactionFactory& TransactionFactory::instance() { - if (!self) + if (!self) { self = new TransactionFactory; + } return *self; } @@ -495,7 +516,7 @@ void TransactionFactory::destruct() self = nullptr; } -void TransactionFactory::addProducer (const Base::Type& type, Base::AbstractProducer *producer) +void TransactionFactory::addProducer(const Base::Type& type, Base::AbstractProducer* producer) { producers[type] = producer; } @@ -503,7 +524,7 @@ void TransactionFactory::addProducer (const Base::Type& type, Base::AbstractProd /** * Creates a transaction object for the given type id. */ -TransactionObject* TransactionFactory::createTransaction (const Base::Type& type) const +TransactionObject* TransactionFactory::createTransaction(const Base::Type& type) const { std::map::const_iterator it; for (it = producers.begin(); it != producers.end(); ++it) { diff --git a/src/App/Transactions.h b/src/App/Transactions.h index 93bc592c6ea8..494f59d16268 100644 --- a/src/App/Transactions.h +++ b/src/App/Transactions.h @@ -42,7 +42,7 @@ class TransactionalObject; /** Represents a atomic transaction of the document */ -class AppExport Transaction : public Base::Persistence +class AppExport Transaction: public Base::Persistence { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -60,15 +60,15 @@ class AppExport Transaction : public Base::Persistence ~Transaction() override; /// apply the content to the document - void apply(Document &Doc,bool forward); + void apply(Document& Doc, bool forward); // the utf-8 name of the transaction std::string Name; - unsigned int getMemSize () const override; - void Save (Base::Writer &writer) const override; + unsigned int getMemSize() const override; + void Save(Base::Writer& writer) const override; /// This method is used to restore properties from an XML document. - void Restore(Base::XMLReader &reader) override; + void Restore(Base::XMLReader& reader) override; /// Return the transaction ID int getID() const; @@ -80,12 +80,12 @@ class AppExport Transaction : public Base::Persistence /// Returns true if the transaction list is empty; otherwise returns false. bool isEmpty() const; /// check if this object is used in a transaction - bool hasObject(const TransactionalObject *Obj) const; - void addOrRemoveProperty(TransactionalObject *Obj, const Property* pcProp, bool add); + bool hasObject(const TransactionalObject* Obj) const; + void addOrRemoveProperty(TransactionalObject* Obj, const Property* pcProp, bool add); - void addObjectNew(TransactionalObject *Obj); - void addObjectDel(const TransactionalObject *Obj); - void addObjectChange(const TransactionalObject *Obj, const Property *Prop); + void addObjectNew(TransactionalObject* Obj); + void addObjectDel(const TransactionalObject* Obj); + void addObjectChange(const TransactionalObject* Obj, const Property* Prop); private: int transID; @@ -94,16 +94,13 @@ class AppExport Transaction : public Base::Persistence Info, bmi::indexed_by< bmi::sequenced<>, - bmi::hashed_unique< - bmi::member - > - > - > _Objects; + bmi::hashed_unique>>> + _Objects; }; /** Represents an entry for an object in a Transaction */ -class AppExport TransactionObject : public Base::Persistence +class AppExport TransactionObject: public Base::Persistence { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -113,26 +110,32 @@ class AppExport TransactionObject : public Base::Persistence /// Destruction ~TransactionObject() override; - virtual void applyNew(Document &Doc, TransactionalObject *pcObj); - virtual void applyDel(Document &Doc, TransactionalObject *pcObj); - virtual void applyChn(Document &Doc, TransactionalObject *pcObj, bool Forward); + virtual void applyNew(Document& Doc, TransactionalObject* pcObj); + virtual void applyDel(Document& Doc, TransactionalObject* pcObj); + virtual void applyChn(Document& Doc, TransactionalObject* pcObj, bool Forward); void setProperty(const Property* pcProp); void addOrRemoveProperty(const Property* pcProp, bool add); - unsigned int getMemSize () const override; - void Save (Base::Writer &writer) const override; + unsigned int getMemSize() const override; + void Save(Base::Writer& writer) const override; /// This method is used to restore properties from an XML document. - void Restore(Base::XMLReader &reader) override; + void Restore(Base::XMLReader& reader) override; friend class Transaction; protected: - enum Status {New,Del,Chn} status{New}; + enum Status + { + New, + Del, + Chn + } status {New}; - struct PropData : DynamicProperty::PropData { + struct PropData: DynamicProperty::PropData + { Base::Type propertyType; - const Property *propertyOrig = nullptr; + const Property* propertyOrig = nullptr; }; std::unordered_map _PropChangeMap; @@ -141,7 +144,7 @@ class AppExport TransactionObject : public Base::Persistence /** Represents an entry for a document object in a transaction */ -class AppExport TransactionDocumentObject : public TransactionObject +class AppExport TransactionDocumentObject: public TransactionObject { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -151,18 +154,18 @@ class AppExport TransactionDocumentObject : public TransactionObject /// Destruction ~TransactionDocumentObject() override; - void applyNew(Document &Doc, TransactionalObject *pcObj) override; - void applyDel(Document &Doc, TransactionalObject *pcObj) override; + void applyNew(Document& Doc, TransactionalObject* pcObj) override; + void applyDel(Document& Doc, TransactionalObject* pcObj) override; }; class AppExport TransactionFactory { public: static TransactionFactory& instance(); - static void destruct (); + static void destruct(); - TransactionObject* createTransaction (const Base::Type& type) const; - void addProducer (const Base::Type& type, Base::AbstractProducer *producer); + TransactionObject* createTransaction(const Base::Type& type) const; + void addProducer(const Base::Type& type, Base::AbstractProducer* producer); private: static TransactionFactory* self; @@ -172,27 +175,26 @@ class AppExport TransactionFactory ~TransactionFactory() = default; }; -template -class TransactionProducer : public Base::AbstractProducer +template +class TransactionProducer: public Base::AbstractProducer { public: - explicit TransactionProducer (const Base::Type& type) + explicit TransactionProducer(const Base::Type& type) { TransactionFactory::instance().addProducer(type, this); } - ~TransactionProducer () override = default; + ~TransactionProducer() override = default; /** * Creates an instance of the specified transaction object. */ - void* Produce () const override + void* Produce() const override { return (new CLASS); } }; -} //namespace App - -#endif // APP_TRANSACTION_H +} // namespace App +#endif // APP_TRANSACTION_H diff --git a/src/App/VRMLObject.cpp b/src/App/VRMLObject.cpp index 8dd6ae1f2c8f..6844fd9327ef 100644 --- a/src/App/VRMLObject.cpp +++ b/src/App/VRMLObject.cpp @@ -40,11 +40,17 @@ PROPERTY_SOURCE(App::VRMLObject, App::GeoFeature) VRMLObject::VRMLObject() { - ADD_PROPERTY_TYPE(VrmlFile,(nullptr),"",Prop_None,"Included file with the VRML definition"); - ADD_PROPERTY_TYPE(Urls,(""),"",static_cast(Prop_ReadOnly|Prop_Output|Prop_Transient), - "Resource files loaded by the VRML file"); - ADD_PROPERTY_TYPE(Resources,(""),"",static_cast(Prop_ReadOnly|Prop_Output), - "Resource files loaded by the VRML file"); + ADD_PROPERTY_TYPE(VrmlFile, (nullptr), "", Prop_None, "Included file with the VRML definition"); + ADD_PROPERTY_TYPE(Urls, + (""), + "", + static_cast(Prop_ReadOnly | Prop_Output | Prop_Transient), + "Resource files loaded by the VRML file"); + ADD_PROPERTY_TYPE(Resources, + (""), + "", + static_cast(Prop_ReadOnly | Prop_Output), + "Resource files loaded by the VRML file"); Urls.setSize(0); Resources.setSize(0); } @@ -82,16 +88,17 @@ void VRMLObject::onChanged(const App::Property* prop) GeoFeature::onChanged(prop); } -PyObject *VRMLObject::getPyObject() +PyObject* VRMLObject::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); + PythonObject = Py::Object(new DocumentObjectPy(this), true); } - return Py::new_reference_to(PythonObject); + return Py::new_reference_to(PythonObject); } -std::string VRMLObject::getRelativePath(const std::string& prefix, const std::string& resource) const +std::string VRMLObject::getRelativePath(const std::string& prefix, + const std::string& resource) const { std::string str; std::string intname = this->getNameInDocument(); @@ -136,38 +143,38 @@ void VRMLObject::makeDirectories(const std::string& path, const std::string& sub if (!fi.createDirectory()) { break; } - pos = subdir.find('/', pos+1); + pos = subdir.find('/', pos + 1); } } -void VRMLObject::Save (Base::Writer &writer) const +void VRMLObject::Save(Base::Writer& writer) const { App::GeoFeature::Save(writer); // save also the inline files if there const std::vector& urls = Resources.getValues(); - for (const auto & url : urls) { + for (const auto& url : urls) { writer.addFile(url.c_str(), this); } this->indexSave = 0; } -void VRMLObject::Restore(Base::XMLReader &reader) +void VRMLObject::Restore(Base::XMLReader& reader) { App::GeoFeature::Restore(reader); Urls.setSize(Resources.getSize()); // restore also the inline files if there const std::vector& urls = Resources.getValues(); - for(const auto & url : urls) { + for (const auto& url : urls) { reader.addFile(url.c_str(), this); } this->indexRestore = 0; } -void VRMLObject::SaveDocFile (Base::Writer &writer) const +void VRMLObject::SaveDocFile(Base::Writer& writer) const { // store the inline files of the VRML file if (this->indexSave < Urls.getSize()) { @@ -192,7 +199,7 @@ void VRMLObject::SaveDocFile (Base::Writer &writer) const } } -bool VRMLObject::restoreTextureFinished(Base::Reader &reader) +bool VRMLObject::restoreTextureFinished(Base::Reader& reader) { Base::StateLocker locker(restoreData, true); if (this->indexRestore < Resources.getSize()) { @@ -228,7 +235,7 @@ void VRMLObject::reloadFile() this->vrmlPath = fi.dirPath(); } -void VRMLObject::RestoreDocFile(Base::Reader &reader) +void VRMLObject::RestoreDocFile(Base::Reader& reader) { if (restoreTextureFinished(reader)) { reloadFile(); diff --git a/src/App/VRMLObject.h b/src/App/VRMLObject.h index f2f8abf2d47c..23474ce47e79 100644 --- a/src/App/VRMLObject.h +++ b/src/App/VRMLObject.h @@ -31,7 +31,7 @@ namespace App { -class AppExport VRMLObject : public GeoFeature +class AppExport VRMLObject: public GeoFeature { PROPERTY_HEADER_WITH_OVERRIDE(App::VRMLObject); @@ -40,24 +40,26 @@ class AppExport VRMLObject : public GeoFeature VRMLObject(); /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "Gui::ViewProviderVRMLObject"; } - DocumentObjectExecReturn *execute() override { + DocumentObjectExecReturn* execute() override + { return DocumentObject::StdReturn; } short mustExecute() const override; - PyObject *getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + PyObject* getPyObject() override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - //NOLINTBEGIN + // NOLINTBEGIN PropertyFileIncluded VrmlFile; PropertyStringList Urls; PropertyStringList Resources; - //NOLINTEND + // NOLINTEND protected: void onChanged(const App::Property*) override; @@ -66,7 +68,7 @@ class AppExport VRMLObject : public GeoFeature std::string getRelativePath(const std::string& prefix, const std::string& resource) const; static std::string fixRelativePath(const std::string& name, const std::string& resource); static void makeDirectories(const std::string& path, const std::string& subdir); - bool restoreTextureFinished(Base::Reader &reader); + bool restoreTextureFinished(Base::Reader& reader); void reloadFile(); private: @@ -76,7 +78,7 @@ class AppExport VRMLObject : public GeoFeature mutable bool restoreData {false}; }; -} //namespace App +} // namespace App -#endif // APP_INVENTOROBJECT_H +#endif // APP_INVENTOROBJECT_H diff --git a/src/App/VarSet.cpp b/src/App/VarSet.cpp index a8ea0fe5a3fa..c02ba0343076 100644 --- a/src/App/VarSet.cpp +++ b/src/App/VarSet.cpp @@ -37,4 +37,3 @@ const char* VarSet::getViewProviderName() const { return "Gui::ViewProviderVarSet"; } - diff --git a/src/App/VarSet.h b/src/App/VarSet.h index 9d55ca680a62..e83edb2ba093 100644 --- a/src/App/VarSet.h +++ b/src/App/VarSet.h @@ -29,18 +29,17 @@ namespace App { /** A DocumentObject class with the purpose to store variables -*/ -class AppExport VarSet : public App::DocumentObject + */ +class AppExport VarSet: public App::DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::VarSet); - -public: +public: VarSet() = default; ~VarSet() override = default; const char* getViewProviderName() const override; }; -} +} // namespace App #endif diff --git a/src/App/core-app.dox b/src/App/core-app.dox index be3f806d40c1..1a5f38b0e95c 100644 --- a/src/App/core-app.dox +++ b/src/App/core-app.dox @@ -13,4 +13,3 @@ */ - diff --git a/src/App/private/DocumentP.h b/src/App/private/DocumentP.h index f3930a442daa..b0098f1715cc 100644 --- a/src/App/private/DocumentP.h +++ b/src/App/private/DocumentP.h @@ -24,7 +24,7 @@ #define APP_DOCUMENTP_H #ifdef _MSC_VER -#pragma warning( disable : 4834 ) +#pragma warning(disable : 4834) #endif #include @@ -38,22 +38,23 @@ // using VertexProperty = boost::property; -using DependencyList = boost::adjacency_list < -boost::vecS, // class OutEdgeListS : a Sequence or an AssociativeContainer -boost::vecS, // class VertexListS : a Sequence or a RandomAccessContainer -boost::directedS, // class DirectedS : This is a directed graph -boost::no_property, // class VertexProperty: -boost::no_property, // class EdgeProperty: -boost::no_property, // class GraphProperty: -boost::listS // class EdgeListS: ->; +using DependencyList = boost::adjacency_list< + boost::vecS, // class OutEdgeListS : a Sequence or an AssociativeContainer + boost::vecS, // class VertexListS : a Sequence or a RandomAccessContainer + boost::directedS, // class DirectedS : This is a directed graph + boost::no_property, // class VertexProperty: + boost::no_property, // class EdgeProperty: + boost::no_property, // class GraphProperty: + boost::listS // class EdgeListS: + >; using Traits = boost::graph_traits; using Vertex = Traits::vertex_descriptor; -using Edge = Traits::edge_descriptor; -using Node = std::vector ; -using Path = std::vector ; +using Edge = Traits::edge_descriptor; +using Node = std::vector; +using Path = std::vector; -namespace App { +namespace App +{ using HasherMap = boost::bimap; class Transaction; @@ -69,12 +70,12 @@ struct DocumentP std::vector pendingRemove; long lastObjectId; DocumentObject* activeObject; - Transaction *activeUndoTransaction; + Transaction* activeUndoTransaction; // pointer to the python class Py::Object DocumentPythonObject; int iTransactionMode; bool rollback; - bool undoing; ///< document in the middle of undo or redo + bool undoing; ///< document in the middle of undo or redo bool committing; bool opentransaction; std::bitset<32> StatusBits; @@ -87,66 +88,77 @@ struct DocumentP DependencyList DepList; std::map VertexObjectList; std::map vertexMap; -#endif //USE_OLD_DAG - std::multimap > _RecomputeLog; +#endif // USE_OLD_DAG + std::multimap> + _RecomputeLog; StringHasherRef Hasher; DocumentP(); - void addRecomputeLog(const char *why, App::DocumentObject *obj) { + void addRecomputeLog(const char* why, App::DocumentObject* obj) + { addRecomputeLog(new DocumentObjectExecReturn(why, obj)); } - void addRecomputeLog(const std::string &why, App::DocumentObject *obj) { + void addRecomputeLog(const std::string& why, App::DocumentObject* obj) + { addRecomputeLog(new DocumentObjectExecReturn(why, obj)); } - void addRecomputeLog(DocumentObjectExecReturn *returnCode) { - if(!returnCode->Which) { + void addRecomputeLog(DocumentObjectExecReturn* returnCode) + { + if (!returnCode->Which) { delete returnCode; return; } - _RecomputeLog.emplace(returnCode->Which, std::unique_ptr(returnCode)); + _RecomputeLog.emplace(returnCode->Which, + std::unique_ptr(returnCode)); returnCode->Which->setStatus(ObjectStatus::Error, true); } - void clearRecomputeLog(const App::DocumentObject *obj=nullptr) { - if(!obj) + void clearRecomputeLog(const App::DocumentObject* obj = nullptr) + { + if (!obj) { _RecomputeLog.clear(); - else + } + else { _RecomputeLog.erase(obj); + } } - void clearDocument() { + void clearDocument() + { objectArray.clear(); - for(auto &v : objectMap) { + for (auto& v : objectMap) { v.second->setStatus(ObjectStatus::Destroy, true); - delete(v.second); + delete (v.second); v.second = nullptr; } objectMap.clear(); objectIdMap.clear(); } - const char *findRecomputeLog(const App::DocumentObject *obj) { + const char* findRecomputeLog(const App::DocumentObject* obj) + { auto range = _RecomputeLog.equal_range(obj); - if(range.first == range.second) + if (range.first == range.second) { return nullptr; + } return (--range.second)->second->Why.c_str(); } - static - void findAllPathsAt(const std::vector &all_nodes, size_t id, - std::vector &all_paths, Path tmp); + static void findAllPathsAt(const std::vector& all_nodes, + size_t id, + std::vector& all_paths, + Path tmp); std::vector topologicalSort(const std::vector& objects) const; - std::vector - static partialTopologicalSort(const std::vector& objects); + static std::vector partialTopologicalSort( + const std::vector& objects); static void checkStringHasher(const Base::XMLReader& reader); }; -} // namespace App +} // namespace App -#endif // APP_DOCUMENTP_H +#endif // APP_DOCUMENTP_H From 7a2bfb737054f71947e266c02dd9712cdb71f1eb Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 20 Nov 2024 23:02:40 +0100 Subject: [PATCH 034/161] Mesh: Fix linter warnings --- src/Mod/Mesh/App/AppMeshPy.cpp | 45 +- src/Mod/Mesh/App/Core/Algorithm.cpp | 122 ++-- src/Mod/Mesh/App/Core/Algorithm.h | 25 +- src/Mod/Mesh/App/Core/Approximation.cpp | 108 ++- src/Mod/Mesh/App/Core/Approximation.h | 8 +- src/Mod/Mesh/App/Core/Builder.cpp | 15 +- src/Mod/Mesh/App/Core/Builder.h | 2 +- src/Mod/Mesh/App/Core/Curvature.cpp | 10 +- src/Mod/Mesh/App/Core/CylinderFit.cpp | 189 +++--- src/Mod/Mesh/App/Core/CylinderFit.h | 8 +- src/Mod/Mesh/App/Core/Decimation.cpp | 2 +- src/Mod/Mesh/App/Core/Decimation.h | 2 +- src/Mod/Mesh/App/Core/Definitions.cpp | 2 +- src/Mod/Mesh/App/Core/Definitions.h | 8 +- src/Mod/Mesh/App/Core/Degeneration.cpp | 67 +- src/Mod/Mesh/App/Core/Degeneration.h | 8 +- src/Mod/Mesh/App/Core/Elements.cpp | 206 +++--- src/Mod/Mesh/App/Core/Elements.h | 63 +- src/Mod/Mesh/App/Core/Evaluation.cpp | 55 +- src/Mod/Mesh/App/Core/Grid.cpp | 9 +- src/Mod/Mesh/App/Core/Grid.h | 2 +- src/Mod/Mesh/App/Core/IO/ReaderOBJ.cpp | 27 +- src/Mod/Mesh/App/Core/IO/WriterInventor.cpp | 4 +- src/Mod/Mesh/App/Core/IO/WriterOBJ.cpp | 17 +- src/Mod/Mesh/App/Core/Info.cpp | 2 +- src/Mod/Mesh/App/Core/Iterator.h | 14 +- src/Mod/Mesh/App/Core/MeshIO.cpp | 629 +++++++++--------- src/Mod/Mesh/App/Core/MeshIO.h | 70 +- src/Mod/Mesh/App/Core/MeshKernel.cpp | 45 +- src/Mod/Mesh/App/Core/MeshKernel.h | 24 +- src/Mod/Mesh/App/Core/Projection.cpp | 11 +- src/Mod/Mesh/App/Core/Segmentation.cpp | 46 +- src/Mod/Mesh/App/Core/Segmentation.h | 8 +- src/Mod/Mesh/App/Core/SetOperations.cpp | 69 +- src/Mod/Mesh/App/Core/SetOperations.h | 4 +- src/Mod/Mesh/App/Core/Smoothing.cpp | 29 +- src/Mod/Mesh/App/Core/SphereFit.cpp | 21 +- src/Mod/Mesh/App/Core/Tools.cpp | 11 +- src/Mod/Mesh/App/Core/Tools.h | 2 +- src/Mod/Mesh/App/Core/TopoAlgorithm.cpp | 70 +- src/Mod/Mesh/App/Core/TopoAlgorithm.h | 6 +- src/Mod/Mesh/App/Core/Triangulation.cpp | 57 +- src/Mod/Mesh/App/Core/Trim.cpp | 24 +- src/Mod/Mesh/App/Core/Trim.h | 4 +- src/Mod/Mesh/App/Core/TrimByPlane.cpp | 20 +- src/Mod/Mesh/App/Core/Visitor.cpp | 23 +- src/Mod/Mesh/App/Core/Visitor.h | 2 +- src/Mod/Mesh/App/Edge.cpp | 10 +- src/Mod/Mesh/App/Edge.h | 4 +- src/Mod/Mesh/App/EdgePyImp.cpp | 2 +- src/Mod/Mesh/App/Exporter.cpp | 15 +- src/Mod/Mesh/App/Exporter.h | 2 +- src/Mod/Mesh/App/Facet.cpp | 10 +- src/Mod/Mesh/App/FacetPyImp.cpp | 2 +- src/Mod/Mesh/App/FeatureMeshDefects.cpp | 4 +- src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp | 13 +- src/Mod/Mesh/App/FeatureMeshSetOperations.cpp | 2 +- src/Mod/Mesh/App/FeatureMeshSolid.cpp | 48 +- src/Mod/Mesh/App/Mesh.cpp | 39 +- src/Mod/Mesh/App/Mesh.h | 18 +- src/Mod/Mesh/App/MeshFeature.h | 1 - src/Mod/Mesh/App/MeshPoint.h | 1 + src/Mod/Mesh/App/MeshProperties.cpp | 2 +- src/Mod/Mesh/App/MeshProperties.h | 10 +- src/Mod/Mesh/App/MeshTexture.cpp | 6 +- src/Mod/Mesh/App/MeshTexture.h | 11 +- .../Mesh/Gui/DlgSettingsImportExportImp.cpp | 2 +- src/Mod/Mesh/Gui/DlgSettingsMeshView.cpp | 2 +- src/Mod/Mesh/Gui/PreCompiled.h | 1 + src/Mod/Mesh/Gui/PropertyEditorMesh.cpp | 8 +- src/Mod/Mesh/Gui/RemeshGmsh.cpp | 3 +- src/Mod/Mesh/Gui/SoFCMeshObject.cpp | 105 ++- src/Mod/Mesh/Gui/SoFCMeshObject.h | 2 +- src/Mod/Mesh/Gui/ViewProvider.cpp | 458 ++++++------- src/Mod/Mesh/Gui/ViewProvider.h | 55 +- src/Mod/Mesh/Gui/ViewProviderCurvature.cpp | 180 +++-- src/Mod/Mesh/Gui/ViewProviderCurvature.h | 2 +- src/Mod/Mesh/Gui/ViewProviderDefects.cpp | 273 ++++---- src/Mod/Mesh/Gui/ViewProviderDefects.h | 41 +- src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.cpp | 27 +- src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h | 6 +- src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp | 6 +- src/Mod/Mesh/Gui/ViewProviderTransform.cpp | 10 +- src/Mod/Mesh/Gui/ViewProviderTransform.h | 2 +- .../Gui/ViewProviderTransformDemolding.cpp | 37 +- .../Mesh/Gui/ViewProviderTransformDemolding.h | 3 +- 86 files changed, 1735 insertions(+), 1883 deletions(-) diff --git a/src/Mod/Mesh/App/AppMeshPy.cpp b/src/Mod/Mesh/App/AppMeshPy.cpp index dbb6506428fc..6ec639a3c4af 100644 --- a/src/Mod/Mesh/App/AppMeshPy.cpp +++ b/src/Mod/Mesh/App/AppMeshPy.cpp @@ -206,7 +206,7 @@ class Module: public Py::ExtensionModule // If not, use the preference, if that exists, else default to 0.1mm. auto hGrp(App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Mesh")); - auto fTolerance(hGrp->GetFloat("MaxDeviationExport", 0.1f)); + auto fTolerance(hGrp->GetFloat("MaxDeviationExport", 0.1F)); int exportAmfCompressed(hGrp->GetBool("ExportAmfCompressed", true)); bool export3mfModel(hGrp->GetBool("Export3mfModel", true)); @@ -319,12 +319,12 @@ class Module: public Py::ExtensionModule MeshObject* mesh = nullptr; do { - float length = 10.0f; - float width = 10.0f; - float height = 10.0f; - float edgelen = -1.0f; + float length = 10.0F; + float width = 10.0F; + float height = 10.0F; + float edgelen = -1.0F; if (PyArg_ParseTuple(args.ptr(), "|ffff", &length, &width, &height, &edgelen)) { - if (edgelen < 0.0f) { + if (edgelen < 0.0F) { mesh = MeshObject::createCube(length, width, height); } else { @@ -359,8 +359,8 @@ class Module: public Py::ExtensionModule y = x; } - float hx = x / 2.0f; - float hy = y / 2.0f; + float hx = x / 2.0F; + float hy = y / 2.0F; std::vector TriaList; TriaList.emplace_back(Base::Vector3f(-hx, -hy, 0.0), @@ -376,7 +376,7 @@ class Module: public Py::ExtensionModule } Py::Object createSphere(const Py::Tuple& args) { - float radius = 5.0f; + float radius = 5.0F; int sampling = 50; if (!PyArg_ParseTuple(args.ptr(), "|fi", &radius, &sampling)) { throw Py::Exception(); @@ -390,8 +390,8 @@ class Module: public Py::ExtensionModule } Py::Object createEllipsoid(const Py::Tuple& args) { - float radius1 = 2.0f; - float radius2 = 4.0f; + float radius1 = 2.0F; + float radius2 = 4.0F; int sampling = 50; if (!PyArg_ParseTuple(args.ptr(), "|ffi", &radius1, &radius2, &sampling)) { throw Py::Exception(); @@ -405,10 +405,10 @@ class Module: public Py::ExtensionModule } Py::Object createCylinder(const Py::Tuple& args) { - float radius = 2.0f; - float length = 10.0f; + float radius = 2.0F; + float length = 10.0F; int closed = 1; - float edgelen = 1.0f; + float edgelen = 1.0F; int sampling = 50; if (!PyArg_ParseTuple(args.ptr(), "|ffifi", @@ -428,11 +428,11 @@ class Module: public Py::ExtensionModule } Py::Object createCone(const Py::Tuple& args) { - float radius1 = 2.0f; - float radius2 = 4.0f; - float len = 10.0f; + float radius1 = 2.0F; + float radius2 = 4.0F; + float len = 10.0F; int closed = 1; - float edgelen = 1.0f; + float edgelen = 1.0F; int sampling = 50; if (!PyArg_ParseTuple(args.ptr(), "|fffifi", @@ -453,8 +453,8 @@ class Module: public Py::ExtensionModule } Py::Object createTorus(const Py::Tuple& args) { - float radius1 = 10.0f; - float radius2 = 2.0f; + float radius1 = 10.0F; + float radius2 = 2.0F; int sampling = 50; if (!PyArg_ParseTuple(args.ptr(), "|ffi", &radius1, &radius2, &sampling)) { throw Py::Exception(); @@ -557,7 +557,7 @@ class Module: public Py::ExtensionModule // residuals std::vector local = polyFit.GetLocalPoints(); Py::Tuple r(local.size()); - for (std::vector::iterator it = local.begin(); it != local.end(); ++it) { + for (auto it = local.begin(); it != local.end(); ++it) { double z = polyFit.Value(it->x, it->y); double d = it->z - z; r.setItem(it - local.begin(), Py::Float(d)); @@ -598,7 +598,8 @@ class Module: public Py::ExtensionModule throw Py::RuntimeError("Too few points"); } - Wm4::Box3d mobox = Wm4::ContMinBox(points.size(), &(points[0]), 0.001, Wm4::Query::QT_REAL); + Wm4::Box3d mobox = + Wm4::ContMinBox(points.size(), points.data(), 0.001, Wm4::Query::QT_REAL); Py::Tuple result(7); Base::Vector3d v; diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index 52dbb2d5d4c2..9b9ebc1b640f 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -246,7 +246,7 @@ bool MeshAlgorithm::FirstFacetToVertex(const Base::Vector3f& rPt, const MeshFacetGrid& rGrid, FacetIndex& uIndex) const { - const float fEps = 0.001f; + const float fEps = 0.001F; bool found = false; std::vector facets; @@ -262,18 +262,17 @@ bool MeshAlgorithm::FirstFacetToVertex(const Base::Vector3f& rPt, uIndex = facet; break; } - else { - // if not then check the distance to the border of the triangle - Base::Vector3f res; - float fDist {}; - unsigned short uSide {}; - cFacet.ProjectPointToPlane(rPt, res); - cFacet.NearestEdgeToPoint(res, fDist, uSide); - if (fDist < fEps) { - found = true; - uIndex = facet; - break; - } + + // if not then check the distance to the border of the triangle + Base::Vector3f res; + float fDist {}; + unsigned short uSide {}; + cFacet.ProjectPointToPlane(rPt, res); + cFacet.NearestEdgeToPoint(res, fDist, uSide); + if (fDist < fEps) { + found = true; + uIndex = facet; + break; } } @@ -282,7 +281,7 @@ bool MeshAlgorithm::FirstFacetToVertex(const Base::Vector3f& rPt, float MeshAlgorithm::GetAverageEdgeLength() const { - float fLen = 0.0f; + float fLen = 0.0F; MeshFacetIterator cF(_rclMesh); for (cF.Init(); cF.More(); cF.Next()) { for (int i = 0; i < 3; i++) { @@ -290,7 +289,7 @@ float MeshAlgorithm::GetAverageEdgeLength() const } } - fLen = fLen / (3.0f * _rclMesh.CountFacets()); + fLen = fLen / (3.0F * _rclMesh.CountFacets()); return fLen; } @@ -309,7 +308,7 @@ float MeshAlgorithm::GetMinimumEdgeLength() const float MeshAlgorithm::GetMaximumEdgeLength() const { - float fLen = 0.0f; + float fLen = 0.0F; MeshFacetIterator cF(_rclMesh); for (cF.Init(); cF.More(); cF.Next()) { for (int i = 0; i < 3; i++) { @@ -425,7 +424,7 @@ void MeshAlgorithm::GetFacetBorders(const std::vector& raulInd, pEI = aclEdges.begin(); break; } - else if (pEI->second == ulFirst) { + if (pEI->second == ulFirst) { ulFirst = pEI->first; clBorder.push_front(ulFirst); aclEdges.erase(pEI); @@ -435,14 +434,14 @@ void MeshAlgorithm::GetFacetBorders(const std::vector& raulInd, // Note: Using this might result into boundaries with wrong orientation. // But if the mesh has some facets with wrong orientation we might get // broken boundary curves. - else if (pEI->second == ulLast && ignoreOrientation) { + if (pEI->second == ulLast && ignoreOrientation) { ulLast = pEI->first; clBorder.push_back(ulLast); aclEdges.erase(pEI); pEI = aclEdges.begin(); break; } - else if (pEI->first == ulFirst && ignoreOrientation) { + if (pEI->first == ulFirst && ignoreOrientation) { ulFirst = pEI->second; clBorder.push_front(ulFirst); aclEdges.erase(pEI); @@ -478,7 +477,7 @@ void MeshAlgorithm::GetFacetBorder(FacetIndex uFacet, std::list& rBo return; } // add the open edge to the beginning of the list - MeshFacetArray::_TConstIterator face = rFAry.begin() + uFacet; + auto face = rFAry.begin() + uFacet; for (unsigned short i = 0; i < 3; i++) { if (face->_aulNeighbours[i] == FACET_INDEX_MAX) { openEdges.push_back(face->GetEdge(i)); @@ -489,7 +488,7 @@ void MeshAlgorithm::GetFacetBorder(FacetIndex uFacet, std::list& rBo return; // facet is not a border facet } - for (MeshFacetArray::_TConstIterator it = rFAry.begin(); it != rFAry.end(); ++it) { + for (auto it = rFAry.begin(); it != rFAry.end(); ++it) { if (it == face) { continue; } @@ -587,7 +586,7 @@ void MeshAlgorithm::SplitBoundaryFromOpenEdges( pEI = openEdges.begin(); break; } - else if (pEI->second == ulFirst) { + if (pEI->second == ulFirst) { ulFirst = pEI->first; boundary.push_front(ulFirst); openEdges.erase(pEI); @@ -647,7 +646,7 @@ void MeshAlgorithm::SplitBoundaryLoops(const std::vector& rBound, for (PointIndex it : rBound) { int deg = (aPtDegree[it]++); if (deg > 0) { - for (std::vector::iterator jt = cBound.begin(); jt != cBound.end(); ++jt) { + for (auto jt = cBound.begin(); jt != cBound.end(); ++jt) { if (*jt == it) { std::vector cBoundLoop; cBoundLoop.insert(cBoundLoop.end(), jt, cBound.end()); @@ -704,9 +703,7 @@ bool MeshAlgorithm::FillupHole(const std::vector& boundary, } else { bool ready = false; - for (MeshFacetArray::_TConstIterator it = _rclMesh._aclFacetArray.begin(); - it != _rclMesh._aclFacetArray.end(); - ++it) { + for (auto it = _rclMesh._aclFacetArray.begin(); it != _rclMesh._aclFacetArray.end(); ++it) { for (int i = 0; i < 3; i++) { if (((it->_aulPoints[i] == refPoint0) && (it->_aulPoints[(i + 1) % 3] == refPoint1)) || ((it->_aulPoints[i] == refPoint1) @@ -866,9 +863,8 @@ void MeshAlgorithm::SetFacetsProperty(const std::vector& raulInds, return; } - std::vector::const_iterator iP = raulProps.begin(); - for (std::vector::const_iterator i = raulInds.begin(); i != raulInds.end(); - ++i, ++iP) { + auto iP = raulProps.begin(); + for (auto i = raulInds.begin(); i != raulInds.end(); ++i, ++iP) { _rclMesh._aclFacetArray[*i].SetProperty(*iP); } } @@ -894,7 +890,7 @@ void MeshAlgorithm::GetFacetsFlag(std::vector& raulInds, MeshFacet:: raulInds.reserve(raulInds.size() + CountFacetFlag(tF)); MeshFacetArray::_TConstIterator beg = _rclMesh._aclFacetArray.begin(); MeshFacetArray::_TConstIterator end = _rclMesh._aclFacetArray.end(); - for (MeshFacetArray::_TConstIterator it = beg; it != end; ++it) { + for (auto it = beg; it != end; ++it) { if (it->IsFlag(tF)) { raulInds.push_back(it - beg); } @@ -906,7 +902,7 @@ void MeshAlgorithm::GetPointsFlag(std::vector& raulInds, MeshPoint:: raulInds.reserve(raulInds.size() + CountPointFlag(tF)); MeshPointArray::_TConstIterator beg = _rclMesh._aclPointArray.begin(); MeshPointArray::_TConstIterator end = _rclMesh._aclPointArray.end(); - for (MeshPointArray::_TConstIterator it = beg; it != end; ++it) { + for (auto it = beg; it != end; ++it) { if (it->IsFlag(tF)) { raulInds.push_back(it - beg); } @@ -995,7 +991,7 @@ void MeshAlgorithm::GetFacetsFromToolMesh(const MeshKernel& rToolMesh, ct = 1; break; // the point lies on the tool mesh } - else if (cTIt->Foraminate(pnt, rcDir, tmp)) { + if (cTIt->Foraminate(pnt, rcDir, tmp)) { // check if the intersection point lies in direction rcDir of the considered // point if ((tmp - pnt) * rcDir > 0) { @@ -1083,7 +1079,7 @@ void MeshAlgorithm::GetFacetsFromToolMesh(const MeshKernel& rToolMesh, ct = 1; break; // the point lies on the tool mesh } - else if (cTIt->Foraminate(point, rcDir, tmp)) { + if (cTIt->Foraminate(point, rcDir, tmp)) { // check if the intersection point lies in direction rcDir of the considered // point if ((tmp - point) * rcDir > 0) { @@ -1160,7 +1156,7 @@ int MeshAlgorithm::Surround(const Base::BoundBox3f& rBox, const Base::Vector3f& ct = 1; break; // the point lies on the tool mesh } - else if (cTIt->Foraminate(cCorner[0], rcDir, tmp)) { + if (cTIt->Foraminate(cCorner[0], rcDir, tmp)) { // check if the intersection point lies in direction rcDir of the considered point if ((tmp - cCorner[0]) * rcDir > 0) { ct++; @@ -1218,7 +1214,7 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, for (it = aulAllElements.begin(); it != aulAllElements.end(); ++it) { bNoPointInside = true; - clGravityOfFacet.Set(0.0f, 0.0f, 0.0f); + clGravityOfFacet.Set(0.0F, 0.0F, 0.0F); MeshGeomFacet rclFacet = _rclMesh.GetFacet(*it); for (const auto& pnt : rclFacet._aclPoints) { clPt2d = fixedProj(pnt); @@ -1233,7 +1229,7 @@ void MeshAlgorithm::CheckFacets(const MeshFacetGrid& rclGrid, // if no facet point is inside the polygon then check also the gravity if (bNoPointInside) { - clGravityOfFacet *= 1.0f / 3.0f; + clGravityOfFacet *= 1.0F / 3.0F; if (clPolyBBox.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y)) && rclPoly.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y))) { @@ -1275,7 +1271,7 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, Base::ViewProjMatrix fixedProj(pclProj->getComposedProjectionMatrix()); FacetIndex index = 0; - for (MeshFacetArray::_TConstIterator it = f.begin(); it != f.end(); ++it, ++index) { + for (auto it = f.begin(); it != f.end(); ++it, ++index) { for (PointIndex ptIndex : it->_aulPoints) { pt2d = fixedProj(p[ptIndex]); @@ -1292,7 +1288,7 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, float MeshAlgorithm::Surface() const { - float fTotal = 0.0f; + float fTotal = 0.0F; MeshFacetIterator clFIter(_rclMesh); for (clFIter.Init(); clFIter.More(); clFIter.Next()) { @@ -1330,7 +1326,7 @@ void MeshAlgorithm::SubSampleAllPoints(std::vector& rclPoints) c void MeshAlgorithm::SubSampleByCount(unsigned long ulCtPoints, std::vector& rclPoints) const { - float fDist = float(sqrt(Surface() / float(ulCtPoints))); + float fDist = float(std::sqrt(Surface() / float(ulCtPoints))); SubSampleByDist(fDist, rclPoints); } @@ -1345,9 +1341,7 @@ void MeshAlgorithm::SearchFacetsFromPolyline(const std::vector& } std::set aclFacets; - for (std::vector::const_iterator pV = rclPolyline.begin(); - pV < (rclPolyline.end() - 1); - ++pV) { + for (auto pV = rclPolyline.begin(); pV < (rclPolyline.end() - 1); ++pV) { const Base::Vector3f &rclP0 = *pV, &rclP1 = *(pV + 1); // BB eines Polyline-Segments @@ -1393,8 +1387,8 @@ unsigned long MeshAlgorithm::CountBorderEdges() const { unsigned long cnt = 0; const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray; - MeshFacetArray::_TConstIterator end = rclFAry.end(); - for (MeshFacetArray::_TConstIterator it = rclFAry.begin(); it != end; ++it) { + auto end = rclFAry.end(); + for (auto it = rclFAry.begin(); it != end; ++it) { for (FacetIndex facetIndex : it->_aulNeighbours) { if (facetIndex == FACET_INDEX_MAX) { cnt++; @@ -1588,7 +1582,7 @@ bool MeshAlgorithm::ConnectLines(std::list _clToDelete; - float fToDelDist = fMinEps / 10.0f; + float fToDelDist = fMinEps / 10.0F; for (TCIter pF = rclLines.begin(); pF != rclLines.end(); ++pF) { if (Base::DistanceP2(pF->first, pF->second) < fToDelDist) { _clToDelete.push_back(pF); @@ -1701,9 +1695,7 @@ bool MeshAlgorithm::ConnectPolygons( std::list>& rclLines) const { - for (std::list>::iterator OutIter = clPolyList.begin(); - OutIter != clPolyList.end(); - ++OutIter) { + for (auto OutIter = clPolyList.begin(); OutIter != clPolyList.end(); ++OutIter) { if (OutIter->empty()) { continue; } @@ -1712,9 +1704,7 @@ bool MeshAlgorithm::ConnectPolygons( currentSort.first = OutIter->front(); currentSort.second = OutIter->back(); - for (std::list>::iterator InnerIter = clPolyList.begin(); - InnerIter != clPolyList.end(); - ++InnerIter) { + for (auto InnerIter = clPolyList.begin(); InnerIter != clPolyList.end(); ++InnerIter) { if (OutIter == InnerIter) { continue; } @@ -1766,8 +1756,8 @@ void MeshAlgorithm::GetFacetsFromPlane(const MeshFacetGrid& rclGrid, bool bInner = false; for (int i = 0; (i < 3) && !bInner; i++) { Base::Vector3f clPt = clSFacet._aclPoints[i]; - if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0f) - && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0f)) { + if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0F) + && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0F)) { bInner = true; } } @@ -1832,7 +1822,8 @@ float MeshAlgorithm::CalculateMinimumGridLength(float fLength, // estimate the minimum allowed grid length float fMinGridLen = static_cast( - pow((rBBox.LengthX() * rBBox.LengthY() * rBBox.LengthZ() / fMaxGridElements), 0.3333f)); + std::pow((rBBox.LengthX() * rBBox.LengthY() * rBBox.LengthZ() / fMaxGridElements), + 0.3333F)); return std::max(fMinGridLen, fLength); } @@ -1846,9 +1837,8 @@ void MeshRefPointToFacets::Rebuild() const MeshFacetArray& rFacets = _rclMesh.GetFacets(); _map.resize(rPoints.size()); - MeshFacetArray::_TConstIterator pFBegin = rFacets.begin(); - for (MeshFacetArray::_TConstIterator pFIter = rFacets.begin(); pFIter != rFacets.end(); - ++pFIter) { + auto pFBegin = rFacets.begin(); + for (auto pFIter = rFacets.begin(); pFIter != rFacets.end(); ++pFIter) { _map[pFIter->_aulPoints[0]].insert(pFIter - pFBegin); _map[pFIter->_aulPoints[1]].insert(pFIter - pFBegin); _map[pFIter->_aulPoints[2]].insert(pFIter - pFBegin); @@ -1875,7 +1865,7 @@ std::set MeshRefPointToFacets::NeighbourPoints(const std::vector cp, nb, lp; cp.insert(pt.begin(), pt.end()); lp.insert(pt.begin(), pt.end()); - MeshFacetArray::_TConstIterator f_it = _rclMesh.GetFacets().begin(); + auto f_it = _rclMesh.GetFacets().begin(); for (int i = 0; i < level; i++) { std::set cur; for (PointIndex it : lp) { @@ -2018,8 +2008,8 @@ void MeshRefFacetToFacets::Rebuild() _map.resize(rFacets.size()); MeshRefPointToFacets vertexFace(_rclMesh); - MeshFacetArray::_TConstIterator pFBegin = rFacets.begin(); - for (MeshFacetArray::_TConstIterator pFIter = pFBegin; pFIter != rFacets.end(); ++pFIter) { + auto pFBegin = rFacets.begin(); + for (auto pFIter = pFBegin; pFIter != rFacets.end(); ++pFIter) { for (PointIndex ptIndex : pFIter->_aulPoints) { const std::set& faces = vertexFace[ptIndex]; for (FacetIndex face : faces) { @@ -2090,7 +2080,7 @@ Base::Vector3f MeshRefPointToPoints::GetNormal(PointIndex pos) const float MeshRefPointToPoints::GetAverageEdgeLength(PointIndex index) const { const MeshPointArray& rPoints = _rclMesh.GetPoints(); - float len = 0.0f; + float len = 0.0F; const std::set& n = (*this)[index]; const Base::Vector3f& p = rPoints[index]; for (PointIndex it : n) { @@ -2122,12 +2112,12 @@ void MeshRefEdgeToFacets::Rebuild() const MeshFacetArray& rFacets = _rclMesh.GetFacets(); FacetIndex index = 0; - for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ++index) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it, ++index) { for (int i = 0; i < 3; i++) { MeshEdge e; e.first = it->_aulPoints[i]; e.second = it->_aulPoints[(i + 1) % 3]; - std::map::iterator jt = _map.find(e); + auto jt = _map.find(e); if (jt == _map.end()) { _map[e].first = index; _map[e].second = FACET_INDEX_MAX; @@ -2163,9 +2153,9 @@ void MeshRefNormalToPoints::Rebuild() float l2p20 = Base::DistanceP2(p2, p0); Base::Vector3f facenormal = _rclMesh.GetFacet(rFacet).GetNormal(); - _norm[rFacet._aulPoints[0]] += facenormal * (1.0f / (l2p01 * l2p20)); - _norm[rFacet._aulPoints[1]] += facenormal * (1.0f / (l2p12 * l2p01)); - _norm[rFacet._aulPoints[2]] += facenormal * (1.0f / (l2p20 * l2p12)); + _norm[rFacet._aulPoints[0]] += facenormal * (1.0F / (l2p01 * l2p20)); + _norm[rFacet._aulPoints[1]] += facenormal * (1.0F / (l2p12 * l2p01)); + _norm[rFacet._aulPoints[2]] += facenormal * (1.0F / (l2p20 * l2p12)); } for (auto& it : _norm) { it.Normalize(); diff --git a/src/Mod/Mesh/App/Core/Algorithm.h b/src/Mod/Mesh/App/Core/Algorithm.h index 8483707aed12..2204efa4786e 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.h +++ b/src/Mod/Mesh/App/Core/Algorithm.h @@ -126,15 +126,15 @@ class MeshExport MeshAlgorithm Base::Vector3f& rclRes, FacetIndex& rulFacet) const; /** - * Searches for the first facet of the grid element (\a rclGrid) in that the point \a rclPt lies + * Searches for the first facet of the grid element (\a rGrid) in that the point \a rPt lies * into which is a distance not higher than \a fMaxDistance. Of no such facet is found \a - * rulFacet is undefined and false is returned, otherwise true. \note If the point \a rclPt is + * uIndex is undefined and false is returned, otherwise true. \note If the point \a rPt is * outside of the grid \a rclGrid nothing is done. */ - bool FirstFacetToVertex(const Base::Vector3f& rclPt, + bool FirstFacetToVertex(const Base::Vector3f& rPt, float fMaxDistance, - const MeshFacetGrid& rclGrid, - FacetIndex& rulFacet) const; + const MeshFacetGrid& rGrid, + FacetIndex& uIndex) const; /** * Checks from the viewpoint \a rcView if the vertex \a rcVertex is visible or it is hidden by a * facet. If the vertex is visible true is returned, false otherwise. @@ -290,14 +290,14 @@ class MeshExport MeshAlgorithm const Base::ViewProjMethod* pclProj, const Base::Polygon2d& rclPoly, bool bInner, - std::vector& rclRes) const; + std::vector& facets) const; /** * Does the same as the above method unless that it doesn't use a grid. */ void CheckFacets(const Base::ViewProjMethod* pclProj, const Base::Polygon2d& rclPoly, bool bInner, - std::vector& rclRes) const; + std::vector& facets) const; /** * Determines all facets of the given array \a raclFacetIndices that lie at the edge or that * have at least neighbour facet that is not inside the array. The resulting array \a @@ -361,7 +361,7 @@ class MeshExport MeshAlgorithm const Base::Vector3f& clNormal, const MeshFacetGrid& rclGrid, std::list>& rclResult, - float fMinEps = 1.0e-2f, + float fMinEps = 1.0e-2F, bool bConnectPolygons = false) const; /** * Gets all facets that cut the plane (N,d) and that lie between the two points left and right. @@ -595,15 +595,14 @@ class MeshExport MeshRefEdgeToFacets if (e1.first < e2.first) { return true; } - else if (e1.first > e2.first) { + if (e1.first > e2.first) { return false; } - else if (e1.second < e2.second) { + if (e1.second < e2.second) { return true; } - else { - return false; - } + + return false; } }; using MeshFacetPair = std::pair; diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index b986c2eeb54b..8b728ece41f7 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -67,9 +67,9 @@ void Approximation::GetMgcVectorArray(std::vector>& rcPts) } } -void Approximation::AddPoint(const Base::Vector3f& rcVector) +void Approximation::AddPoint(const Base::Vector3f& point) { - _vPoints.push_back(rcVector); + _vPoints.push_back(point); _bIsFitted = false; } @@ -104,7 +104,7 @@ Base::Vector3f Approximation::GetGravity() const for (const auto& vPoint : _vPoints) { clGravity += vPoint; } - clGravity *= 1.0f / float(_vPoints.size()); + clGravity *= 1.0F / float(_vPoints.size()); } return clGravity; } @@ -263,7 +263,7 @@ float PlaneFit::Fit() } // make a right-handed system - if ((_vDirU % _vDirV) * _vDirW < 0.0f) { + if ((_vDirU % _vDirV) * _vDirW < 0.0F) { Base::Vector3f tmp = _vDirU; _vDirU = _vDirV; _vDirV = tmp; @@ -285,9 +285,8 @@ Base::Vector3f PlaneFit::GetBase() const if (_bIsFitted) { return _vBase; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } Base::Vector3f PlaneFit::GetDirU() const @@ -295,9 +294,8 @@ Base::Vector3f PlaneFit::GetDirU() const if (_bIsFitted) { return _vDirU; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } Base::Vector3f PlaneFit::GetDirV() const @@ -305,9 +303,8 @@ Base::Vector3f PlaneFit::GetDirV() const if (_bIsFitted) { return _vDirV; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } Base::Vector3f PlaneFit::GetNormal() const @@ -315,9 +312,8 @@ Base::Vector3f PlaneFit::GetNormal() const if (_bIsFitted) { return _vDirW; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } float PlaneFit::GetDistanceToPlane(const Base::Vector3f& rcPoint) const @@ -339,7 +335,7 @@ float PlaneFit::GetStdDeviation() const return FLOAT_MAX; } - float fSumXi = 0.0f, fSumXi2 = 0.0f, fMean = 0.0f, fDist = 0.0f; + float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; float ulPtCt = float(CountPoints()); std::list::const_iterator cIt; @@ -350,8 +346,8 @@ float PlaneFit::GetStdDeviation() const fSumXi2 += (fDist * fDist); } - fMean = (1.0f / ulPtCt) * fSumXi; - return sqrt((ulPtCt / (ulPtCt - 1.0f)) * ((1.0f / ulPtCt) * fSumXi2 - fMean * fMean)); + fMean = (1.0F / ulPtCt) * fSumXi; + return sqrt((ulPtCt / (ulPtCt - 1.0F)) * ((1.0F / ulPtCt) * fSumXi2 - fMean * fMean)); } float PlaneFit::GetSignedStdDeviation() const @@ -373,7 +369,7 @@ float PlaneFit::GetSignedStdDeviation() const for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) { clGravity += *cIt; } - clGravity *= (1.0f / ulPtCt); + clGravity *= (1.0F / ulPtCt); for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) { if ((clGravity - *cIt).Length() < fMinDist) { @@ -387,15 +383,15 @@ float PlaneFit::GetSignedStdDeviation() const // which side if ((clPt - clGravity) * GetNormal() > 0) { - fFactor = 1.0f; + fFactor = 1.0F; } else { - fFactor = -1.0f; + fFactor = -1.0F; } - fMean = 1.0f / ulPtCt * fSumXi; + fMean = 1.0F / ulPtCt * fSumXi; - return fFactor * sqrt((ulPtCt / (ulPtCt - 3.0f)) * ((1.0f / ulPtCt) * fSumXi2 - fMean * fMean)); + return fFactor * sqrt((ulPtCt / (ulPtCt - 3.0F)) * ((1.0F / ulPtCt) * fSumXi2 - fMean * fMean)); } void PlaneFit::ProjectToPlane() @@ -510,9 +506,8 @@ double QuadraticFit::GetCoeff(std::size_t ulIndex) const if (_bIsFitted) { return _fCoeff[ulIndex]; } - else { - return double(FLOAT_MAX); - } + + return double(FLOAT_MAX); } float QuadraticFit::Fit() @@ -522,7 +517,7 @@ float QuadraticFit::Fit() if (CountPoints() > 0) { std::vector> cPts; GetMgcVectorArray(cPts); - fResult = (float)Wm4::QuadraticFit3(CountPoints(), &(cPts[0]), _fCoeff); + fResult = (float)Wm4::QuadraticFit3(CountPoints(), cPts.data(), _fCoeff); _fLastResult = fResult; _bIsFitted = true; @@ -610,9 +605,8 @@ void QuadraticFit::CalcZValues(double x, double y, double& dZ1, double& dZ2) con dZ2 = double(FLOAT_MAX); return; } - else { - dDisk = sqrt(dDisk); - } + + dDisk = sqrt(dDisk); dZ1 = 0.5 * ((-_fCoeff[3] - _fCoeff[8] * x - _fCoeff[9] * y + dDisk) / _fCoeff[6]); dZ2 = 0.5 * ((-_fCoeff[3] - _fCoeff[8] * x - _fCoeff[9] * y - dDisk) / _fCoeff[6]); @@ -710,9 +704,8 @@ double SurfaceFit::PolynomFit() transform.reserve(_vPoints.size()); double dW2 = 0; - for (std::list::const_iterator it = _vPoints.begin(); it != _vPoints.end(); - ++it) { - Base::Vector3d clPoint = Base::convertTo(*it); + for (const auto& it : _vPoints) { + Base::Vector3d clPoint = Base::convertTo(it); clPoint.TransformToCoordinateSystem(bs, ex, ey); transform.push_back(clPoint); double dU = clPoint.x; @@ -1058,7 +1051,7 @@ struct LMCylinderFunctor operator()(xMinus, fvecMinus); Eigen::VectorXd fvecDiff(values()); - fvecDiff = (fvecPlus - fvecMinus) / (2.0f * epsilon); + fvecDiff = (fvecPlus - fvecMinus) / (2.0F * epsilon); fjac.block(0, i, values(), 1) = fvecDiff; } @@ -1276,9 +1269,8 @@ Base::Vector3f CylinderFit::GetBase() const if (_bIsFitted) { return _vBase; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } Base::Vector3f CylinderFit::GetAxis() const @@ -1286,9 +1278,8 @@ Base::Vector3f CylinderFit::GetAxis() const if (_bIsFitted) { return _vAxis; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } float CylinderFit::GetDistanceToCylinder(const Base::Vector3f& rcPoint) const @@ -1310,7 +1301,7 @@ float CylinderFit::GetStdDeviation() const return FLOAT_MAX; } - float fSumXi = 0.0f, fSumXi2 = 0.0f, fMean = 0.0f, fDist = 0.0f; + float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; float ulPtCt = float(CountPoints()); std::list::const_iterator cIt; @@ -1321,8 +1312,8 @@ float CylinderFit::GetStdDeviation() const fSumXi2 += (fDist * fDist); } - fMean = (1.0f / ulPtCt) * fSumXi; - return sqrt((ulPtCt / (ulPtCt - 1.0f)) * ((1.0f / ulPtCt) * fSumXi2 - fMean * fMean)); + fMean = (1.0F / ulPtCt) * fSumXi; + return sqrt((ulPtCt / (ulPtCt - 1.0F)) * ((1.0F / ulPtCt) * fSumXi2 - fMean * fMean)); } void CylinderFit::GetBounding(Base::Vector3f& bottom, Base::Vector3f& top) const @@ -1392,9 +1383,8 @@ float SphereFit::GetRadius() const if (_bIsFitted) { return _fRadius; } - else { - return FLOAT_MAX; - } + + return FLOAT_MAX; } Base::Vector3f SphereFit::GetCenter() const @@ -1402,9 +1392,8 @@ Base::Vector3f SphereFit::GetCenter() const if (_bIsFitted) { return _vCenter; } - else { - return Base::Vector3f(); - } + + return Base::Vector3f(); } float SphereFit::Fit() @@ -1483,7 +1472,7 @@ float SphereFit::GetStdDeviation() const return FLOAT_MAX; } - float fSumXi = 0.0f, fSumXi2 = 0.0f, fMean = 0.0f, fDist = 0.0f; + float fSumXi = 0.0F, fSumXi2 = 0.0F, fMean = 0.0F, fDist = 0.0F; float ulPtCt = float(CountPoints()); std::list::const_iterator cIt; @@ -1494,8 +1483,8 @@ float SphereFit::GetStdDeviation() const fSumXi2 += (fDist * fDist); } - fMean = (1.0f / ulPtCt) * fSumXi; - return sqrt((ulPtCt / (ulPtCt - 1.0f)) * ((1.0f / ulPtCt) * fSumXi2 - fMean * fMean)); + fMean = (1.0F / ulPtCt) * fSumXi; + return sqrt((ulPtCt / (ulPtCt - 1.0F)) * ((1.0F / ulPtCt) * fSumXi2 - fMean * fMean)); } void SphereFit::ProjectToSphere() @@ -1531,15 +1520,14 @@ float PolynomialFit::Fit() x.reserve(_vPoints.size()); y.reserve(_vPoints.size()); z.reserve(_vPoints.size()); - for (std::list::const_iterator it = _vPoints.begin(); it != _vPoints.end(); - ++it) { - x.push_back(it->x); - y.push_back(it->y); - z.push_back(it->z); + for (const auto& it : _vPoints) { + x.push_back(it.x); + y.push_back(it.y); + z.push_back(it.z); } try { - float* coeff = Wm4::PolyFit3(_vPoints.size(), &(x[0]), &(y[0]), &(z[0]), 2, 2); + float* coeff = Wm4::PolyFit3(_vPoints.size(), x.data(), y.data(), z.data(), 2, 2); for (int i = 0; i < 9; i++) { _fCoeff[i] = coeff[i]; } @@ -1548,7 +1536,7 @@ float PolynomialFit::Fit() return FLOAT_MAX; } - return 0.0f; + return 0.0F; } float PolynomialFit::Value(float x, float y) const diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 3ccb599fc55c..1bbe71ebd54d 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -133,19 +133,19 @@ class MeshExport Approximation /** * Add point for the fit algorithm. */ - void AddPoint(const Base::Vector3f& rcVector); + void AddPoint(const Base::Vector3f& point); /** * Add points for the fit algorithm. */ - void AddPoints(const std::vector& rvPointVect); + void AddPoints(const std::vector& points); /** * Add points for the fit algorithm. */ - void AddPoints(const std::set& rsPointSet); + void AddPoints(const std::set& points); /** * Add points for the fit algorithm. */ - void AddPoints(const std::list& rsPointList); + void AddPoints(const std::list& points); /** * Add points for the fit algorithm. */ diff --git a/src/Mod/Mesh/App/Core/Builder.cpp b/src/Mod/Mesh/App/Core/Builder.cpp index 6da208df6011..0989ba1eace9 100644 --- a/src/Mod/Mesh/App/Core/Builder.cpp +++ b/src/Mod/Mesh/App/Core/Builder.cpp @@ -73,7 +73,7 @@ void MeshBuilder::Initialize(size_t ctFacets, bool deletion) // memory with 10% surcharge To save memory we hold an array with iterators that point to // the right vertex (insertion order) in the set, instead of holding the vertex array twice. size_t ctPoints = ctFacets / 2; - _pointsIterator.reserve(static_cast(float(ctPoints) * 1.10f)); + _pointsIterator.reserve(static_cast(float(ctPoints) * 1.10F)); _ptIdx = 0; } else { @@ -90,7 +90,7 @@ void MeshBuilder::Initialize(size_t ctFacets, bool deletion) size_t newCtFacets = _meshKernel._aclFacetArray.size() + ctFacets; _meshKernel._aclFacetArray.reserve(newCtFacets); size_t ctPoints = newCtFacets / 2; - _pointsIterator.reserve(static_cast(float(ctPoints) * 1.10f)); + _pointsIterator.reserve(static_cast(float(ctPoints) * 1.10F)); } this->_seq = new Base::SequencerLauncher("create mesh structure...", ctFacets * 2); @@ -132,7 +132,7 @@ void MeshBuilder::AddFacet(Base::Vector3f* facetPoints, unsigned char flag, unsi // adjust circulation direction if ((((facetPoints[1] - facetPoints[0]) % (facetPoints[2] - facetPoints[0])) * facetPoints[3]) - < 0.0f) { + < 0.0F) { std::swap(facetPoints[1], facetPoints[2]); } @@ -306,15 +306,14 @@ struct MeshFastBuilder::Private if (x != rhs.x) { return x < rhs.x; } - else if (y != rhs.y) { + if (y != rhs.y) { return y < rhs.y; } - else if (z != rhs.z) { + if (z != rhs.z) { return z < rhs.z; } - else { - return false; - } + + return false; } }; diff --git a/src/Mod/Mesh/App/Core/Builder.h b/src/Mod/Mesh/App/Core/Builder.h index e9ab351bb801..2ebe70473544 100644 --- a/src/Mod/Mesh/App/Core/Builder.h +++ b/src/Mod/Mesh/App/Core/Builder.h @@ -114,7 +114,7 @@ class MeshExport MeshBuilder void RemoveUnreferencedPoints(); public: - explicit MeshBuilder(MeshKernel& rclM); + explicit MeshBuilder(MeshKernel& kernel); ~MeshBuilder(); MeshBuilder(const MeshBuilder&) = delete; diff --git a/src/Mod/Mesh/App/Core/Curvature.cpp b/src/Mod/Mesh/App/Core/Curvature.cpp index 8c36fed6ce7b..07334f7785e3 100644 --- a/src/Mod/Mesh/App/Core/Curvature.cpp +++ b/src/Mod/Mesh/App/Core/Curvature.cpp @@ -53,7 +53,7 @@ namespace sp = std::placeholders; MeshCurvature::MeshCurvature(const MeshKernel& kernel) : myKernel(kernel) , myMinPoints(20) - , myRadius(0.5f) + , myRadius(0.5F) { mySegment.resize(kernel.CountFacets()); std::generate(mySegment.begin(), mySegment.end(), Base::iotaGen(0)); @@ -62,7 +62,7 @@ MeshCurvature::MeshCurvature(const MeshKernel& kernel) MeshCurvature::MeshCurvature(const MeshKernel& kernel, std::vector segm) : myKernel(kernel) , myMinPoints(20) - , myRadius(0.5f) + , myRadius(0.5F) , mySegment(std::move(segm)) {} @@ -319,9 +319,9 @@ void MeshCurvature::ComputePerVertex() // compute vertex based curvatures Wm4::MeshCurvature meshCurv(myKernel.CountPoints(), - &(aPnts[0]), + aPnts.data(), myKernel.CountFacets(), - &(aIdx[0])); + aIdx.data()); // get curvature information now const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); @@ -401,7 +401,7 @@ CurvatureInfo FacetCurvature::Compute(FacetIndex index) const } float min_points = myMinPoints; float use_points = point_indices.size(); - searchDist = searchDist * sqrt(min_points / use_points); + searchDist = searchDist * std::sqrt(min_points / use_points); } while ((point_indices.size() < myMinPoints) && (attempts++ < 3)); std::vector fitPoints; diff --git a/src/Mod/Mesh/App/Core/CylinderFit.cpp b/src/Mod/Mesh/App/Core/CylinderFit.cpp index 7a20d73bbb85..face997e6b44 100644 --- a/src/Mod/Mesh/App/Core/CylinderFit.cpp +++ b/src/Mod/Mesh/App/Core/CylinderFit.cpp @@ -62,6 +62,7 @@ #endif #include +#include #include #include "CylinderFit.h" @@ -100,10 +101,8 @@ void CylinderFit::SetApproximations(const Base::Vector3d& base, const Base::Vect _vAxis.Normalize(); _dRadius = 0.0; if (!_vPoints.empty()) { - for (std::list::const_iterator cIt = _vPoints.begin(); - cIt != _vPoints.end(); - ++cIt) { - _dRadius += Base::Vector3d(cIt->x, cIt->y, cIt->z).DistanceToLine(_vBase, _vAxis); + for (const auto& it : _vPoints) { + _dRadius += Base::Vector3d(it.x, it.y, it.z).DistanceToLine(_vBase, _vAxis); } _dRadius /= (double)_vPoints.size(); } @@ -136,9 +135,8 @@ double CylinderFit::GetRadius() const if (_bIsFitted) { return _dRadius; } - else { - return 0.0; - } + + return 0.0; } Base::Vector3d CylinderFit::GetBase() const @@ -146,9 +144,8 @@ Base::Vector3d CylinderFit::GetBase() const if (_bIsFitted) { return _vBase; } - else { - return Base::Vector3d(); - } + + return Base::Vector3d(); } Base::Vector3d CylinderFit::GetAxis() const @@ -156,9 +153,8 @@ Base::Vector3d CylinderFit::GetAxis() const if (_bIsFitted) { return _vAxis; } - else { - return Base::Vector3d(); - } + + return Base::Vector3d(); } int CylinderFit::GetNumIterations() const @@ -166,17 +162,16 @@ int CylinderFit::GetNumIterations() const if (_bIsFitted) { return _numIter; } - else { - return 0; - } + + return 0; } float CylinderFit::GetDistanceToCylinder(const Base::Vector3f& rcPoint) const { float fResult = FLOAT_MAX; if (_bIsFitted) { - fResult = Base::Vector3d(rcPoint.x, rcPoint.y, rcPoint.z).DistanceToLine(_vBase, _vAxis) - - _dRadius; + Base::Vector3d pt(rcPoint.x, rcPoint.y, rcPoint.z); + fResult = static_cast(pt.DistanceToLine(_vBase, _vAxis) - _dRadius); } return fResult; } @@ -190,7 +185,9 @@ float CylinderFit::GetStdDeviation() const return FLOAT_MAX; } - double sumXi = 0.0, sumXi2 = 0.0, dist = 0.0; + double sumXi = 0.0; + double sumXi2 = 0.0; + double dist = 0.0; for (auto it : _vPoints) { dist = GetDistanceToCylinder(it); sumXi += dist; @@ -199,13 +196,13 @@ float CylinderFit::GetStdDeviation() const double N = static_cast(CountPoints()); double mean = sumXi / N; - return sqrt((N / (N - 1.0)) * (sumXi2 / N - mean * mean)); + return static_cast(sqrt((N / (N - 1.0)) * (sumXi2 / N - mean * mean))); } void CylinderFit::ProjectToCylinder() { - Base::Vector3f cBase(_vBase.x, _vBase.y, _vBase.z); - Base::Vector3f cAxis(_vAxis.x, _vAxis.y, _vAxis.z); + auto cBase = Base::convertTo(_vBase); + auto cAxis = Base::convertTo(_vAxis); for (auto& cPnt : _vPoints) { if (cPnt.DistanceToLine(cBase, cAxis) > 0) { @@ -259,10 +256,8 @@ void CylinderFit::ComputeApproximationsLine() _vBase.Set(kLine.Origin.X(), kLine.Origin.Y(), kLine.Origin.Z()); _vAxis.Set(kLine.Direction.X(), kLine.Direction.Y(), kLine.Direction.Z()); - for (std::list::const_iterator cIt = _vPoints.begin(); - cIt != _vPoints.end(); - ++cIt) { - _dRadius += Base::Vector3d(cIt->x, cIt->y, cIt->z).DistanceToLine(_vBase, _vAxis); + for (const auto& it : _vPoints) { + _dRadius += Base::Vector3d(it.x, it.y, it.z).DistanceToLine(_vBase, _vAxis); } _dRadius /= (double)_vPoints.size(); } @@ -275,7 +270,8 @@ float CylinderFit::Fit() _numIter = 0; // A minimum of 5 surface points is needed to define a cylinder - if (CountPoints() < 5) { + const int minPts = 5; + if (CountPoints() < minPts) { return FLOAT_MAX; } @@ -295,9 +291,10 @@ float CylinderFit::Fit() findBestSolDirection(solDir); // Initialise some matrices and vectors + const int dim = 5; std::vector residuals(CountPoints(), Base::Vector3d(0.0, 0.0, 0.0)); Matrix5x5 atpa; - Eigen::VectorXd atpl(5); + Eigen::VectorXd atpl(dim); // Iteration loop... double sigma0 {}; @@ -317,11 +314,12 @@ float CylinderFit::Fit() // Check parameter convergence cont = false; + // x(0), x(1): the two position parameter corrections + // x(2),x(3): the two direction parameter corrections + // x(4): the radius correction if ((fabs(x(0)) > _posConvLimit) || (fabs(x(1)) > _posConvLimit) - || // the two position parameter corrections - (fabs(x(2)) > _dirConvLimit) || (fabs(x(3)) > _dirConvLimit) - || // the two direction parameter corrections - (fabs(x(4)) > _posConvLimit)) { // the radius correction + || (fabs(x(2)) > _dirConvLimit) || (fabs(x(3)) > _dirConvLimit) + || (fabs(x(4)) > _posConvLimit)) { cont = true; } @@ -381,7 +379,7 @@ void CylinderFit::findBestSolDirection(SolutionD& solDir) } double fixedVal = 0.0; - double lambda; + double lambda {}; switch (solDir) { case solL: fixedVal = meanXObs(); @@ -413,10 +411,8 @@ double CylinderFit::meanXObs() { double mx = 0.0; if (!_vPoints.empty()) { - for (std::list::const_iterator cIt = _vPoints.begin(); - cIt != _vPoints.end(); - ++cIt) { - mx += cIt->x; + for (const auto& it : _vPoints) { + mx += it.x; } mx /= double(_vPoints.size()); } @@ -427,10 +423,8 @@ double CylinderFit::meanYObs() { double my = 0.0; if (!_vPoints.empty()) { - for (std::list::const_iterator cIt = _vPoints.begin(); - cIt != _vPoints.end(); - ++cIt) { - my += cIt->y; + for (const auto& it : _vPoints) { + my += it.y; } my /= double(_vPoints.size()); } @@ -441,10 +435,8 @@ double CylinderFit::meanZObs() { double mz = 0.0; if (!_vPoints.empty()) { - for (std::list::const_iterator cIt = _vPoints.begin(); - cIt != _vPoints.end(); - ++cIt) { - mz += cIt->z; + for (const auto& it : _vPoints) { + mz += it.z; } mz /= double(_vPoints.size()); } @@ -465,11 +457,12 @@ void CylinderFit::setupNormalEquationMatrices(SolutionD solDir, // For each point, setup the observation equation coefficients and add their // contribution into the normal equation matrices - double a[5] {}, b[3] {}; - double f0 {}, qw {}; - std::vector::const_iterator vIt = residuals.begin(); - std::list::const_iterator cIt; - for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { + DoubleArray5 a {}; + DoubleArray3 b {}; + double f0 {}; + double qw {}; + auto vIt = residuals.begin(); + for (auto cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { // if (using this point) { // currently all given points are used (could modify this if // eliminating outliers, etc.... setupObservation(solDir, *cIt, *vIt, a, f0, qw, b); @@ -479,6 +472,8 @@ void CylinderFit::setupNormalEquationMatrices(SolutionD solDir, setLowerPart(atpa); } +// clang-format off +// NOLINTBEGIN // Sets up contributions of given observation to the quasi parametric // normal equation matrices. Assumes uncorrelated coordinates. // point ... point @@ -490,10 +485,10 @@ void CylinderFit::setupNormalEquationMatrices(SolutionD solDir, void CylinderFit::setupObservation(SolutionD solDir, const Base::Vector3f& point, const Base::Vector3d& residual, - double a[5], + DoubleArray5& a, double& f0, double& qw, - double b[3]) const + DoubleArray3& b) const { // This adjustment requires an update of the observation approximations // because the residuals do not have a linear relationship. @@ -503,8 +498,7 @@ void CylinderFit::setupObservation(SolutionD solDir, double zEstimate = (double)point.z + residual.z; // intermediate parameters - double lambda = _vAxis.x * (xEstimate - _vBase.x) + _vAxis.y * (yEstimate - _vBase.y) - + _vAxis.z * (zEstimate - _vBase.z); + double lambda = _vAxis.x * (xEstimate - _vBase.x) + _vAxis.y * (yEstimate - _vBase.y) + _vAxis.z * (zEstimate - _vBase.z); double x0 = _vBase.x + lambda * _vAxis.x; double y0 = _vBase.y + lambda * _vAxis.y; double z0 = _vBase.z + lambda * _vAxis.z; @@ -516,12 +510,9 @@ void CylinderFit::setupObservation(SolutionD solDir, double dz00 = _vBase.z - zEstimate; // partials of the observations - b[0] = - 2.0 * (dx - _vAxis.x * _vAxis.x * dx - _vAxis.x * _vAxis.y * dy - _vAxis.x * _vAxis.z * dz); - b[1] = - 2.0 * (dy - _vAxis.x * _vAxis.y * dx - _vAxis.y * _vAxis.y * dy - _vAxis.y * _vAxis.z * dz); - b[2] = - 2.0 * (dz - _vAxis.x * _vAxis.z * dx - _vAxis.y * _vAxis.z * dy - _vAxis.z * _vAxis.z * dz); + b[0] = 2.0 * (dx - _vAxis.x * _vAxis.x * dx - _vAxis.x * _vAxis.y * dy - _vAxis.x * _vAxis.z * dz); + b[1] = 2.0 * (dy - _vAxis.x * _vAxis.y * dx - _vAxis.y * _vAxis.y * dy - _vAxis.y * _vAxis.z * dz); + b[2] = 2.0 * (dz - _vAxis.x * _vAxis.z * dx - _vAxis.y * _vAxis.z * dy - _vAxis.z * _vAxis.z * dz); double ddxdl {}, ddydl {}, ddzdl {}; double ddxdm {}, ddydm {}, ddzdm {}; @@ -531,16 +522,12 @@ void CylinderFit::setupObservation(SolutionD solDir, switch (solDir) { case solL: // order of parameters: Yc, Zc, M, N, R - ddxdm = -2.0 * _vAxis.y * dx00 + (_vAxis.x - _vAxis.y * _vAxis.y / _vAxis.x) * dy00 - - (_vAxis.y * _vAxis.z / _vAxis.x) * dz00; - ddydm = (_vAxis.x - _vAxis.y * _vAxis.y / _vAxis.x) * dx00 + 2.0 * _vAxis.y * dy00 - + _vAxis.z * dz00; + ddxdm = -2.0 * _vAxis.y * dx00 + (_vAxis.x - _vAxis.y * _vAxis.y / _vAxis.x) * dy00 - (_vAxis.y * _vAxis.z / _vAxis.x) * dz00; + ddydm = (_vAxis.x - _vAxis.y * _vAxis.y / _vAxis.x) * dx00 + 2.0 * _vAxis.y * dy00 + _vAxis.z * dz00; ddzdm = -(_vAxis.y * _vAxis.z / _vAxis.x) * dx00 + _vAxis.z * dy00; - ddxdn = -2.0 * _vAxis.z * dx00 - (_vAxis.y * _vAxis.z / _vAxis.x) * dy00 - + (_vAxis.x - _vAxis.z * _vAxis.z / _vAxis.x) * dz00; + ddxdn = -2.0 * _vAxis.z * dx00 - (_vAxis.y * _vAxis.z / _vAxis.x) * dy00 + (_vAxis.x - _vAxis.z * _vAxis.z / _vAxis.x) * dz00; ddydn = -(_vAxis.y * _vAxis.z / _vAxis.x) * dx00 + _vAxis.y * dz00; - ddzdn = (_vAxis.x - _vAxis.z * _vAxis.z / _vAxis.x) * dx00 + _vAxis.y * dy00 - + 2.0 * _vAxis.z * dz00; + ddzdn = (_vAxis.x - _vAxis.z * _vAxis.z / _vAxis.x) * dx00 + _vAxis.y * dy00 + 2.0 * _vAxis.z * dz00; a[0] = -b[1]; a[1] = -b[2]; a[2] = 2.0 * (dx * ddxdm + dy * ddydm + dz * ddzdm); @@ -549,16 +536,12 @@ void CylinderFit::setupObservation(SolutionD solDir, break; case solM: // order of parameters: Xc, Zc, L, N, R - ddxdl = 2.0 * _vAxis.x * dx00 + (_vAxis.y - _vAxis.x * _vAxis.x / _vAxis.y) * dy00 - + _vAxis.z * dz00; - ddydl = (_vAxis.y - _vAxis.x * _vAxis.x / _vAxis.y) * dx00 - 2.0 * _vAxis.x * dy00 - - (_vAxis.x * _vAxis.z / _vAxis.y) * dz00; + ddxdl = 2.0 * _vAxis.x * dx00 + (_vAxis.y - _vAxis.x * _vAxis.x / _vAxis.y) * dy00 + _vAxis.z * dz00; + ddydl = (_vAxis.y - _vAxis.x * _vAxis.x / _vAxis.y) * dx00 - 2.0 * _vAxis.x * dy00 - (_vAxis.x * _vAxis.z / _vAxis.y) * dz00; ddzdl = _vAxis.z * dx00 - (_vAxis.x * _vAxis.z / _vAxis.y) * dy00; ddxdn = -(_vAxis.x * _vAxis.z / _vAxis.y) * dy00 + _vAxis.x * dz00; - ddydn = -(_vAxis.x * _vAxis.z / _vAxis.y) * dx00 - 2.0 * _vAxis.z * dy00 - + (_vAxis.y - _vAxis.z * _vAxis.z / _vAxis.y) * dz00; - ddzdn = _vAxis.x * dx00 + (_vAxis.y - _vAxis.z * _vAxis.z / _vAxis.y) * dy00 - + 2.0 * _vAxis.z * dz00; + ddydn = -(_vAxis.x * _vAxis.z / _vAxis.y) * dx00 - 2.0 * _vAxis.z * dy00 + (_vAxis.y - _vAxis.z * _vAxis.z / _vAxis.y) * dz00; + ddzdn = _vAxis.x * dx00 + (_vAxis.y - _vAxis.z * _vAxis.z / _vAxis.y) * dy00 + 2.0 * _vAxis.z * dz00; a[0] = -b[0]; a[1] = -b[2]; a[2] = 2.0 * (dx * ddxdl + dy * ddydl + dz * ddzdl); @@ -567,16 +550,12 @@ void CylinderFit::setupObservation(SolutionD solDir, break; case solN: // order of parameters: Xc, Yc, L, M, R - ddxdl = 2.0 * _vAxis.x * dx00 + _vAxis.y * dy00 - + (_vAxis.z - _vAxis.x * _vAxis.x / _vAxis.z) * dz00; + ddxdl = 2.0 * _vAxis.x * dx00 + _vAxis.y * dy00 + (_vAxis.z - _vAxis.x * _vAxis.x / _vAxis.z) * dz00; ddydl = _vAxis.y * dx00 - (_vAxis.x * _vAxis.y / _vAxis.z) * dz00; - ddzdl = (_vAxis.z - _vAxis.x * _vAxis.x / _vAxis.z) * dx00 - - (_vAxis.x * _vAxis.y / _vAxis.z) * dy00 - 2.0 * _vAxis.x * dz00; + ddzdl = (_vAxis.z - _vAxis.x * _vAxis.x / _vAxis.z) * dx00 - (_vAxis.x * _vAxis.y / _vAxis.z) * dy00 - 2.0 * _vAxis.x * dz00; ddxdm = _vAxis.x * dy00 - (_vAxis.x * _vAxis.y / _vAxis.z) * dz00; - ddydm = _vAxis.x * dx00 + 2.0 * _vAxis.y * dy00 - + (_vAxis.z - _vAxis.y * _vAxis.y / _vAxis.z) * dz00; - ddzdm = -(_vAxis.x * _vAxis.y / _vAxis.z) * dx00 - + (_vAxis.z - _vAxis.y * _vAxis.y / _vAxis.z) * dy00 - 2.0 * _vAxis.y * dz00; + ddydm = _vAxis.x * dx00 + 2.0 * _vAxis.y * dy00 + (_vAxis.z - _vAxis.y * _vAxis.y / _vAxis.z) * dz00; + ddzdm = -(_vAxis.x * _vAxis.y / _vAxis.z) * dx00 + (_vAxis.z - _vAxis.y * _vAxis.y / _vAxis.z) * dy00 - 2.0 * _vAxis.y * dz00; a[0] = -b[0]; a[1] = -b[1]; a[2] = 2.0 * (dx * ddxdl + dy * ddydl + dz * ddzdl); @@ -586,8 +565,7 @@ void CylinderFit::setupObservation(SolutionD solDir, } // free term - f0 = _dRadius * _dRadius - dx * dx - dy * dy - dz * dz + b[0] * residual.x + b[1] * residual.y - + b[2] * residual.z; + f0 = _dRadius * _dRadius - dx * dx - dy * dy - dz * dz + b[0] * residual.x + b[1] * residual.y + b[2] * residual.z; // quasi weight (using equal weights for cylinder point coordinate observations) // w[0] = 1.0; @@ -596,6 +574,8 @@ void CylinderFit::setupObservation(SolutionD solDir, // qw = 1.0 / (b[0] * b[0] / w[0] + b[1] * b[1] / w[1] + b[2] * b[2] / w[2]); qw = 1.0 / (b[0] * b[0] + b[1] * b[1] + b[2] * b[2]); } +// NOLINTEND +// clang-format on // Computes contribution of the given observation equation on the normal equation matrices // Call this for each observation (point) @@ -607,15 +587,16 @@ void CylinderFit::setupObservation(SolutionD solDir, // pi ... weight of observation (= quasi weight qw for this solution) // atpa ... 5x5 normal equation matrix // atpl ... 5x1 matrix/vector (right-hand side of equations) -void CylinderFit::addObservationU(double a[5], +void CylinderFit::addObservationU(DoubleArray5 a, double li, double pi, Matrix5x5& atpa, Eigen::VectorXd& atpl) const { - for (int i = 0; i < 5; ++i) { + const int dim = 5; + for (int i = 0; i < dim; ++i) { double aipi = a[i] * pi; - for (int j = i; j < 5; ++j) { + for (int j = i; j < dim; ++j) { atpa(i, j) += aipi * a[j]; // atpa(j, i) = atpa(i, j); // it's a symmetrical matrix, we'll set this later after all // observations processed @@ -628,8 +609,9 @@ void CylinderFit::addObservationU(double a[5], // This is done after all the observations have been added void CylinderFit::setLowerPart(Matrix5x5& atpa) const { - for (int i = 0; i < 5; ++i) { - for (int j = i + 1; j < 5; ++j) { // skip the diagonal elements + const int dim = 5; + for (int i = 0; i < dim; ++i) { + for (int j = i + 1; j < dim; ++j) { // skip the diagonal elements atpa(j, i) = atpa(i, j); } } @@ -643,25 +625,29 @@ bool CylinderFit::computeResiduals(SolutionD solDir, double vConvLimit, bool& vConverged) const { + const int dim = 5; + // A minimum of 5 surface points is needed to define a cylinder + const int minPts = 5; vConverged = true; int nPtsUsed = 0; sigma0 = 0.0; - double a[5] {}, b[3] {}; - double f0 {}, qw {}; + DoubleArray5 a {}; + DoubleArray3 b {}; + double f0 {}; + double qw {}; // double maxdVx = 0.0; // double maxdVy = 0.0; // double maxdVz = 0.0; // double rmsVv = 0.0; - std::vector::iterator vIt = residuals.begin(); - std::list::const_iterator cIt; - for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { + auto vIt = residuals.begin(); + for (auto cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { // if (using this point) { // currently all given points are used (could modify this if // eliminating outliers, etc.... ++nPtsUsed; Base::Vector3d& v = *vIt; setupObservation(solDir, *cIt, v, a, f0, qw, b); double qv = -f0; - for (int i = 0; i < 5; ++i) { + for (int i = 0; i < dim; ++i) { qv += a[i] * x(i); } @@ -699,12 +685,11 @@ bool CylinderFit::computeResiduals(SolutionD solDir, } // Compute degrees of freedom and sigma0 - if (nPtsUsed < 5) // A minimum of 5 surface points is needed to define a cylinder - { + if (nPtsUsed < minPts) { sigma0 = 0.0; return false; } - int df = nPtsUsed - 5; + int df = nPtsUsed - minPts; if (df == 0) { sigma0 = 0.0; } @@ -748,7 +733,9 @@ bool CylinderFit::updateParameters(SolutionD solDir, const Eigen::VectorXd& x) } // Update the dependent axis direction parameter - double l2 {}, m2 {}, n2 {}; + double l2 {}; + double m2 {}; + double n2 {}; switch (solDir) { case solL: l2 = 1.0 - _vAxis.y * _vAxis.y - _vAxis.z * _vAxis.z; diff --git a/src/Mod/Mesh/App/Core/CylinderFit.h b/src/Mod/Mesh/App/Core/CylinderFit.h index 817c586a1aeb..0d08456ee1ef 100644 --- a/src/Mod/Mesh/App/Core/CylinderFit.h +++ b/src/Mod/Mesh/App/Core/CylinderFit.h @@ -33,6 +33,8 @@ namespace MeshCoreFit { using Matrix5x5 = Eigen::Matrix; +using DoubleArray3 = std::array; +using DoubleArray5 = std::array; /** * Best-fit cylinder for a given set of points. @@ -144,14 +146,14 @@ class MeshExport CylinderFit: public MeshCore::Approximation void setupObservation(SolutionD solDir, const Base::Vector3f& point, const Base::Vector3d& residual, - double a[5], + DoubleArray5& a, double& f0, double& qw, - double b[3]) const; + DoubleArray3& b) const; /** * Computes contribution of the given observation equation on the normal equation matrices */ - void addObservationU(double a[5], + void addObservationU(DoubleArray5 a, double li, double pi, Matrix5x5& atpa, diff --git a/src/Mod/Mesh/App/Core/Decimation.cpp b/src/Mod/Mesh/App/Core/Decimation.cpp index b9d0a2389a0c..096b438add11 100644 --- a/src/Mod/Mesh/App/Core/Decimation.cpp +++ b/src/Mod/Mesh/App/Core/Decimation.cpp @@ -61,7 +61,7 @@ void MeshSimplify::simplify(float tolerance, float reduction) alg.triangles.push_back(t); } - int target_count = static_cast(static_cast(facets.size()) * (1.0f - reduction)); + int target_count = static_cast(static_cast(facets.size()) * (1.0F - reduction)); // Simplification starts alg.simplify_mesh(target_count, tolerance); diff --git a/src/Mod/Mesh/App/Core/Decimation.h b/src/Mod/Mesh/App/Core/Decimation.h index ba19bfd9cb1e..cce68b8dd33a 100644 --- a/src/Mod/Mesh/App/Core/Decimation.h +++ b/src/Mod/Mesh/App/Core/Decimation.h @@ -33,7 +33,7 @@ class MeshKernel; class MeshExport MeshSimplify { public: - MeshSimplify(MeshKernel&); // explicit bombs + explicit MeshSimplify(MeshKernel&); void simplify(float tolerance, float reduction); void simplify(int targetSize); diff --git a/src/Mod/Mesh/App/Core/Definitions.cpp b/src/Mod/Mesh/App/Core/Definitions.cpp index ff8882c39913..7d19d8ec6795 100644 --- a/src/Mod/Mesh/App/Core/Definitions.cpp +++ b/src/Mod/Mesh/App/Core/Definitions.cpp @@ -49,7 +49,7 @@ void MeshDefinitions::SetMinPointDistance(float fMin) { _fMinPointDistance = fMin; _fMinPointDistanceP2 = fMin * fMin; - _fMinPointDistanceD1 = float(sqrt((fMin * fMin) / 3.0f)); + _fMinPointDistanceD1 = float(std::sqrt((fMin * fMin) / 3.0F)); } } // namespace MeshCore diff --git a/src/Mod/Mesh/App/Core/Definitions.h b/src/Mod/Mesh/App/Core/Definitions.h index 9337ab396e86..e8b2569d2074 100644 --- a/src/Mod/Mesh/App/Core/Definitions.h +++ b/src/Mod/Mesh/App/Core/Definitions.h @@ -30,8 +30,8 @@ #include // default values -#define MESH_MIN_PT_DIST 1.0e-6f -#define MESH_MIN_EDGE_LEN 1.0e-3f +#define MESH_MIN_PT_DIST 1.0e-6F +#define MESH_MIN_EDGE_LEN 1.0e-3F #define MESH_MIN_EDGE_ANGLE 2.0 #define MESH_REMOVE_MIN_LEN true #define MESH_REMOVE_G3_EDGES true @@ -39,10 +39,10 @@ /* * general constant definitions */ -#define FLOAT_EPS 1.0e-4f +#define FLOAT_EPS 1.0e-4F #ifndef FLOAT_MAX -#define FLOAT_MAX 1e30f +#define FLOAT_MAX 1e30F #endif #ifndef DOUBLE_MAX diff --git a/src/Mod/Mesh/App/Core/Degeneration.cpp b/src/Mod/Mesh/App/Core/Degeneration.cpp index b01895a62412..2b27f5297f3e 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.cpp +++ b/src/Mod/Mesh/App/Core/Degeneration.cpp @@ -64,7 +64,7 @@ std::vector MeshEvalInvalids::GetIndices() const const MeshFacetArray& rFaces = _rclMesh.GetFacets(); const MeshPointArray& rPoints = _rclMesh.GetPoints(); FacetIndex ind = 0; - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { if (!it->IsValid()) { aInds.push_back(ind); } @@ -108,7 +108,7 @@ struct Vertex_EqualTo if ((*x) < (*y)) { return false; } - else if ((*y) < (*x)) { + if ((*y) < (*x)) { return false; } return true; @@ -132,16 +132,14 @@ bool MeshEvalDuplicatePoints::Evaluate() const MeshPointArray& rPoints = _rclMesh.GetPoints(); std::vector vertices; vertices.reserve(rPoints.size()); - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it) { vertices.push_back(it); } // if there are two adjacent vertices which have the same coordinates std::sort(vertices.begin(), vertices.end(), Vertex_Less()); - if (std::adjacent_find(vertices.begin(), vertices.end(), Vertex_EqualTo()) < vertices.end()) { - return false; - } - return true; + return (std::adjacent_find(vertices.begin(), vertices.end(), Vertex_EqualTo()) + == vertices.end()); } std::vector MeshEvalDuplicatePoints::GetIndices() const @@ -152,7 +150,7 @@ std::vector MeshEvalDuplicatePoints::GetIndices() const const MeshPointArray& rPoints = _rclMesh.GetPoints(); std::vector vertices; vertices.reserve(rPoints.size()); - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it) { vertices.push_back(it); } @@ -182,7 +180,7 @@ bool MeshFixDuplicatePoints::Fixup() const MeshPointArray& rPoints = _rclMesh.GetPoints(); std::vector vertices; vertices.reserve(rPoints.size()); - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it) { vertices.push_back(it); } @@ -196,7 +194,7 @@ bool MeshFixDuplicatePoints::Fixup() while (next < vertices.end()) { next = std::adjacent_find(next, vertices.end(), pred); if (next < vertices.end()) { - std::vector::iterator first = next; + auto first = next; PointIndex first_index = *first - rPoints.begin(); ++next; while (next < vertices.end() && pred(*first, *next)) { @@ -212,7 +210,7 @@ bool MeshFixDuplicatePoints::Fixup() MeshFacetArray& rFacets = _rclMesh._aclFacetArray; for (auto& it : rFacets) { for (PointIndex& point : it._aulPoints) { - std::map::iterator pt = mapPointIndex.find(point); + auto pt = mapPointIndex.find(point); if (pt != mapPointIndex.end()) { point = pt->second; } @@ -244,7 +242,7 @@ std::vector MeshEvalNaNPoints::GetIndices() const { std::vector aInds; const MeshPointArray& rPoints = _rclMesh.GetPoints(); - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it) { if (boost::math::isnan(it->x) || boost::math::isnan(it->y) || boost::math::isnan(it->z)) { aInds.push_back(it - rPoints.begin()); } @@ -257,7 +255,7 @@ bool MeshFixNaNPoints::Fixup() { std::vector aInds; const MeshPointArray& rPoints = _rclMesh.GetPoints(); - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it) { if (boost::math::isnan(it->x) || boost::math::isnan(it->y) || boost::math::isnan(it->z)) { aInds.push_back(it - rPoints.begin()); } @@ -325,21 +323,20 @@ struct MeshFacet_Less if (x0 < y0) { return true; } - else if (x0 > y0) { + if (x0 > y0) { return false; } - else if (x1 < y1) { + if (x1 < y1) { return true; } - else if (x1 > y1) { + if (x1 > y1) { return false; } - else if (x2 < y2) { + if (x2 < y2) { return true; } - else { - return false; - } + + return false; } }; @@ -359,8 +356,8 @@ struct MeshFacet_EqualTo && x->_aulPoints[2] == y->_aulPoints[(i + 2) % 3]) { return true; } - else if (x->_aulPoints[1] == y->_aulPoints[(i + 2) % 3] - && x->_aulPoints[2] == y->_aulPoints[(i + 1) % 3]) { + if (x->_aulPoints[1] == y->_aulPoints[(i + 2) % 3] + && x->_aulPoints[2] == y->_aulPoints[(i + 1) % 3]) { return true; } } @@ -374,7 +371,7 @@ bool MeshEvalDuplicateFacets::Evaluate() { std::set aFaces; const MeshFacetArray& rFaces = _rclMesh.GetFacets(); - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it) { std::pair::iterator, bool> pI = aFaces.insert(it); if (!pI.second) { return false; @@ -436,7 +433,7 @@ bool MeshFixDuplicateFacets::Fixup() // get all facets std::set aFaceSet; - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) { std::pair::iterator, bool> pI = aFaceSet.insert(it); if (!pI.second) { aRemoveFaces.push_back(uIndex); @@ -460,7 +457,7 @@ bool MeshEvalInternalFacets::Evaluate() // get all facets std::set aFaceSet; MeshFacetArray::_TConstIterator first = rFaces.begin(); - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) { std::pair::iterator, bool> pI = aFaceSet.insert(it); if (!pI.second) { // collect both elements @@ -935,7 +932,7 @@ bool MeshEvalFoldsOnSurface::Evaluate() this->indices.clear(); const MeshFacetArray& rFAry = _rclMesh.GetFacets(); unsigned long ct = 0; - for (MeshFacetArray::const_iterator it = rFAry.begin(); it != rFAry.end(); ++it, ct++) { + for (auto it = rFAry.begin(); it != rFAry.end(); ++it, ct++) { for (int i = 0; i < 3; i++) { FacetIndex n1 = it->_aulNeighbours[i]; FacetIndex n2 = it->_aulNeighbours[(i + 1) % 3]; @@ -943,8 +940,8 @@ bool MeshEvalFoldsOnSurface::Evaluate() if (n1 != FACET_INDEX_MAX && n2 != FACET_INDEX_MAX) { Base::Vector3f v2 = _rclMesh.GetFacet(n1).GetNormal(); Base::Vector3f v3 = _rclMesh.GetFacet(n2).GetNormal(); - if (v2 * v3 > 0.0f) { - if (v1 * v2 < -0.1f && v1 * v3 < -0.1f) { + if (v2 * v3 > 0.0F) { + if (v1 * v2 < -0.1F && v1 * v3 < -0.1F) { indices.push_back(n1); indices.push_back(n2); indices.push_back(ct); @@ -974,14 +971,14 @@ bool MeshEvalFoldsOnBoundary::Evaluate() // the angle to the neighbour is more than 60 degree this->indices.clear(); const MeshFacetArray& rFacAry = _rclMesh.GetFacets(); - for (MeshFacetArray::_TConstIterator it = rFacAry.begin(); it != rFacAry.end(); ++it) { + for (auto it = rFacAry.begin(); it != rFacAry.end(); ++it) { if (it->CountOpenEdges() == 2) { for (FacetIndex nbIndex : it->_aulNeighbours) { if (nbIndex != FACET_INDEX_MAX) { MeshGeomFacet f1 = _rclMesh.GetFacet(*it); MeshGeomFacet f2 = _rclMesh.GetFacet(nbIndex); float cos_angle = f1.GetNormal() * f2.GetNormal(); - if (cos_angle <= 0.5f) { // ~ 60 degree + if (cos_angle <= 0.5F) { // ~ 60 degree indices.push_back(it - rFacAry.begin()); } } @@ -1028,7 +1025,7 @@ bool MeshEvalFoldOversOnSurface::Evaluate() && f_it->HasSameOrientation(f_beg[index2])) { n1 = _rclMesh.GetFacet(index1).GetNormal(); n2 = _rclMesh.GetFacet(index2).GetNormal(); - if (n1 * n2 < -0.5f) { // angle > 120 deg + if (n1 * n2 < -0.5F) { // angle > 120 deg this->indices.push_back(f_it - f_beg); break; } @@ -1091,7 +1088,7 @@ std::vector MeshEvalRangeFacet::GetIndices() const FacetIndex ulCtFacets = rFaces.size(); FacetIndex ind = 0; - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { for (FacetIndex nbIndex : it->_aulNeighbours) { if ((nbIndex >= ulCtFacets) && (nbIndex < FACET_INDEX_MAX)) { aInds.push_back(ind); @@ -1137,7 +1134,7 @@ std::vector MeshEvalRangePoint::GetIndices() const PointIndex ulCtPoints = _rclMesh.CountPoints(); PointIndex ind = 0; - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { if (std::find_if(it->_aulPoints, it->_aulPoints + 3, [ulCtPoints](PointIndex i) { @@ -1195,7 +1192,7 @@ std::vector MeshEvalCorruptedFacets::GetIndices() const const MeshFacetArray& rFaces = _rclMesh.GetFacets(); FacetIndex ind = 0; - for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { + for (auto it = rFaces.begin(); it != rFaces.end(); ++it, ind++) { if (it->IsDegenerated()) { aInds.push_back(ind); } @@ -1240,7 +1237,7 @@ bool MeshEvalPointOnEdge::Evaluate() edge._aclPoints[1] = points[facet._aulPoints[(i + 1) % 3]]; if (edge.GetBoundBox().IsInBox(points[idx])) { - if (edge.IsPointOf(points[idx], 0.001f)) { + if (edge.IsPointOf(points[idx], 0.001F)) { return true; } } diff --git a/src/Mod/Mesh/App/Core/Degeneration.h b/src/Mod/Mesh/App/Core/Degeneration.h index 6477002c98d9..116fc5c4f000 100644 --- a/src/Mod/Mesh/App/Core/Degeneration.h +++ b/src/Mod/Mesh/App/Core/Degeneration.h @@ -328,9 +328,9 @@ class MeshExport MeshRemoveNeedles: public MeshValidation * It defines the amount of perimeter of a triangle for which the shortest * edge is considered for removal. */ - explicit MeshRemoveNeedles(MeshKernel& rclM, float fMinEdgeLen = 0.05f) + explicit MeshRemoveNeedles(MeshKernel& rclM, float fMinEdgeLen = 0.05F) : MeshValidation(rclM) - , fMinEdgeLength(std::min(fMinEdgeLen, 0.25f)) + , fMinEdgeLength(std::min(fMinEdgeLen, 0.25F)) {} /** * Removes all facets with an edge smaller than \a fMinEdgeLength without leaving holes or gaps @@ -359,8 +359,8 @@ class MeshExport MeshFixCaps: public MeshValidation * Construction. The \arg fFactor must be in the range of 0.0 and 0.5. */ explicit MeshFixCaps(MeshKernel& rclM, - float fMaxAng = 2.61f, - float fFactor = 0.25f) // ~150 degree + float fMaxAng = 2.61F, + float fFactor = 0.25F) // ~150 degree : MeshValidation(rclM) , fMaxAngle(fMaxAng) , fSplitFactor(fFactor) diff --git a/src/Mod/Mesh/App/Core/Elements.cpp b/src/Mod/Mesh/App/Core/Elements.cpp index 068801c94f99..5d365251db05 100644 --- a/src/Mod/Mesh/App/Core/Elements.cpp +++ b/src/Mod/Mesh/App/Core/Elements.cpp @@ -48,9 +48,8 @@ PointIndex MeshPointArray::Get(const MeshPoint& rclPoint) if (clIter != end()) { return clIter - begin(); } - else { - return POINT_INDEX_MAX; - } + + return POINT_INDEX_MAX; } PointIndex MeshPointArray::GetOrAddIndex(const MeshPoint& rclPoint) @@ -61,21 +60,20 @@ PointIndex MeshPointArray::GetOrAddIndex(const MeshPoint& rclPoint) push_back(rclPoint); return static_cast(size() - 1); } - else { - return ulIndex; - } + + return ulIndex; } void MeshPointArray::SetFlag(MeshPoint::TFlagType tF) const { - for (MeshPointArray::_TConstIterator i = begin(); i < end(); ++i) { + for (auto i = begin(); i < end(); ++i) { i->SetFlag(tF); } } void MeshPointArray::ResetFlag(MeshPoint::TFlagType tF) const { - for (MeshPointArray::_TConstIterator i = begin(); i < end(); ++i) { + for (auto i = begin(); i < end(); ++i) { i->ResetFlag(tF); } } @@ -150,14 +148,14 @@ void MeshFacetArray::DecrementIndices(PointIndex ulIndex) void MeshFacetArray::SetFlag(MeshFacet::TFlagType tF) const { - for (MeshFacetArray::_TConstIterator i = begin(); i < end(); ++i) { + for (auto i = begin(); i < end(); ++i) { i->SetFlag(tF); } } void MeshFacetArray::ResetFlag(MeshFacet::TFlagType tF) const { - for (MeshFacetArray::_TConstIterator i = begin(); i < end(); ++i) { + for (auto i = begin(); i < end(); ++i) { i->ResetFlag(tF); } } @@ -202,11 +200,7 @@ bool MeshGeomEdge::ContainedByOrIntersectBoundingBox(const Base::BoundBox3f& rcl } // "real" test for cut - if (IntersectBoundingBox(rclBB)) { - return true; - } - - return false; + return (IntersectBoundingBox(rclBB)); } Base::BoundBox3f MeshGeomEdge::GetBoundBox() const @@ -225,18 +219,18 @@ bool MeshGeomEdge::IntersectBoundingBox(const Base::BoundBox3f& rclBB) const Vector3 n = B - A; float len = n.Length(); n.Normalize(); - Vector3 p = 0.5f * (A + B); + Vector3 p = 0.5F * (A + B); - Segment3 akSeg(p, n, 0.5f * len); + Segment3 akSeg(p, n, 0.5F * len); Base::Vector3f clCenter = rclBB.GetCenter(); Vector3 center(clCenter.x, clCenter.y, clCenter.z); - Vector3 axis0(1.0f, 0.0f, 0.0f); - Vector3 axis1(0.0f, 1.0f, 0.0f); - Vector3 axis2(0.0f, 0.0f, 1.0f); - float extent0 = 0.5f * rclBB.LengthX(); - float extent1 = 0.5f * rclBB.LengthY(); - float extent2 = 0.5f * rclBB.LengthZ(); + Vector3 axis0(1.0F, 0.0F, 0.0F); + Vector3 axis1(0.0F, 1.0F, 0.0F); + Vector3 axis2(0.0F, 0.0F, 1.0F); + float extent0 = 0.5F * rclBB.LengthX(); + float extent1 = 0.5F * rclBB.LengthY(); + float extent2 = 0.5F * rclBB.LengthZ(); Box3 kBox(center, axis0, axis1, axis2, extent0, extent1, extent2); @@ -248,7 +242,7 @@ bool MeshGeomEdge::IntersectWithLine(const Base::Vector3f& rclPt, const Base::Vector3f& rclDir, Base::Vector3f& rclRes) const { - const float eps = 1e-06f; + const float eps = 1e-06F; Base::Vector3f n = _aclPoints[1] - _aclPoints[0]; // check angle between edge and the line direction, FLOAT_MAX is @@ -309,7 +303,7 @@ bool MeshGeomEdge::IsCollinear(const MeshGeomEdge& edge) const bool MeshGeomEdge::IntersectWithEdge(const MeshGeomEdge& edge, Base::Vector3f& res) const { - const float eps = 1e-06f; + const float eps = 1e-06F; Base::Vector3f p(_aclPoints[0]); Base::Vector3f r(_aclPoints[1] - _aclPoints[0]); Base::Vector3f q(edge._aclPoints[0]); @@ -332,17 +326,16 @@ bool MeshGeomEdge::IntersectWithEdge(const MeshGeomEdge& edge, Base::Vector3f& r return false; } - else { - // Parallel - return false; - } + + // Parallel + return false; } else { // Get the distance of q to the plane defined by p and n float distance = q.DistanceToPlane(p, n); // lines are warped - if (fabs(distance) > eps) { + if (std::fabs(distance) > eps) { return false; } @@ -350,7 +343,7 @@ bool MeshGeomEdge::IntersectWithEdge(const MeshGeomEdge& edge, Base::Vector3f& r float u = d.Cross(r).Dot(n) / n.Sqr(); auto is_in_range = [](float v) { - return v >= 0.0f && v <= 1.0f; + return v >= 0.0F && v <= 1.0F; }; if (is_in_range(t) && is_in_range(u)) { @@ -370,7 +363,7 @@ bool MeshGeomEdge::IntersectWithPlane(const Base::Vector3f& rclPt, float dist2 = _aclPoints[1].DistanceToPlane(rclPt, rclDir); // either both points are below or above the plane - if (dist1 * dist2 >= 0.0f) { + if (dist1 * dist2 >= 0.0F) { return false; } @@ -396,7 +389,7 @@ void MeshGeomEdge::ClosestPointsToLine(const Base::Vector3f& linePt, Base::Vector3f& rclPnt1, Base::Vector3f& rclPnt2) const { - const float eps = 1e-06f; + const float eps = 1e-06F; Base::Vector3f edgeDir = _aclPoints[1] - _aclPoints[0]; // check angle between edge and the line direction, FLOAT_MAX is @@ -437,8 +430,8 @@ void MeshGeomEdge::ClosestPointsToLine(const Base::Vector3f& linePt, bool MeshGeomEdge::IsPointOf(const Base::Vector3f& rclPoint, float fDistance) const { float len2 = Base::DistanceP2(_aclPoints[0], _aclPoints[1]); - if (len2 == 0.0f) { - return _aclPoints[0].IsEqual(rclPoint, 0.0f); + if (len2 == 0.0F) { + return _aclPoints[0].IsEqual(rclPoint, 0.0F); } Base::Vector3f p2p1 = _aclPoints[1] - _aclPoints[0]; @@ -446,7 +439,7 @@ bool MeshGeomEdge::IsPointOf(const Base::Vector3f& rclPoint, float fDistance) co float dot = pXp1 * p2p1; float t = dot / len2; - if (t < 0.0f || t > 1.0f) { + if (t < 0.0F || t > 1.0F) { return false; } @@ -460,7 +453,7 @@ bool MeshGeomEdge::IsProjectionPointOf(const Base::Vector3f& point) const Base::Vector3f fromStartToPoint = point - _aclPoints[0]; Base::Vector3f fromPointToEnd = _aclPoints[1] - point; float dot = fromStartToPoint * fromPointToEnd; - return dot >= 0.0f; + return dot >= 0.0F; } // ----------------------------------------------------------------- @@ -503,7 +496,7 @@ bool MeshGeomFacet::IsPointOf(const Base::Vector3f& rclPoint, float fDistance) c // Edge P0 --> P1 clEdge = clP1 - clP0; fLP = clProjPt.DistanceToLine(clP0, clEdge); - if (fLP > 0.0f) { + if (fLP > 0.0F) { fLE = clP2.DistanceToLine(clP0, clEdge); if (fLP <= fLE) { if (clProjPt.DistanceToLine(clP2, clEdge) > fLE) { @@ -518,7 +511,7 @@ bool MeshGeomFacet::IsPointOf(const Base::Vector3f& rclPoint, float fDistance) c // Edge P0 --> P2 clEdge = clP2 - clP0; fLP = clProjPt.DistanceToLine(clP0, clEdge); - if (fLP > 0.0f) { + if (fLP > 0.0F) { fLE = clP1.DistanceToLine(clP0, clEdge); if (fLP <= fLE) { if (clProjPt.DistanceToLine(clP1, clEdge) > fLE) { @@ -533,7 +526,7 @@ bool MeshGeomFacet::IsPointOf(const Base::Vector3f& rclPoint, float fDistance) c // Edge P1 --> P2 clEdge = clP2 - clP1; fLP = clProjPt.DistanceToLine(clP1, clEdge); - if (fLP > 0.0f) { + if (fLP > 0.0F) { fLE = clP0.DistanceToLine(clP1, clEdge); if (fLP <= fLE) { if (clProjPt.DistanceToLine(clP0, clEdge) > fLE) { @@ -570,15 +563,15 @@ bool MeshGeomFacet::IsPointOfFace(const Base::Vector3f& rclP, float fDistance) c return false; } - if (n * n1 <= 0.0f) { + if (n * n1 <= 0.0F) { return false; } - if (n * n2 <= 0.0f) { + if (n * n2 <= 0.0F) { return false; } - if (n * n3 <= 0.0f) { + if (n * n3 <= 0.0F) { return false; } @@ -596,7 +589,7 @@ bool MeshGeomFacet::Weights(const Base::Vector3f& rclP, float& w0, float& w1, fl w1 = fAreaPCA / fAreaABC; w2 = fAreaPAB / fAreaABC; - return fabs(w0 + w1 + w2 - 1.0f) < 0.001f; + return std::fabs(w0 + w1 + w2 - 1.0F) < 0.001F; } void MeshGeomFacet::ProjectPointToPlane(const Base::Vector3f& rclPoint, @@ -627,7 +620,7 @@ void MeshGeomFacet::Enlarge(float fDist) clV = _aclPoints[ulP3] - _aclPoints[ulP1]; clM = -(clU + clV); fA = clM.GetAngle(-clU); - fD = fDist / float(sin(fA)); + fD = fDist / float(std::sin(fA)); clM.Normalize(); clM.Scale(fD, fD, fD); clPNew[ulP1] = _aclPoints[ulP1] + clM; @@ -720,9 +713,9 @@ bool MeshGeomFacet::IntersectBoundingBox(const Base::BoundBox3f& rclBB) const float len2 = (v2 - v0).Length(); // Build up the line segments - Vector3 p0(0.5f * (v0.x + v1.x), 0.5f * (v0.y + v1.y), 0.5f * (v0.z + v1.z)); - Vector3 p1(0.5f * (v1.x + v2.x), 0.5f * (v1.y + v2.y), 0.5f * (v1.z + v2.z)); - Vector3 p2(0.5f * (v2.x + v0.x), 0.5f * (v2.y + v0.y), 0.5f * (v2.z + v0.z)); + Vector3 p0(0.5F * (v0.x + v1.x), 0.5F * (v0.y + v1.y), 0.5F * (v0.z + v1.z)); + Vector3 p1(0.5F * (v1.x + v2.x), 0.5F * (v1.y + v2.y), 0.5F * (v1.z + v2.z)); + Vector3 p2(0.5F * (v2.x + v0.x), 0.5F * (v2.y + v0.y), 0.5F * (v2.z + v0.z)); Vector3 d0(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z); d0.Normalize(); @@ -731,19 +724,19 @@ bool MeshGeomFacet::IntersectBoundingBox(const Base::BoundBox3f& rclBB) const Vector3 d2(v0.x - v2.x, v0.y - v2.y, v0.z - v2.z); d2.Normalize(); - Segment3 akSeg0(p0, d0, len0 / 2.0f); - Segment3 akSeg1(p1, d1, len1 / 2.0f); - Segment3 akSeg2(p2, d2, len2 / 2.0f); + Segment3 akSeg0(p0, d0, len0 / 2.0F); + Segment3 akSeg1(p1, d1, len1 / 2.0F); + Segment3 akSeg2(p2, d2, len2 / 2.0F); // Build up the box Base::Vector3f clCenter = rclBB.GetCenter(); Vector3 center(clCenter.x, clCenter.y, clCenter.z); - Vector3 axis0(1.0f, 0.0f, 0.0f); - Vector3 axis1(0.0f, 1.0f, 0.0f); - Vector3 axis2(0.0f, 0.0f, 1.0f); - float extent0 = 0.5f * rclBB.LengthX(); - float extent1 = 0.5f * rclBB.LengthY(); - float extent2 = 0.5f * rclBB.LengthZ(); + Vector3 axis0(1.0F, 0.0F, 0.0F); + Vector3 axis1(0.0F, 1.0F, 0.0F); + Vector3 axis2(0.0F, 0.0F, 1.0F); + float extent0 = 0.5F * rclBB.LengthX(); + float extent1 = 0.5F * rclBB.LengthY(); + float extent2 = 0.5F * rclBB.LengthZ(); Box3 akBox(center, axis0, axis1, axis2, extent0, extent1, extent2); @@ -757,12 +750,7 @@ bool MeshGeomFacet::IntersectBoundingBox(const Base::BoundBox3f& rclBB) const return true; } IntrSegment3Box3 akSec2(akSeg2, akBox, false); - if (akSec2.Test()) { - return true; - } - - // no intersection - return false; + return (akSec2.Test()); } bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, @@ -770,7 +758,7 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, Base::Vector3f& rclP1, Base::Vector3f& rclP2) const { - const float eps = 1e-06f; + const float eps = 1e-06F; // the triangle's corner points const Base::Vector3f& v0 = _aclPoints[0]; @@ -803,9 +791,9 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, float len2 = (v2 - v0).Length(); // Build up the line segments - Vector3 p0(0.5f * (v0.x + v1.x), 0.5f * (v0.y + v1.y), 0.5f * (v0.z + v1.z)); - Vector3 p1(0.5f * (v1.x + v2.x), 0.5f * (v1.y + v2.y), 0.5f * (v1.z + v2.z)); - Vector3 p2(0.5f * (v2.x + v0.x), 0.5f * (v2.y + v0.y), 0.5f * (v2.z + v0.z)); + Vector3 p0(0.5F * (v0.x + v1.x), 0.5F * (v0.y + v1.y), 0.5F * (v0.z + v1.z)); + Vector3 p1(0.5F * (v1.x + v2.x), 0.5F * (v1.y + v2.y), 0.5F * (v1.z + v2.z)); + Vector3 p2(0.5F * (v2.x + v0.x), 0.5F * (v2.y + v0.y), 0.5F * (v2.z + v0.z)); Vector3 d0(v1.x - v0.x, v1.y - v0.y, v1.z - v0.z); d0.Normalize(); @@ -814,9 +802,9 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, Vector3 d2(v0.x - v2.x, v0.y - v2.y, v0.z - v2.z); d2.Normalize(); - Segment3 akSeg0(p0, d0, len0 / 2.0f); - Segment3 akSeg1(p1, d1, len1 / 2.0f); - Segment3 akSeg2(p2, d2, len2 / 2.0f); + Segment3 akSeg0(p0, d0, len0 / 2.0F); + Segment3 akSeg1(p1, d1, len1 / 2.0F); + Segment3 akSeg2(p2, d2, len2 / 2.0F); // Build up the plane Vector3 p(rclBase.x, rclBase.y, rclBase.z); @@ -840,7 +828,7 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, } return true; } - else if (dist1 < eps) { + if (dist1 < eps) { rclP1 = v1; rclP2 = v1; if (test2.Find()) { @@ -849,7 +837,7 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, } return true; } - else if (dist2 < eps) { + if (dist2 < eps) { rclP1 = v2; rclP2 = v2; if (test0.Find()) { @@ -869,7 +857,7 @@ bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, rclP2.Set(intr[0], intr[1], intr[2]); return true; } - else if (test2.Find()) { + if (test2.Find()) { intr = p2 + test2.GetSegmentT() * d2; rclP2.Set(intr[0], intr[1], intr[2]); return true; @@ -894,7 +882,7 @@ bool MeshGeomFacet::Foraminate(const Base::Vector3f& P, Base::Vector3f& I, float fMaxAngle) const { - const float eps = 1e-06f; + const float eps = 1e-06F; Base::Vector3f n = this->GetNormal(); // check angle between facet normal and the line direction, FLOAT_MAX is @@ -925,13 +913,13 @@ bool MeshGeomFacet::Foraminate(const Base::Vector3f& P, float vv = v * v; float wu = w * u; float wv = w * v; - float det = float(fabs((uu * vv) - (uv * uv))); + float det = float(std::fabs((uu * vv) - (uv * uv))); float s = (vv * wu) - (uv * wv); float t = (uu * wv) - (uv * wu); // is the intersection point inside the triangle? - if ((s >= 0.0f) && (t >= 0.0f) && ((s + t) <= det)) { + if ((s >= 0.0F) && (t >= 0.0F) && ((s + t) <= det)) { I = w + this->_aclPoints[0]; return true; } @@ -944,7 +932,7 @@ bool MeshGeomFacet::IntersectPlaneWithLine(const Base::Vector3f& rclPt, Base::Vector3f& rclRes) const { // calculate the intersection of the straight line <-> plane - if (fabs(rclDir * GetNormal()) < 1e-3f) { + if (fabs(rclDir * GetNormal()) < 1e-3F) { return false; // line and plane are parallel } @@ -962,7 +950,7 @@ bool MeshGeomFacet::IntersectWithLine(const Base::Vector3f& rclPt, return false; // line and plane are parallel } // Check if the intersection point is inside the facet - return IsPointOfFace(rclRes, 1e-03f); + return IsPointOfFace(rclRes, 1e-03F); } float MeshGeomFacet::DistanceToLineSegment(const Base::Vector3f& rclP1, @@ -975,9 +963,9 @@ float MeshGeomFacet::DistanceToLineSegment(const Base::Vector3f& rclP1, Vector3 n = B - A; float len = n.Length(); n.Normalize(); - Vector3 p = 0.5f * (A + B); + Vector3 p = 0.5F * (A + B); - Segment3 akSeg(p, n, 0.5f * len); + Segment3 akSeg(p, n, 0.5F * len); // triangle Vector3 akF0(_aclPoints[0].x, _aclPoints[0].y, _aclPoints[0].z); @@ -1042,8 +1030,8 @@ void MeshGeomFacet::SubSample(float fStep, std::vector& rclPoint clVecHNorm.Normalize(); float bx = fLenAB; - float cy = float(sin(clVecAB.GetAngle(clVecAC)) * fLenAC); - float cx = float(sqrt(fabs(fLenAC * fLenAC - cy * cy))); + float cy = float(std::sin(clVecAB.GetAngle(clVecAC)) * fLenAC); + float cx = float(std::sqrt(std::fabs(fLenAC * fLenAC - cy * cy))); float fDetABC = bx * cy; @@ -1055,7 +1043,7 @@ void MeshGeomFacet::SubSample(float fStep, std::vector& rclPoint float v = (px * cy - cx * py) / fDetABC; float w = (bx * py) / fDetABC; - if ((u >= 0.0f) && (v >= 0.0f) && (w >= 0.0f) && ((u + v) < 1.0f)) { + if ((u >= 0.0F) && (v >= 0.0F) && (w >= 0.0F) && ((u + v) < 1.0F)) { // rclPoints.push_back(CBase::Vector3f(u*A + v*B + w*C)); Base::Vector3f clV = A + (px * clVecABNorm) + (py * clVecHNorm); clPoints.push_back(clV); @@ -1076,10 +1064,10 @@ void MeshGeomFacet::SubSample(float fStep, std::vector& rclPoint bool MeshGeomFacet::IsCoplanar(const MeshGeomFacet& facet) const { - const float eps = 1e-06f; - const float unit = 0.9995f; - float mult = fabs(this->GetNormal() * facet.GetNormal()); - float dist = fabs(DistancePlaneToPoint(facet._aclPoints[0])); + const float eps = 1e-06F; + const float unit = 0.9995F; + float mult = std::fabs(this->GetNormal() * facet.GetNormal()); + float dist = std::fabs(DistancePlaneToPoint(facet._aclPoints[0])); return (mult >= unit) && (dist <= eps); } @@ -1139,7 +1127,7 @@ int MeshGeomFacet::IntersectWithFacet(const MeshGeomFacet& rclFacet, rclPt1 = intersections[1]; return 2; } - else if (intersections.size() == 1) { + if (intersections.size() == 1) { rclPt0 = intersections[0]; rclPt1 = intersections[0]; return 1; @@ -1186,13 +1174,13 @@ int MeshGeomFacet::IntersectWithFacet(const MeshGeomFacet& rclFacet, // model. So, a plausibility check is to verify that the intersection points // are inside the bounding boxes of both triangles. Base::BoundBox3f box1 = this->GetBoundBox(); - box1.Enlarge(0.001f); + box1.Enlarge(0.001F); if (!box1.IsInBox(rclPt0) || !box1.IsInBox(rclPt1)) { return 0; } Base::BoundBox3f box2 = rclFacet.GetBoundBox(); - box2.Enlarge(0.001f); + box2.Enlarge(0.001F); if (!box2.IsInBox(rclPt0) || !box2.IsInBox(rclPt1)) { return 0; } @@ -1202,7 +1190,7 @@ int MeshGeomFacet::IntersectWithFacet(const MeshGeomFacet& rclFacet, // behaviour occurs if the triangles are nearly co-planar float mult = fabs(this->GetNormal() * rclFacet.GetNormal()); if (rclPt0 == rclPt1) { - if (mult < 0.995f) { // not co-planar, thus no test needed + if (mult < 0.995F) { // not co-planar, thus no test needed return 1; } if (this->IsPointOf(rclPt0) && rclFacet.IsPointOf(rclPt0)) { @@ -1210,7 +1198,7 @@ int MeshGeomFacet::IntersectWithFacet(const MeshGeomFacet& rclFacet, } } else { - if (mult < 0.995f) { // not co-planar, thus no test needed + if (mult < 0.995F) { // not co-planar, thus no test needed return 2; } if (this->IsPointOf(rclPt0) && rclFacet.IsPointOf(rclPt0) && this->IsPointOf(rclPt1) @@ -1270,7 +1258,7 @@ float MeshGeomFacet::CenterOfInscribedCircle(Base::Vector3f& rclCenter) const // radius of the circle float fRadius = Area(); - fRadius *= 2.0f / (a + b + c); + fRadius *= 2.0F / (a + b + c); // center of the circle float w = a + b + c; @@ -1329,10 +1317,10 @@ unsigned short MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt) co Base::Vector3f clDir = rcP2 - rcP1; float fLen = Base::Distance(rcP2, rcP1); float t = ((rclPt - rcP1) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD1 = Base::Distance(rclPt, rcP1); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD1 = Base::Distance(rclPt, rcP2); } else { @@ -1343,10 +1331,10 @@ unsigned short MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt) co clDir = rcP3 - rcP2; fLen = Base::Distance(rcP3, rcP2); t = ((rclPt - rcP2) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD2 = Base::Distance(rclPt, rcP2); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD2 = Base::Distance(rclPt, rcP3); } else { @@ -1357,10 +1345,10 @@ unsigned short MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt) co clDir = rcP1 - rcP3; fLen = Base::Distance(rcP1, rcP3); t = ((rclPt - rcP3) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD3 = Base::Distance(rclPt, rcP3); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD3 = Base::Distance(rclPt, rcP1); } else { @@ -1403,10 +1391,10 @@ void MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt, Base::Vector3f clDir = rcP2 - rcP1; float fLen = Base::Distance(rcP2, rcP1); float t = ((rclPt - rcP1) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD1 = Base::Distance(rclPt, rcP1); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD1 = Base::Distance(rclPt, rcP2); } else { @@ -1417,10 +1405,10 @@ void MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt, clDir = rcP3 - rcP2; fLen = Base::Distance(rcP3, rcP2); t = ((rclPt - rcP2) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD2 = Base::Distance(rclPt, rcP2); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD2 = Base::Distance(rclPt, rcP3); } else { @@ -1431,10 +1419,10 @@ void MeshGeomFacet::NearestEdgeToPoint(const Base::Vector3f& rclPt, clDir = rcP1 - rcP3; fLen = Base::Distance(rcP1, rcP3); t = ((rclPt - rcP3) * clDir) / (fLen * fLen); - if (t < 0.0f) { + if (t < 0.0F) { fD3 = Base::Distance(rclPt, rcP3); } - else if (t > 1.0f) { + else if (t > 1.0F) { fD3 = Base::Distance(rclPt, rcP1); } else { @@ -1500,12 +1488,12 @@ float MeshGeomFacet::VolumeOfPrism(const MeshGeomFacet& rclF1) const Base::Vector3f N2 = (P2 - P1) % (Q2 - P1); Base::Vector3f N3 = (Q2 - P1) % (Q1 - P1); - float fVol = 0.0f; + float fVol = 0.0F; fVol += float(fabs((Q3 - P1) * N1)); fVol += float(fabs((Q3 - P1) * N2)); fVol += float(fabs((Q3 - P1) * N3)); - fVol /= 6.0f; + fVol /= 6.0F; return fVol; ; @@ -1513,7 +1501,7 @@ float MeshGeomFacet::VolumeOfPrism(const MeshGeomFacet& rclF1) const float MeshGeomFacet::MaximumAngle() const { - float fMaxAngle = 0.0f; + float fMaxAngle = 0.0F; for (int i = 0; i < 3; i++) { Base::Vector3f dir1(_aclPoints[(i + 1) % 3] - _aclPoints[i]); @@ -1589,7 +1577,7 @@ float MeshGeomFacet::AspectRatio() const // squared area of the parallelogram spanned by d0 and d1 float a2 = (d0 % d1).Sqr(); - return float(sqrt((maxl2 * maxl2) / a2)); + return float(std::sqrt((maxl2 * maxl2) / a2)); } float MeshGeomFacet::AspectRatio2() const diff --git a/src/Mod/Mesh/App/Core/Elements.h b/src/Mod/Mesh/App/Core/Elements.h index 32994a3a5c71..a4602b1a6fc6 100644 --- a/src/Mod/Mesh/App/Core/Elements.h +++ b/src/Mod/Mesh/App/Core/Elements.h @@ -365,7 +365,7 @@ class MeshFacet * Returns the edge-number defined by the shared edge of both facets. If the facets don't * share a common edge USHRT_MAX is returned. */ - inline unsigned short Side(const MeshFacet& rcFace) const; + inline unsigned short Side(const MeshFacet& rFace) const; /** * Returns true if this facet shares the same three points as \a rcFace. * The orientation is not of interest in this case. @@ -463,7 +463,7 @@ class MeshExport MeshGeomFacet * must already exactly lie on the plane defined by the facet, which is not * checked. This method is very efficient. */ - bool IsPointOf(const Base::Vector3f& rclPoint) const; + bool IsPointOf(const Base::Vector3f& P) const; /** Checks whether the given point is inside the facet with tolerance \a fDistance. * This method does actually the same as IsPointOf() but this implementation * is done more effective through comparison of normals. @@ -596,9 +596,9 @@ class MeshExport MeshGeomFacet * additionally constraint that the angle between the direction of the line and the normal of * the plane must not exceed \a fMaxAngle. */ - bool Foraminate(const Base::Vector3f& rclPt, - const Base::Vector3f& rclDir, - Base::Vector3f& rclRes, + bool Foraminate(const Base::Vector3f& P, + const Base::Vector3f& dir, + Base::Vector3f& I, float fMaxAngle = Mathf::PI) const; /** Checks if the facet intersects with the plane defined by the base \a rclBase and the normal * \a rclNormal and returns true if two points are found, false otherwise. @@ -617,8 +617,8 @@ class MeshExport MeshGeomFacet * base \a rclBase and the direction \a rclNormal and returns the intersection point \a rclRes * if possible. */ - bool IntersectPlaneWithLine(const Base::Vector3f& rclBase, - const Base::Vector3f& rclNormal, + bool IntersectPlaneWithLine(const Base::Vector3f& rclPt, + const Base::Vector3f& rclDir, Base::Vector3f& rclRes) const; /** Calculates the volume of the prism defined by two facets. * \note The two facets must not intersect. @@ -877,13 +877,13 @@ inline bool MeshPoint::operator==(const Base::Vector3f& rclV) const inline bool MeshPoint::operator<(const MeshPoint& rclPt) const { - if (fabs(this->x - rclPt.x) >= MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(this->x - rclPt.x) >= MeshDefinitions::_fMinPointDistanceD1) { return this->x < rclPt.x; } - if (fabs(this->y - rclPt.y) >= MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(this->y - rclPt.y) >= MeshDefinitions::_fMinPointDistanceD1) { return this->y < rclPt.y; } - if (fabs(this->z - rclPt.z) >= MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(this->z - rclPt.z) >= MeshDefinitions::_fMinPointDistanceD1) { return this->z < rclPt.z; } return false; // points are considered to be equal @@ -912,7 +912,7 @@ inline Base::Vector3f MeshGeomFacet::GetNormal() const inline void MeshGeomFacet::SetNormal(const Base::Vector3f& rclNormal) { - if (rclNormal.Sqr() == 0.0f) { + if (rclNormal.Sqr() == 0.0F) { return; } _clNormal = rclNormal; @@ -923,20 +923,20 @@ inline void MeshGeomFacet::SetNormal(const Base::Vector3f& rclNormal) inline void MeshGeomFacet::ArrangeNormal(const Base::Vector3f& rclN) { // force internal normal to be computed if not done yet - if ((rclN * GetNormal()) < 0.0f) { + if ((rclN * GetNormal()) < 0.0F) { _clNormal = -_clNormal; } } inline Base::Vector3f MeshGeomFacet::GetGravityPoint() const { - return (1.0f / 3.0f) * (_aclPoints[0] + _aclPoints[1] + _aclPoints[2]); + return (1.0F / 3.0F) * (_aclPoints[0] + _aclPoints[1] + _aclPoints[2]); } inline void MeshGeomFacet::AdjustCirculationDirection() { Base::Vector3f clN = (_aclPoints[1] - _aclPoints[0]) % (_aclPoints[2] - _aclPoints[0]); - if ((clN * _clNormal) < 0.0f) { + if ((clN * _clNormal) < 0.0F) { std::swap(_aclPoints[1], _aclPoints[2]); } } @@ -948,7 +948,7 @@ inline Base::BoundBox3f MeshGeomFacet::GetBoundBox() const inline float MeshGeomFacet::Perimeter() const { - float perimeter = 0.0f; + float perimeter = 0.0F; perimeter += Base::Distance(_aclPoints[0], _aclPoints[1]); perimeter += Base::Distance(_aclPoints[1], _aclPoints[2]); perimeter += Base::Distance(_aclPoints[2], _aclPoints[0]); @@ -957,7 +957,7 @@ inline float MeshGeomFacet::Perimeter() const inline float MeshGeomFacet::Area() const { - return ((_aclPoints[1] - _aclPoints[0]) % (_aclPoints[2] - _aclPoints[0])).Length() / 2.0f; + return ((_aclPoints[1] - _aclPoints[0]) % (_aclPoints[2] - _aclPoints[0])).Length() / 2.0F; } inline bool MeshGeomFacet::ContainedByOrIntersectBoundingBox(const Base::BoundBox3f& rclBB) const @@ -980,19 +980,15 @@ inline bool MeshGeomFacet::ContainedByOrIntersectBoundingBox(const Base::BoundBo } // "real" test for cutting - if (IntersectBoundingBox(rclBB)) { - return true; - } - - return false; + return (IntersectBoundingBox(rclBB)); } inline bool MeshGeomFacet::IntersectWithPlane(const Base::Vector3f& rclBase, const Base::Vector3f& rclNormal) const { - bool bD0 = (_aclPoints[0].DistanceToPlane(rclBase, rclNormal) > 0.0f); - return !((bD0 == (_aclPoints[1].DistanceToPlane(rclBase, rclNormal) > 0.0f)) - && (bD0 == (_aclPoints[2].DistanceToPlane(rclBase, rclNormal) > 0.0f))); + bool bD0 = (_aclPoints[0].DistanceToPlane(rclBase, rclNormal) > 0.0F); + return !((bD0 == (_aclPoints[1].DistanceToPlane(rclBase, rclNormal) > 0.0F)) + && (bD0 == (_aclPoints[2].DistanceToPlane(rclBase, rclNormal) > 0.0F))); } inline MeshFacet::MeshFacet() // NOLINT @@ -1144,15 +1140,14 @@ inline unsigned short MeshFacet::Side(FacetIndex ulNIndex) const if (_aulNeighbours[0] == ulNIndex) { return 0; } - else if (_aulNeighbours[1] == ulNIndex) { + if (_aulNeighbours[1] == ulNIndex) { return 1; } - else if (_aulNeighbours[2] == ulNIndex) { + if (_aulNeighbours[2] == ulNIndex) { return 2; } - else { - return USHRT_MAX; - } + + return USHRT_MAX; } inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const @@ -1161,7 +1156,7 @@ inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const if (_aulPoints[1] == ulP1) { return 0; // Edge 0-1 ==> 0 } - else if (_aulPoints[2] == ulP1) { + if (_aulPoints[2] == ulP1) { return 2; // Edge 0-2 ==> 2 } } @@ -1169,7 +1164,7 @@ inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const if (_aulPoints[0] == ulP1) { return 0; // Edge 1-0 ==> 0 } - else if (_aulPoints[2] == ulP1) { + if (_aulPoints[2] == ulP1) { return 1; // Edge 1-2 ==> 1 } } @@ -1177,7 +1172,7 @@ inline unsigned short MeshFacet::Side(PointIndex ulP0, PointIndex ulP1) const if (_aulPoints[0] == ulP1) { return 2; // Edge 2-0 ==> 2 } - else if (_aulPoints[1] == ulP1) { + if (_aulPoints[1] == ulP1) { return 1; // Edge 2-1 ==> 1 } } @@ -1206,8 +1201,8 @@ inline bool MeshFacet::IsEqual(const MeshFacet& rcFace) const && this->_aulPoints[2] == rcFace._aulPoints[(i + 2) % 3]) { return true; } - else if (this->_aulPoints[1] == rcFace._aulPoints[(i + 2) % 3] - && this->_aulPoints[2] == rcFace._aulPoints[(i + 1) % 3]) { + if (this->_aulPoints[1] == rcFace._aulPoints[(i + 2) % 3] + && this->_aulPoints[2] == rcFace._aulPoints[(i + 1) % 3]) { return true; } } diff --git a/src/Mod/Mesh/App/Core/Evaluation.cpp b/src/Mod/Mesh/App/Core/Evaluation.cpp index 6b6c8820e6f3..2e5fd9954e5e 100644 --- a/src/Mod/Mesh/App/Core/Evaluation.cpp +++ b/src/Mod/Mesh/App/Core/Evaluation.cpp @@ -133,7 +133,7 @@ bool MeshEvalOrientation::Evaluate() const MeshFacetArray& rFAry = _rclMesh.GetFacets(); MeshFacetArray::_TConstIterator iBeg = rFAry.begin(); MeshFacetArray::_TConstIterator iEnd = rFAry.end(); - for (MeshFacetArray::_TConstIterator it = iBeg; it != iEnd; ++it) { + for (auto it = iBeg; it != iEnd; ++it) { for (int i = 0; i < 3; i++) { if (it->_aulNeighbours[i] != FACET_INDEX_MAX) { const MeshFacet& rclFacet = iBeg[it->_aulNeighbours[i]]; @@ -215,7 +215,7 @@ std::vector MeshEvalOrientation::GetIndices() const // In the currently visited component we have found less than 40% as correct // oriented and the rest as false oriented. So, we decide that it should be the other // way round and swap the indices of this component. - if (uComplement.size() < static_cast(0.4f * static_cast(ulVisited))) { + if (uComplement.size() < static_cast(0.4F * static_cast(ulVisited))) { uIndices.erase(uIndices.begin() + wrongFacets, uIndices.end()); uIndices.insert(uIndices.end(), uComplement.begin(), uComplement.end()); } @@ -318,13 +318,13 @@ struct Edge_Less if (x.p0 < y.p0) { return true; } - else if (x.p0 > y.p0) { + if (x.p0 > y.p0) { return false; } - else if (x.p1 < y.p1) { + if (x.p1 < y.p1) { return true; } - else if (x.p1 > y.p1) { + if (x.p1 > y.p1) { return false; } return false; @@ -629,14 +629,12 @@ bool MeshEvalSelfIntersection::Evaluate() MeshGeomFacet facet1, facet2; Base::Vector3f pt1, pt2; - for (std::vector::iterator it = aulGridElements.begin(); - it != aulGridElements.end(); - ++it) { + for (auto it = aulGridElements.begin(); it != aulGridElements.end(); ++it) { const Base::BoundBox3f& box1 = boxes[*it]; cMFI.Set(*it); facet1 = *cMFI; const MeshFacet& rface1 = rFaces[*it]; - for (std::vector::iterator jt = it; jt != aulGridElements.end(); ++jt) { + for (auto jt = it; jt != aulGridElements.end(); ++jt) { if (jt == it) { // the identical facet continue; } @@ -735,14 +733,12 @@ void MeshEvalSelfIntersection::GetIntersections( MeshGeomFacet facet1, facet2; Base::Vector3f pt1, pt2; - for (std::vector::iterator it = aulGridElements.begin(); - it != aulGridElements.end(); - ++it) { + for (auto it = aulGridElements.begin(); it != aulGridElements.end(); ++it) { const Base::BoundBox3f& box1 = boxes[*it]; cMFI.Set(*it); facet1 = *cMFI; const MeshFacet& rface1 = rFaces[*it]; - for (std::vector::iterator jt = it; jt != aulGridElements.end(); ++jt) { + for (auto jt = it; jt != aulGridElements.end(); ++jt) { if (jt == it) { // the identical facet continue; } @@ -977,9 +973,8 @@ void MeshKernel::RebuildNeighbours(FacetIndex index) edges.reserve(3 * (this->_aclFacetArray.size() - index)); // build up an array of edges - MeshFacetArray::_TConstIterator pI; - MeshFacetArray::_TConstIterator pB = this->_aclFacetArray.begin(); - for (pI = pB + index; pI != this->_aclFacetArray.end(); ++pI) { + auto pB = this->_aclFacetArray.begin(); + for (auto pI = pB + index; pI != this->_aclFacetArray.end(); ++pI) { for (int i = 0; i < 3; i++) { Edge_Index item {}; item.p0 = std::min(pI->_aulPoints[i], pI->_aulPoints[(i + 1) % 3]); @@ -1054,9 +1049,9 @@ void MeshKernel::RebuildNeighbours() MeshEigensystem::MeshEigensystem(const MeshKernel& rclB) : MeshEvaluation(rclB) - , _cU(1.0f, 0.0f, 0.0f) - , _cV(0.0f, 1.0f, 0.0f) - , _cW(0.0f, 0.0f, 1.0f) + , _cU(1.0F, 0.0F, 0.0F) + , _cV(0.0F, 1.0F, 0.0F) + , _cW(0.0F, 0.0F, 1.0F) { // use the values of world coordinates as default Base::BoundBox3f box = _rclMesh.GetBoundBox(); @@ -1108,7 +1103,7 @@ bool MeshEigensystem::Evaluate() { CalculateLocalSystem(); - float xmin = 0.0f, xmax = 0.0f, ymin = 0.0f, ymax = 0.0f, zmin = 0.0f, zmax = 0.0f; + float xmin = 0.0F, xmax = 0.0F, ymin = 0.0F, ymax = 0.0F, zmin = 0.0F, zmax = 0.0F; Base::Vector3f clVect, clProj; float fH {}; @@ -1122,7 +1117,7 @@ bool MeshEigensystem::Evaluate() fH = clVect.Length(); // point vectors in the same direction ? - if ((clVect * _cU) < 0.0f) { + if ((clVect * _cU) < 0.0F) { fH = -fH; } @@ -1136,7 +1131,7 @@ bool MeshEigensystem::Evaluate() fH = clVect.Length(); // point vectors in the same direction ? - if ((clVect * _cV) < 0.0f) { + if ((clVect * _cV) < 0.0F) { fH = -fH; } @@ -1150,7 +1145,7 @@ bool MeshEigensystem::Evaluate() fH = clVect.Length(); // point vectors in the same direction ? - if ((clVect * _cW) < 0.0f) { + if ((clVect * _cW) < 0.0F) { fH = -fH; } @@ -1203,17 +1198,17 @@ void MeshEigensystem::CalculateLocalSystem() } // avoid ambiguities concerning directions - if (fSumU < 0.0f) { - _cU *= -1.0f; + if (fSumU < 0.0F) { + _cU *= -1.0F; } - if (fSumV < 0.0f) { - _cV *= -1.0f; + if (fSumV < 0.0F) { + _cV *= -1.0F; } - if (fSumW < 0.0f) { - _cW *= -1.0f; + if (fSumW < 0.0F) { + _cW *= -1.0F; } - if ((_cU % _cV) * _cW < 0.0f) { + if ((_cU % _cV) * _cW < 0.0F) { _cW = -_cW; // make a right-handed system } } diff --git a/src/Mod/Mesh/App/Core/Grid.cpp b/src/Mod/Mesh/App/Core/Grid.cpp index af6532609c14..603650ed7b7f 100644 --- a/src/Mod/Mesh/App/Core/Grid.cpp +++ b/src/Mod/Mesh/App/Core/Grid.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include +#include #endif #include "Algorithm.h" @@ -349,7 +350,7 @@ void MeshGrid::CalculateGridLength(int iCtGridPerAxis) fVolumenGrid = fVolumen / static_cast(iMaxGrids); } - float fLengthGrid = pow(fVolumenGrid, 1.0F / 3.0F); + float fLengthGrid = std::pow(fVolumenGrid, 1.0F / 3.0F); _ulCtGridsX = std::max(static_cast(fLenghtX / fLengthGrid), 1UL); _ulCtGridsY = std::max(static_cast(fLenghtY / fLengthGrid), 1UL); @@ -367,7 +368,7 @@ void MeshGrid::CalculateGridLength(int iCtGridPerAxis) fAreaGrid = fArea / static_cast(iMaxGrids); } - auto fLengthGrid = float(sqrt(fAreaGrid)); + auto fLengthGrid = float(std::sqrt(fAreaGrid)); _ulCtGridsY = std::max(static_cast(fLenghtY / fLengthGrid), 1); @@ -385,7 +386,7 @@ void MeshGrid::CalculateGridLength(int iCtGridPerAxis) fAreaGrid = fArea / static_cast(iMaxGrids); } - auto fLengthGrid = float(sqrt(fAreaGrid)); + auto fLengthGrid = float(std::sqrt(fAreaGrid)); _ulCtGridsX = std::max(static_cast(fLenghtX / fLengthGrid), 1); @@ -408,7 +409,7 @@ void MeshGrid::CalculateGridLength(int iCtGridPerAxis) fAreaGrid = fArea / static_cast(iMaxGrids); } - auto fLengthGrid = float(sqrt(fAreaGrid)); + auto fLengthGrid = float(std::sqrt(fAreaGrid)); _ulCtGridsX = std::max(static_cast(fLenghtX / fLengthGrid), 1); diff --git a/src/Mod/Mesh/App/Core/Grid.h b/src/Mod/Mesh/App/Core/Grid.h index cb1a8c6d8d96..834ba65b8b7f 100644 --- a/src/Mod/Mesh/App/Core/Grid.h +++ b/src/Mod/Mesh/App/Core/Grid.h @@ -42,7 +42,7 @@ class MeshKernel; class MeshGeomFacet; class MeshGrid; -#define MESHGRID_BBOX_EXTENSION 10.0f +static constexpr float MESHGRID_BBOX_EXTENSION = 10.0F; /** * The MeshGrid allows to divide a global mesh object into smaller regions diff --git a/src/Mod/Mesh/App/Core/IO/ReaderOBJ.cpp b/src/Mod/Mesh/App/Core/IO/ReaderOBJ.cpp index 1cc2d45ef9cb..ad7e9f9fa374 100644 --- a/src/Mod/Mesh/App/Core/IO/ReaderOBJ.cpp +++ b/src/Mod/Mesh/App/Core/IO/ReaderOBJ.cpp @@ -104,9 +104,9 @@ bool ReaderOBJ::Load(std::istream& str) fX = (float)std::atof(what[1].first); fY = (float)std::atof(what[4].first); fZ = (float)std::atof(what[7].first); - float r = std::min(std::atof(what[10].first), 255) / 255.0f; - float g = std::min(std::atof(what[11].first), 255) / 255.0f; - float b = std::min(std::atof(what[12].first), 255) / 255.0f; + float r = std::min(std::atof(what[10].first), 255) / 255.0F; + float g = std::min(std::atof(what[11].first), 255) / 255.0F; + float b = std::min(std::atof(what[12].first), 255) / 255.0F; meshPoints.push_back(MeshPoint(Base::Vector3f(fX, fY, fZ))); App::Color c(r, g, b); @@ -224,7 +224,7 @@ bool ReaderOBJ::Load(std::istream& str) // calling instance but the color list is pre-filled with a default value if (_material) { _material->binding = MeshIO::PER_FACE; - _material->diffuseColor.resize(meshFacets.size(), App::Color(0.8f, 0.8f, 0.8f)); + _material->diffuseColor.resize(meshFacets.size(), App::Color(0.8F, 0.8F, 0.8F)); } } @@ -275,7 +275,7 @@ bool ReaderOBJ::LoadMaterial(std::istream& str) float r = boost::lexical_cast(tokens[1]); return App::Color(r, r, r); } - else if (tokens.size() == 4) { + if (tokens.size() == 4) { float r = boost::lexical_cast(tokens[1]); float g = boost::lexical_cast(tokens[2]); float b = boost::lexical_cast(tokens[3]); @@ -298,7 +298,7 @@ bool ReaderOBJ::LoadMaterial(std::istream& str) } else if (token_results[0] == "d") { float a = boost::lexical_cast(token_results[1]); - materialTransparency[materialName] = 1.0f - a; + materialTransparency[materialName] = 1.0F - a; } // If only R is given then G and B will be equal else if (token_results[0] == "Ka") { @@ -357,12 +357,11 @@ bool ReaderOBJ::LoadMaterial(std::istream& str) _material->transparency.swap(transparency); return true; } - else { - _material->binding = MeshIO::OVERALL; - _material->ambientColor.clear(); - _material->diffuseColor.clear(); - _material->specularColor.clear(); - _material->transparency.clear(); - return false; - } + + _material->binding = MeshIO::OVERALL; + _material->ambientColor.clear(); + _material->diffuseColor.clear(); + _material->specularColor.clear(); + _material->transparency.clear(); + return false; } diff --git a/src/Mod/Mesh/App/Core/IO/WriterInventor.cpp b/src/Mod/Mesh/App/Core/IO/WriterInventor.cpp index aa401c209117..be89c3ed501c 100644 --- a/src/Mod/Mesh/App/Core/IO/WriterInventor.cpp +++ b/src/Mod/Mesh/App/Core/IO/WriterInventor.cpp @@ -41,7 +41,7 @@ class WriterInventorImp return !out || out.bad(); } - WriterInventorImp(Base::InventorBuilder& builder) + explicit WriterInventorImp(Base::InventorBuilder& builder) : builder(builder) {} @@ -62,7 +62,7 @@ class WriterInventorImp std::stringstream str; str << "Triangle mesh contains " << kernel.CountPoints() << " vertices and " << kernel.CountFacets() << " faces"; - Base::LabelItem label {str.str().c_str()}; + Base::LabelItem label {str.str()}; builder.addNode(label); } diff --git a/src/Mod/Mesh/App/Core/IO/WriterOBJ.cpp b/src/Mod/Mesh/App/Core/IO/WriterOBJ.cpp index 3e0b8d797fef..b08bf7d12190 100644 --- a/src/Mod/Mesh/App/Core/IO/WriterOBJ.cpp +++ b/src/Mod/Mesh/App/Core/IO/WriterOBJ.cpp @@ -122,7 +122,7 @@ bool WriterOBJ::Save(std::ostream& out) // vertices Base::Vector3f pt; std::size_t index = 0; - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { if (this->apply_transform) { pt = this->_transform * *it; } @@ -139,9 +139,9 @@ bool WriterOBJ::Save(std::ostream& out) c = _material->diffuseColor.front(); } - int r = static_cast(c.r * 255.0f); - int g = static_cast(c.g * 255.0f); - int b = static_cast(c.b * 255.0f); + int r = static_cast(c.r * 255.0F); + int g = static_cast(c.g * 255.0F); + int b = static_cast(c.b * 255.0F); out << "v " << pt.x << " " << pt.y << " " << pt.z << " " << r << " " << g << " " << b << '\n'; @@ -179,12 +179,10 @@ bool WriterOBJ::Save(std::ostream& out) App::Color prev; int faceIdx = 1; const std::vector& Kd = _material->diffuseColor; - for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); - ++it, index++) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it, index++) { if (index == 0 || prev != Kd[index]) { prev = Kd[index]; - std::vector::iterator c_it = - std::find(colors.begin(), colors.end(), prev); + auto c_it = std::find(colors.begin(), colors.end(), prev); if (c_it != colors.end()) { out << "usemtl material_" << (c_it - colors.begin()) << '\n'; } @@ -226,8 +224,7 @@ bool WriterOBJ::Save(std::ostream& out) if (first || prev != Kd[it]) { first = false; prev = Kd[it]; - std::vector::iterator c_it = - std::find(colors.begin(), colors.end(), prev); + auto c_it = std::find(colors.begin(), colors.end(), prev); if (c_it != colors.end()) { out << "usemtl material_" << (c_it - colors.begin()) << '\n'; } diff --git a/src/Mod/Mesh/App/Core/Info.cpp b/src/Mod/Mesh/App/Core/Info.cpp index 1bde0af7a652..3dd60c7cd615 100644 --- a/src/Mod/Mesh/App/Core/Info.cpp +++ b/src/Mod/Mesh/App/Core/Info.cpp @@ -230,7 +230,7 @@ std::ostream& MeshInfo::TopologyInformation(std::ostream& rclStream) const { unsigned long index = 0; const MeshFacetArray& rFAry = _rclMesh.GetFacets(); - for (MeshFacetArray::_TConstIterator it = rFAry.begin(); it != rFAry.end(); ++it, ++index) { + for (auto it = rFAry.begin(); it != rFAry.end(); ++it, ++index) { rclStream << "F " << std::setw(4) << index << ": P (" << it->_aulPoints[0] << ", " << it->_aulPoints[1] << ", " << it->_aulPoints[2] << "), N (" << it->_aulNeighbours[0] << ", " << it->_aulNeighbours[1] << ", " diff --git a/src/Mod/Mesh/App/Core/Iterator.h b/src/Mod/Mesh/App/Core/Iterator.h index 607c861c6b1c..4949af280835 100644 --- a/src/Mod/Mesh/App/Core/Iterator.h +++ b/src/Mod/Mesh/App/Core/Iterator.h @@ -478,10 +478,9 @@ inline bool MeshFacetIterator::Set(FacetIndex ulIndex) _clIter = _rclFAry.begin() + ulIndex; return true; } - else { - _clIter = _rclFAry.end(); - return false; - } + + _clIter = _rclFAry.end(); + return false; } inline MeshFacetIterator& MeshFacetIterator::operator=(const MeshFacetIterator& rpI) @@ -597,10 +596,9 @@ inline bool MeshPointIterator::Set(PointIndex ulIndex) _clIter = _rclPAry.begin() + ulIndex; return true; } - else { - _clIter = _rclPAry.end(); - return false; - } + + _clIter = _rclPAry.end(); + return false; } inline MeshPointIterator& MeshPointIterator::operator=(const MeshPointIterator& rpI) diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 56cb3c10e88e..47ccec3adbfb 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -166,27 +166,26 @@ MeshIO::Format MeshInput::getFormat(const char* FileName) if (fi.hasExtension("bms")) { return MeshIO::Format::BMS; } - else if (fi.hasExtension("ply")) { + if (fi.hasExtension("ply")) { return MeshIO::Format::PLY; } - else if (fi.hasExtension("stl")) { + if (fi.hasExtension("stl")) { return MeshIO::Format::STL; } - else if (fi.hasExtension("ast")) { + if (fi.hasExtension("ast")) { return MeshIO::Format::ASTL; } - else if (fi.hasExtension("obj")) { + if (fi.hasExtension("obj")) { return MeshIO::Format::OBJ; } - else if (fi.hasExtension("off")) { + if (fi.hasExtension("off")) { return MeshIO::Format::OFF; } - else if (fi.hasExtension("smf")) { + if (fi.hasExtension("smf")) { return MeshIO::Format::SMF; } - else { - throw Base::FileException("File extension not supported", FileName); - } + + throw Base::FileException("File extension not supported", FileName); } bool MeshInput::LoadAny(const char* FileName) @@ -206,71 +205,70 @@ bool MeshInput::LoadAny(const char* FileName) _rclMesh.Read(str); return true; } - else { - // read file - bool ok = false; - if (fi.hasExtension({"stl", "ast"})) { - ok = LoadSTL(str); - } - else if (fi.hasExtension("iv")) { - ok = LoadInventor(str); - if (ok && _rclMesh.CountFacets() == 0) { - Base::Console().Warning("No usable mesh found in file '%s'", FileName); - } - } - else if (fi.hasExtension({"nas", "bdf"})) { - ok = LoadNastran(str); - } - else if (fi.hasExtension("obj")) { - ok = LoadOBJ(str, FileName); - } - else if (fi.hasExtension("smf")) { - ok = LoadSMF(str); - } - else if (fi.hasExtension("3mf")) { - ok = Load3MF(str); - } - else if (fi.hasExtension("off")) { - ok = LoadOFF(str); - } - else if (fi.hasExtension("ply")) { - ok = LoadPLY(str); - } - else { - throw Base::FileException("File extension not supported", FileName); - } - return ok; + // read file + bool ok = false; + if (fi.hasExtension({"stl", "ast"})) { + ok = LoadSTL(str); + } + else if (fi.hasExtension("iv")) { + ok = LoadInventor(str); + if (ok && _rclMesh.CountFacets() == 0) { + Base::Console().Warning("No usable mesh found in file '%s'", FileName); + } + } + else if (fi.hasExtension({"nas", "bdf"})) { + ok = LoadNastran(str); + } + else if (fi.hasExtension("obj")) { + ok = LoadOBJ(str, FileName); + } + else if (fi.hasExtension("smf")) { + ok = LoadSMF(str); + } + else if (fi.hasExtension("3mf")) { + ok = Load3MF(str); + } + else if (fi.hasExtension("off")) { + ok = LoadOFF(str); + } + else if (fi.hasExtension("ply")) { + ok = LoadPLY(str); } + else { + throw Base::FileException("File extension not supported", FileName); + } + + return ok; } -bool MeshInput::LoadFormat(std::istream& str, MeshIO::Format fmt) +bool MeshInput::LoadFormat(std::istream& input, MeshIO::Format fmt) { switch (fmt) { case MeshIO::BMS: - _rclMesh.Read(str); + _rclMesh.Read(input); return true; case MeshIO::APLY: case MeshIO::PLY: - return LoadPLY(str); + return LoadPLY(input); case MeshIO::ASTL: - return LoadAsciiSTL(str); + return LoadAsciiSTL(input); case MeshIO::BSTL: - return LoadBinarySTL(str); + return LoadBinarySTL(input); case MeshIO::STL: - return LoadSTL(str); + return LoadSTL(input); case MeshIO::OBJ: - return LoadOBJ(str); + return LoadOBJ(input); case MeshIO::SMF: - return LoadSMF(str); + return LoadSMF(input); case MeshIO::ThreeMF: - return Load3MF(str); + return Load3MF(input); case MeshIO::OFF: - return LoadOFF(str); + return LoadOFF(input); case MeshIO::IV: - return LoadInventor(str); + return LoadInventor(input); case MeshIO::NAS: - return LoadNastran(str); + return LoadNastran(input); default: throw Base::FileException("Unsupported file format"); } @@ -279,11 +277,11 @@ bool MeshInput::LoadFormat(std::istream& str, MeshIO::Format fmt) /** Loads an STL file either in binary or ASCII format. * Therefore the file header gets checked to decide if the file is binary or not. */ -bool MeshInput::LoadSTL(std::istream& rstrIn) +bool MeshInput::LoadSTL(std::istream& input) { char szBuf[200]; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } @@ -292,20 +290,20 @@ bool MeshInput::LoadSTL(std::istream& rstrIn) // we must not read in more than (max.) 54 bytes because the file size has only 134 bytes in // this case. On the other hand we must overread the first 80 bytes because it can happen that // the file is binary but contains one of these keywords. - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (!buf) { return false; } buf->pubseekoff(80, std::ios::beg, std::ios::in); uint32_t ulCt {}, ulBytes = 50; - rstrIn.read((char*)&ulCt, sizeof(ulCt)); + input.read((char*)&ulCt, sizeof(ulCt)); // if we have a binary STL with a single triangle we can only read-in 50 bytes if (ulCt > 1) { ulBytes = 100; } // Either it's really an invalid STL file or it's just empty. In this case the number of facets // must be 0. - if (!rstrIn.read(szBuf, ulBytes)) { + if (!input.read(szBuf, ulBytes)) { return (ulCt == 0); } szBuf[ulBytes] = 0; @@ -317,13 +315,12 @@ bool MeshInput::LoadSTL(std::istream& rstrIn) && !strstr(szBuf, "ENDLOOP")) { // probably binary STL buf->pubseekoff(0, std::ios::beg, std::ios::in); - return LoadBinarySTL(rstrIn); - } - else { - // Ascii STL - buf->pubseekoff(0, std::ios::beg, std::ios::in); - return LoadAsciiSTL(rstrIn); + return LoadBinarySTL(input); } + + // Ascii STL + buf->pubseekoff(0, std::ios::beg, std::ios::in); + return LoadAsciiSTL(input); } catch (const Base::MemoryException&) { _rclMesh.Clear(); @@ -346,10 +343,10 @@ bool MeshInput::LoadSTL(std::istream& rstrIn) } /** Loads an OBJ file. */ -bool MeshInput::LoadOBJ(std::istream& rstrIn) +bool MeshInput::LoadOBJ(std::istream& input) { ReaderOBJ reader(this->_rclMesh, this->_material); - if (reader.Load(rstrIn)) { + if (reader.Load(input)) { _groupNames = reader.GetGroupNames(); return true; } @@ -357,10 +354,10 @@ bool MeshInput::LoadOBJ(std::istream& rstrIn) return false; } -bool MeshInput::LoadOBJ(std::istream& str, const char* filename) +bool MeshInput::LoadOBJ(std::istream& input, const char* filename) { ReaderOBJ reader(this->_rclMesh, this->_material); - if (reader.Load(str)) { + if (reader.Load(input)) { _groupNames = reader.GetGroupNames(); if (this->_material && this->_material->binding == MeshCore::MeshIO::PER_FACE) { Base::FileInfo fi(filename); @@ -378,7 +375,7 @@ bool MeshInput::LoadOBJ(std::istream& str, const char* filename) } /** Loads an SMF file. */ -bool MeshInput::LoadSMF(std::istream& rstrIn) +bool MeshInput::LoadSMF(std::istream& input) { boost::regex rx_p("^v\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" @@ -397,16 +394,16 @@ bool MeshInput::LoadSMF(std::istream& rstrIn) int i1 = 1, i2 = 1, i3 = 1; MeshFacet item; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (!buf) { return false; } - while (std::getline(rstrIn, line)) { + while (std::getline(input, line)) { if (boost::regex_match(line.c_str(), what, rx_p)) { fX = (float)std::atof(what[1].first); fY = (float)std::atof(what[4].first); @@ -439,7 +436,7 @@ bool MeshInput::LoadSMF(std::istream& rstrIn) } /** Loads an OFF file. */ -bool MeshInput::LoadOFF(std::istream& rstrIn) +bool MeshInput::LoadOFF(std::istream& input) { // http://edutechwiki.unige.ch/en/3D_file_format boost::regex rx_n(R"(^\s*([0-9]+)\s+([0-9]+)\s+([0-9]+)\s*$)"); @@ -453,16 +450,16 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) std::string line; MeshFacet item; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (!buf) { return false; } - std::getline(rstrIn, line); + std::getline(input, line); boost::algorithm::to_lower(line); if (line.find("coff") != std::string::npos) { // we expect colors to be there per vertex: x y z r g b a @@ -476,7 +473,7 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) int numPoints = 0, numFaces = 0; while (true) { - std::getline(rstrIn, line); + std::getline(input, line); boost::algorithm::to_lower(line); if (boost::regex_match(line.c_str(), what, rx_n)) { numPoints = std::atoi(what[1].first); @@ -500,7 +497,7 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) int cntPoints = 0; while (cntPoints < numPoints) { - if (!std::getline(rstrIn, line)) { + if (!std::getline(input, line)) { break; } std::istringstream str(line); @@ -525,14 +522,14 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) str >> std::ws >> a; // no transparency if (!str) { - a = 1.0f; + a = 1.0F; } - if (r > 1.0f || g > 1.0f || b > 1.0f || a > 1.0f) { - r = static_cast(r) / 255.0f; - g = static_cast(g) / 255.0f; - b = static_cast(b) / 255.0f; - a = static_cast(a) / 255.0f; + if (r > 1.0F || g > 1.0F || b > 1.0F || a > 1.0F) { + r = static_cast(r) / 255.0F; + g = static_cast(g) / 255.0F; + b = static_cast(b) / 255.0F; + a = static_cast(a) / 255.0F; } diffuseColor.emplace_back(r, g, b, a); } @@ -543,7 +540,7 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) int cntFaces = 0; while (cntFaces < numFaces) { - if (!std::getline(rstrIn, line)) { + if (!std::getline(input, line)) { break; } std::istringstream str(line); @@ -578,14 +575,14 @@ bool MeshInput::LoadOFF(std::istream& rstrIn) str >> std::ws >> a; // no transparency if (!str) { - a = 1.0f; + a = 1.0F; } - if (r > 1.0f || g > 1.0f || b > 1.0f || a > 1.0f) { - r = static_cast(r) / 255.0f; - g = static_cast(g) / 255.0f; - b = static_cast(b) / 255.0f; - a = static_cast(a) / 255.0f; + if (r > 1.0F || g > 1.0F || b > 1.0F || a > 1.0F) { + r = static_cast(r) / 255.0F; + g = static_cast(g) / 255.0F; + b = static_cast(b) / 255.0F; + a = static_cast(a) / 255.0F; } for (int i = 0; i < count - 2; i++) { diffuseColor.emplace_back(r, g, b, a); @@ -653,7 +650,7 @@ struct Property using namespace Ply; } // namespace MeshCore -bool MeshInput::LoadPLY(std::istream& inp) +bool MeshInput::LoadPLY(std::istream& input) { // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ std::size_t v_count = 0, f_count = 0; @@ -668,20 +665,20 @@ bool MeshInput::LoadPLY(std::istream& inp) binary_big_endian } format = unknown; - if (!inp || inp.bad()) { + if (!input || input.bad()) { return false; } - std::streambuf* buf = inp.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (!buf) { return false; } // read in the first three characters char ply[3]; - inp.read(ply, 3); - inp.ignore(1); - if (!inp) { + input.read(ply, 3); + input.ignore(1); + if (!input) { return false; } if ((ply[0] != 'p') || (ply[1] != 'l') || (ply[2] != 'y')) { @@ -693,7 +690,7 @@ bool MeshInput::LoadPLY(std::istream& inp) std::string line, element; MeshIO::Binding rgb_value = MeshIO::OVERALL; - while (std::getline(inp, line)) { + while (std::getline(input, line)) { std::istringstream str(line); str.unsetf(std::ios_base::skipws); str >> std::ws; @@ -738,7 +735,7 @@ bool MeshInput::LoadPLY(std::istream& inp) !std::isspace(space_element_name) || !std::isspace(space_name_count)) { return false; } - else if (name == "vertex") { + if (name == "vertex") { element = name; v_count = count; meshPoints.reserve(count); @@ -921,7 +918,7 @@ bool MeshInput::LoadPLY(std::istream& inp) boost::regex rx_f(R"(^\s*3\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s*)"); boost::smatch what; - for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { + for (std::size_t i = 0; i < v_count && std::getline(input, line); i++) { // go through the vertex properties std::map prop_values; for (const auto& it : vertex_props) { @@ -976,15 +973,15 @@ bool MeshInput::LoadPLY(std::istream& inp) meshPoints.push_back(pt); if (_material && (rgb_value == MeshIO::PER_VERTEX)) { - float r = (prop_values["red"]) / 255.0f; - float g = (prop_values["green"]) / 255.0f; - float b = (prop_values["blue"]) / 255.0f; + float r = (prop_values["red"]) / 255.0F; + float g = (prop_values["green"]) / 255.0F; + float b = (prop_values["blue"]) / 255.0F; _material->diffuseColor.emplace_back(r, g, b); } } int f1 {}, f2 {}, f3 {}; - for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) { + for (std::size_t i = 0; i < f_count && std::getline(input, line); i++) { if (boost::regex_search(line, what, rx_f)) { f1 = boost::lexical_cast(what[1]); f2 = boost::lexical_cast(what[2]); @@ -995,7 +992,7 @@ bool MeshInput::LoadPLY(std::istream& inp) } // binary else { - Base::InputStream is(inp); + Base::InputStream is(input); if (format == binary_little_endian) { is.setByteOrder(Base::Stream::LittleEndian); } @@ -1060,9 +1057,9 @@ bool MeshInput::LoadPLY(std::istream& inp) meshPoints.push_back(pt); if (_material && (rgb_value == MeshIO::PER_VERTEX)) { - float r = (prop_values["red"]) / 255.0f; - float g = (prop_values["green"]) / 255.0f; - float b = (prop_values["blue"]) / 255.0f; + float r = (prop_values["red"]) / 255.0F; + float g = (prop_values["green"]) / 255.0F; + float b = (prop_values["blue"]) / 255.0F; _material->diffuseColor.emplace_back(r, g, b); } } @@ -1138,7 +1135,7 @@ bool MeshInput::LoadPLY(std::istream& inp) return true; } -bool MeshInput::LoadMeshNode(std::istream& rstrIn) +bool MeshInput::LoadMeshNode(std::istream& input) { boost::regex rx_p("^v\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" @@ -1155,16 +1152,16 @@ bool MeshInput::LoadMeshNode(std::istream& rstrIn) unsigned int i1 = 1, i2 = 1, i3 = 1; MeshGeomFacet clFacet; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (!buf) { return false; } - while (std::getline(rstrIn, line)) { + while (std::getline(input, line)) { boost::algorithm::to_lower(line); if (boost::regex_match(line.c_str(), what, rx_p)) { fX = (float)std::atof(what[1].first); @@ -1195,7 +1192,7 @@ bool MeshInput::LoadMeshNode(std::istream& rstrIn) } /** Loads an ASCII STL file. */ -bool MeshInput::LoadAsciiSTL(std::istream& rstrIn) +bool MeshInput::LoadAsciiSTL(std::istream& input) { boost::regex rx_p("^\\s*VERTEX\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" @@ -1210,27 +1207,27 @@ bool MeshInput::LoadAsciiSTL(std::istream& rstrIn) unsigned long ulVertexCt {}, ulFacetCt {}; MeshGeomFacet clFacet; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } std::streamoff ulSize = 0; - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in); buf->pubseekoff(0, std::ios::beg, std::ios::in); ulSize -= 20; // count facets - while (std::getline(rstrIn, line)) { + while (std::getline(input, line)) { boost::algorithm::to_upper(line); if (line.find("ENDFACET") != std::string::npos) { ulFacetCt++; } // prevent from reading EOF (as I don't know how to reread the file then) - if (rstrIn.tellg() > ulSize) { + if (input.tellg() > ulSize) { break; } - else if (line.find("ENDSOLID") != std::string::npos) { + if (line.find("ENDSOLID") != std::string::npos) { break; } } @@ -1246,7 +1243,7 @@ bool MeshInput::LoadAsciiSTL(std::istream& rstrIn) builder.Initialize(ulFacetCt); ulVertexCt = 0; - while (std::getline(rstrIn, line)) { + while (std::getline(input, line)) { boost::algorithm::to_upper(line); if (boost::regex_match(line.c_str(), what, rx_f)) { fX = (float)std::atof(what[1].first); @@ -1272,29 +1269,29 @@ bool MeshInput::LoadAsciiSTL(std::istream& rstrIn) } /** Loads a binary STL file. */ -bool MeshInput::LoadBinarySTL(std::istream& rstrIn) +bool MeshInput::LoadBinarySTL(std::istream& input) { char szInfo[80]; Base::Vector3f clVects[4]; uint16_t usAtt = 0; uint32_t ulCt = 0; - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } // Header-Info ueberlesen - rstrIn.read(szInfo, sizeof(szInfo)); + input.read(szInfo, sizeof(szInfo)); // Anzahl Facets - rstrIn.read((char*)&ulCt, sizeof(ulCt)); - if (rstrIn.bad()) { + input.read((char*)&ulCt, sizeof(ulCt)); + if (input.bad()) { return false; } // get file size and calculate the number of facets std::streamoff ulSize = 0; - std::streambuf* buf = rstrIn.rdbuf(); + std::streambuf* buf = input.rdbuf(); if (buf) { std::streamoff ulCurr {}; ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in); @@ -1318,13 +1315,13 @@ bool MeshInput::LoadBinarySTL(std::istream& rstrIn) for (uint32_t i = 0; i < ulCt; i++) { // read normal, points - rstrIn.read((char*)&clVects, sizeof(clVects)); + input.read((char*)&clVects, sizeof(clVects)); std::swap(clVects[0], clVects[3]); builder.AddFacet(clVects); // overread 2 bytes attribute - rstrIn.read((char*)&usAtt, sizeof(usAtt)); + input.read((char*)&usAtt, sizeof(usAtt)); } builder.Finish(); @@ -1373,9 +1370,9 @@ void MeshInput::LoadXML(Base::XMLReader& reader) } /** Loads a 3MF file. */ -bool MeshInput::Load3MF(std::istream& inp) +bool MeshInput::Load3MF(std::istream& input) { - Reader3MF reader(inp); + Reader3MF reader(input); reader.Load(); std::vector ids = reader.GetMeshIds(); if (!ids.empty()) { @@ -1396,9 +1393,9 @@ bool MeshInput::Load3MF(std::istream& inp) } /** Loads an OpenInventor file. */ -bool MeshInput::LoadInventor(std::istream& inp) +bool MeshInput::LoadInventor(std::istream& input) { - Base::InventorLoader loader(inp); + Base::InventorLoader loader(input); if (!loader.read()) { return false; } @@ -1444,9 +1441,9 @@ bool MeshInput::LoadInventor(std::istream& inp) } /** Loads a Nastran file. */ -bool MeshInput::LoadNastran(std::istream& rstrIn) +bool MeshInput::LoadNastran(std::istream& input) { - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } @@ -1468,7 +1465,7 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) int badElementCounter = 0; - while (std::getline(rstrIn, line)) { + while (std::getline(input, line)) { boost::algorithm::to_upper(ltrim(line)); if (line.empty()) { // Skip all the following tests @@ -1491,8 +1488,8 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) // GRID* 1 0.1234567890120. // * 1. // - if (line.length() - < 8 + 16 + 16 + 16 + 1) { // Element type(8), index(16), empty(16), x(16), y(>=1) + // Element type(8), index(16), empty(16), x(16), y(>=1) + if (line.length() < 8 + 16 + 16 + 16 + 1) { badElementCounter++; continue; } @@ -1502,7 +1499,7 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) auto yView = std::string_view(&line[8 + 16 + 16 + 16]); std::string line2; - std::getline(rstrIn, line2); + std::getline(input, line2); if ((!line2.empty() && line2[0] != '*') || line2.length() < 9) { badElementCounter++; continue; // File format error: second line is not a continuation line @@ -1563,8 +1560,8 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) // GRID 1 1.2345671.2345671.234567 // GRID 112 6.0000000.5000000.00E+00 - if (line.length() - < 41) { // Element type(8), id(8), cp(8), x(8), y(8), z(at least 1) + // Element type(8), id(8), cp(8), x(8), y(8), z(at least 1) + if (line.length() < 41) { badElementCounter++; continue; } @@ -1585,8 +1582,8 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) badElementCounter++; continue; } - index = indexCheck.get() - - 1; // Minus one so we are zero-indexed to match existing code + // Minus one so we are zero-indexed to match existing code + index = indexCheck.get() - 1; auto x = boost::convert(xString, converter); auto y = boost::convert(yString, converter); @@ -1708,9 +1705,9 @@ bool MeshInput::LoadNastran(std::istream& rstrIn) } /** Loads a Cadmould FE file. */ -bool MeshInput::LoadCadmouldFE(std::ifstream& rstrIn) +bool MeshInput::LoadCadmouldFE(std::ifstream& input) { - if (!rstrIn || rstrIn.bad()) { + if (!input || input.bad()) { return false; } assert(0); @@ -1779,66 +1776,65 @@ MeshIO::Format MeshOutput::GetFormat(const char* FileName) if (file.hasExtension("bms")) { return MeshIO::BMS; } - else if (file.hasExtension("stl")) { + if (file.hasExtension("stl")) { return MeshIO::BSTL; } - else if (file.hasExtension("ast")) { + if (file.hasExtension("ast")) { return MeshIO::ASTL; } - else if (file.hasExtension("obj")) { + if (file.hasExtension("obj")) { return MeshIO::OBJ; } - else if (file.hasExtension("off")) { + if (file.hasExtension("off")) { return MeshIO::OFF; } - else if (file.hasExtension("ply")) { + if (file.hasExtension("ply")) { return MeshIO::PLY; } - else if (file.hasExtension("idtf")) { + if (file.hasExtension("idtf")) { return MeshIO::IDTF; } - else if (file.hasExtension("mgl")) { + if (file.hasExtension("mgl")) { return MeshIO::MGL; } - else if (file.hasExtension("iv")) { + if (file.hasExtension("iv")) { return MeshIO::IV; } - else if (file.hasExtension("x3d")) { + if (file.hasExtension("x3d")) { return MeshIO::X3D; } - else if (file.hasExtension("x3dz")) { + if (file.hasExtension("x3dz")) { return MeshIO::X3DZ; } - else if (file.hasExtension("xhtml")) { + if (file.hasExtension("xhtml")) { return MeshIO::X3DOM; } - else if (file.hasExtension("py")) { + if (file.hasExtension("py")) { return MeshIO::PY; } - else if (file.hasExtension({"wrl", "vrml"})) { + if (file.hasExtension({"wrl", "vrml"})) { return MeshIO::VRML; } - else if (file.hasExtension("wrz")) { + if (file.hasExtension("wrz")) { return MeshIO::WRZ; } - else if (file.hasExtension({"nas", "bdf"})) { + if (file.hasExtension({"nas", "bdf"})) { return MeshIO::NAS; } - else if (file.hasExtension("amf")) { + if (file.hasExtension("amf")) { return MeshIO::AMF; } - else if (file.hasExtension("3mf")) { + if (file.hasExtension("3mf")) { return MeshIO::ThreeMF; } - else if (file.hasExtension("smf")) { + if (file.hasExtension("smf")) { return MeshIO::SMF; } - else if (file.hasExtension("asy")) { + if (file.hasExtension("asy")) { return MeshIO::ASY; } - else { - return MeshIO::Undefined; - } + + return MeshIO::Undefined; } /// Save in a file, format is decided by the extension if not explicitly given @@ -2051,25 +2047,25 @@ bool MeshOutput::SaveFormat(std::ostream& str, MeshIO::Format fmt) const } /** Saves the mesh object into an ASCII file. */ -bool MeshOutput::SaveAsciiSTL(std::ostream& rstrOut) const +bool MeshOutput::SaveAsciiSTL(std::ostream& output) const { MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh); clIter.Transform(this->_transform); const MeshGeomFacet* pclFacet {}; - if (!rstrOut || rstrOut.bad() || _rclMesh.CountFacets() == 0) { + if (!output || output.bad() || _rclMesh.CountFacets() == 0) { return false; } - rstrOut.precision(6); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); + output.precision(6); + output.setf(std::ios::fixed | std::ios::showpoint); Base::SequencerLauncher seq("saving...", _rclMesh.CountFacets() + 1); if (this->objectName.empty()) { - rstrOut << "solid Mesh\n"; + output << "solid Mesh\n"; } else { - rstrOut << "solid " << this->objectName << '\n'; + output << "solid " << this->objectName << '\n'; } clIter.Begin(); @@ -2078,38 +2074,37 @@ bool MeshOutput::SaveAsciiSTL(std::ostream& rstrOut) const pclFacet = &(*clIter); // normal - rstrOut << " facet normal " << pclFacet->GetNormal().x << " " << pclFacet->GetNormal().y - << " " << pclFacet->GetNormal().z << '\n'; - rstrOut << " outer loop\n"; + output << " facet normal " << pclFacet->GetNormal().x << " " << pclFacet->GetNormal().y + << " " << pclFacet->GetNormal().z << '\n'; + output << " outer loop\n"; // vertices for (const auto& pnt : pclFacet->_aclPoints) { - rstrOut << " vertex " << pnt.x << " " << pnt.y << " " << pnt.z << '\n'; + output << " vertex " << pnt.x << " " << pnt.y << " " << pnt.z << '\n'; } - rstrOut << " endloop\n"; - rstrOut << " endfacet\n"; + output << " endloop\n"; + output << " endfacet\n"; ++clIter; seq.next(true); // allow to cancel } - rstrOut << "endsolid Mesh\n"; + output << "endsolid Mesh\n"; return true; } /** Saves the mesh object into a binary file. */ -bool MeshOutput::SaveBinarySTL(std::ostream& rstrOut) const +bool MeshOutput::SaveBinarySTL(std::ostream& output) const { MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh); clIter.Transform(this->_transform); const MeshGeomFacet* pclFacet {}; - uint32_t i {}; uint16_t usAtt {}; char szInfo[81]; - if (!rstrOut || rstrOut.bad() /*|| _rclMesh.CountFacets() == 0*/) { + if (!output || output.bad() /*|| _rclMesh.CountFacets() == 0*/) { return false; } @@ -2117,10 +2112,10 @@ bool MeshOutput::SaveBinarySTL(std::ostream& rstrOut) const // stl_header has a length of 80 strcpy(szInfo, stl_header.c_str()); - rstrOut.write(szInfo, std::strlen(szInfo)); + output.write(szInfo, std::strlen(szInfo)); uint32_t uCtFts = (uint32_t)_rclMesh.CountFacets(); - rstrOut.write((const char*)&uCtFts, sizeof(uCtFts)); + output.write((const char*)&uCtFts, sizeof(uCtFts)); usAtt = 0; clIter.Begin(); @@ -2129,19 +2124,19 @@ bool MeshOutput::SaveBinarySTL(std::ostream& rstrOut) const pclFacet = &(*clIter); // normal Base::Vector3f normal = pclFacet->GetNormal(); - rstrOut.write((const char*)&(normal.x), sizeof(float)); - rstrOut.write((const char*)&(normal.y), sizeof(float)); - rstrOut.write((const char*)&(normal.z), sizeof(float)); + output.write((const char*)&(normal.x), sizeof(float)); + output.write((const char*)&(normal.y), sizeof(float)); + output.write((const char*)&(normal.z), sizeof(float)); // vertices - for (i = 0; i < 3; i++) { - rstrOut.write((const char*)&(pclFacet->_aclPoints[i].x), sizeof(float)); - rstrOut.write((const char*)&(pclFacet->_aclPoints[i].y), sizeof(float)); - rstrOut.write((const char*)&(pclFacet->_aclPoints[i].z), sizeof(float)); + for (uint32_t i = 0; i < 3; i++) { + output.write((const char*)&(pclFacet->_aclPoints[i].x), sizeof(float)); + output.write((const char*)&(pclFacet->_aclPoints[i].y), sizeof(float)); + output.write((const char*)&(pclFacet->_aclPoints[i].z), sizeof(float)); } // attribute - rstrOut.write((const char*)&usAtt, sizeof(usAtt)); + output.write((const char*)&usAtt, sizeof(usAtt)); ++clIter; seq.next(true); // allow to cancel @@ -2206,7 +2201,7 @@ bool MeshOutput::SaveSMF(std::ostream& out) const // vertices Base::Vector3f pt; std::size_t index = 0; - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { if (this->apply_transform) { pt = this->_transform * *it; } @@ -2251,7 +2246,7 @@ bool MeshOutput::SaveAsymptote(std::ostream& out) const Base::Vector3f camera(center); camera.x += std::max(std::max(bbox.LengthX(), bbox.LengthY()), bbox.LengthZ()); Base::Vector3f target(center); - Base::Vector3f upvec(0.0f, 0.0f, 1.0f); + Base::Vector3f upvec(0.0F, 0.0F, 1.0F); out << "// CA:Camera, OB:Camera\n" << "currentprojection = orthographic(camera = (" << camera.x << ", " << camera.y << ", " @@ -2284,7 +2279,7 @@ bool MeshOutput::SaveAsymptote(std::ostream& out) const bool saveFaceColor = (_material && _material->binding == MeshIO::PER_FACE && _material->diffuseColor.size() == rFacets.size()); // global mesh color - App::Color mc(0.8f, 0.8f, 0.8f); + App::Color mc(0.8F, 0.8F, 0.8F); if (_material && _material->binding == MeshIO::OVERALL && _material->diffuseColor.size() == 1) { mc = _material->diffuseColor[0]; } @@ -2379,7 +2374,7 @@ bool MeshOutput::SaveOFF(std::ostream& out) const // vertices Base::Vector3f pt; std::size_t index = 0; - for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { + for (auto it = rPoints.begin(); it != rPoints.end(); ++it, ++index) { if (this->apply_transform) { pt = this->_transform * *it; } @@ -2396,10 +2391,10 @@ bool MeshOutput::SaveOFF(std::ostream& out) const c = _material->diffuseColor.front(); } - int r = static_cast(c.r * 255.0f); - int g = static_cast(c.g * 255.0f); - int b = static_cast(c.b * 255.0f); - int a = static_cast(c.a * 255.0f); + int r = static_cast(c.r * 255.0F); + int g = static_cast(c.g * 255.0F); + int b = static_cast(c.b * 255.0F); + int a = static_cast(c.a * 255.0F); out << pt.x << " " << pt.y << " " << pt.z << " " << r << " " << g << " " << b << " " << a << '\n'; @@ -2461,9 +2456,9 @@ bool MeshOutput::SaveBinaryPLY(std::ostream& out) const } if (saveVertexColor) { const App::Color& c = _material->diffuseColor[i]; - uint8_t r = uint8_t(255.0f * c.r); - uint8_t g = uint8_t(255.0f * c.g); - uint8_t b = uint8_t(255.0f * c.b); + uint8_t r = uint8_t(255.0F * c.r); + uint8_t g = uint8_t(255.0F * c.g); + uint8_t b = uint8_t(255.0F * c.b); os << r << g << b; } } @@ -2523,9 +2518,9 @@ bool MeshOutput::SaveAsciiPLY(std::ostream& out) const } const App::Color& c = _material->diffuseColor[i]; - int r = (int)(255.0f * c.r); - int g = (int)(255.0f * c.g); - int b = (int)(255.0f * c.b); + int r = (int)(255.0F * c.r); + int g = (int)(255.0F * c.g); + int b = (int)(255.0F * c.b); out << " " << r << " " << g << " " << b << '\n'; } } @@ -2555,35 +2550,35 @@ bool MeshOutput::SaveAsciiPLY(std::ostream& out) const return true; } -bool MeshOutput::SaveMeshNode(std::ostream& rstrOut) +bool MeshOutput::SaveMeshNode(std::ostream& output) { const MeshPointArray& rPoints = _rclMesh.GetPoints(); const MeshFacetArray& rFacets = _rclMesh.GetFacets(); - if (!rstrOut || rstrOut.bad()) { + if (!output || output.bad()) { return false; } // vertices - rstrOut << "[" << '\n'; + output << "[" << '\n'; if (this->apply_transform) { Base::Vector3f pt; for (const auto& it : rPoints) { pt = this->_transform * it; - rstrOut << "v " << pt.x << " " << pt.y << " " << pt.z << '\n'; + output << "v " << pt.x << " " << pt.y << " " << pt.z << '\n'; } } else { for (const auto& it : rPoints) { - rstrOut << "v " << it.x << " " << it.y << " " << it.z << '\n'; + output << "v " << it.x << " " << it.y << " " << it.z << '\n'; } } // facet indices (no texture and normal indices) for (const auto& it : rFacets) { - rstrOut << "f " << it._aulPoints[0] + 1 << " " << it._aulPoints[1] + 1 << " " - << it._aulPoints[2] + 1 << '\n'; + output << "f " << it._aulPoints[0] + 1 << " " << it._aulPoints[1] + 1 << " " + << it._aulPoints[2] + 1 << '\n'; } - rstrOut << "]" << '\n'; + output << "]" << '\n'; return true; } @@ -2643,9 +2638,9 @@ void MeshOutput::SaveXML(Base::Writer& writer) const } /** Saves the mesh object into a 3MF file. */ -bool MeshOutput::Save3MF(std::ostream& str) const +bool MeshOutput::Save3MF(std::ostream& output) const { - Writer3MF writer(str); + Writer3MF writer(output); writer.AddMesh(_rclMesh, _transform); return writer.Save(); } @@ -2715,13 +2710,13 @@ bool MeshOutput::SaveIDTF(std::ostream& str) const str << Base::tabs(3) << "}\n"; str << Base::tabs(3) << "MESH_FACE_NORMAL_LIST {\n"; int index = 0; - for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) { + for (auto it = fts.begin(); it != fts.end(); ++it) { str << Base::tabs(4) << index << " " << index + 1 << " " << index + 2 << '\n'; index += 3; } str << Base::tabs(3) << "}\n"; str << Base::tabs(3) << "MESH_FACE_SHADING_LIST {\n"; - for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) { + for (auto it = fts.begin(); it != fts.end(); ++it) { str << Base::tabs(4) << "0\n"; } str << Base::tabs(3) << "}\n"; @@ -2801,11 +2796,11 @@ bool MeshOutput::SaveMGL(std::ostream& str) const } /** Writes an OpenInventor file. */ -bool MeshOutput::SaveInventor(std::ostream& rstrOut) const +bool MeshOutput::SaveInventor(std::ostream& output) const { WriterInventor writer(_rclMesh, _material); writer.SetTransform(_transform); - return writer.Save(rstrOut); + return writer.Save(output); } /** Writes an X3D file. */ @@ -2835,7 +2830,7 @@ bool MeshOutput::SaveX3DContent(std::ostream& out, bool exportViewpoints) const bbox = bbox.Transformed(_transform); } - App::Color mat(0.65f, 0.65f, 0.65f); + App::Color mat(0.65F, 0.65F, 0.65F); if (_material && _material->binding == MeshIO::Binding::OVERALL) { if (!_material->diffuseColor.empty()) { mat = _material->diffuseColor.front(); @@ -2878,44 +2873,44 @@ bool MeshOutput::SaveX3DContent(std::ostream& out, bool exportViewpoints) const }; Base::Vector3f cnt = bbox.GetCenter(); - float dist = 1.2f * bbox.CalcDiagonalLength(); - float dist3 = 0.577350f * dist; // sqrt(1/3) * dist + float dist = 1.2F * bbox.CalcDiagonalLength(); + float dist3 = 0.577350F * dist; // sqrt(1/3) * dist viewpoint("Iso", cnt, Base::Vector3f(cnt.x + dist3, cnt.y - dist3, cnt.z + dist3), - Base::Vector3f(0.742906f, 0.307722f, 0.594473f), - 1.21712f); + Base::Vector3f(0.742906F, 0.307722F, 0.594473F), + 1.21712F); viewpoint("Front", cnt, Base::Vector3f(cnt.x, cnt.y - dist, cnt.z), - Base::Vector3f(1.0f, 0.0f, 0.0f), - 1.5707964f); + Base::Vector3f(1.0F, 0.0F, 0.0F), + 1.5707964F); viewpoint("Back", cnt, Base::Vector3f(cnt.x, cnt.y + dist, cnt.z), - Base::Vector3f(0.0f, 0.707106f, 0.707106f), - 3.141592f); + Base::Vector3f(0.0F, 0.707106F, 0.707106F), + 3.141592F); viewpoint("Right", cnt, Base::Vector3f(cnt.x + dist, cnt.y, cnt.z), - Base::Vector3f(0.577350f, 0.577350f, 0.577350f), - 2.094395f); + Base::Vector3f(0.577350F, 0.577350F, 0.577350F), + 2.094395F); viewpoint("Left", cnt, Base::Vector3f(cnt.x - dist, cnt.y, cnt.z), - Base::Vector3f(-0.577350f, 0.577350f, 0.577350f), - 4.188790f); + Base::Vector3f(-0.577350F, 0.577350F, 0.577350F), + 4.188790F); viewpoint("Top", cnt, Base::Vector3f(cnt.x, cnt.y, cnt.z + dist), - Base::Vector3f(0.0f, 0.0f, 1.0f), - 0.0f); + Base::Vector3f(0.0F, 0.0F, 1.0F), + 0.0F); viewpoint("Bottom", cnt, Base::Vector3f(cnt.x, cnt.y, cnt.z - dist), - Base::Vector3f(1.0f, 0.0f, 0.0f), - 3.141592f); + Base::Vector3f(1.0F, 0.0F, 0.0F), + 3.141592F); } if (apply_transform) { @@ -3032,9 +3027,9 @@ bool MeshOutput::SaveX3DOM(std::ostream& out) const } /** Writes a Nastran file. */ -bool MeshOutput::SaveNastran(std::ostream& rstrOut) const +bool MeshOutput::SaveNastran(std::ostream& output) const { - if (!rstrOut || rstrOut.bad() || (_rclMesh.CountFacets() == 0)) { + if (!output || output.bad() || (_rclMesh.CountFacets() == 0)) { return false; } @@ -3045,20 +3040,20 @@ bool MeshOutput::SaveNastran(std::ostream& rstrOut) const Base::SequencerLauncher seq("Saving...", _rclMesh.CountFacets() + 1); - rstrOut.precision(3); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); + output.precision(3); + output.setf(std::ios::fixed | std::ios::showpoint); for (clPIter.Init(); clPIter.More(); clPIter.Next()) { float x = clPIter->x; float y = clPIter->y; float z = clPIter->z; - rstrOut << "GRID"; + output << "GRID"; - rstrOut << std::setfill(' ') << std::setw(12) << iIndx; - rstrOut << std::setfill(' ') << std::setw(16) << x; - rstrOut << std::setfill(' ') << std::setw(8) << y; - rstrOut << std::setfill(' ') << std::setw(8) << z; - rstrOut << '\n'; + output << std::setfill(' ') << std::setw(12) << iIndx; + output << std::setfill(' ') << std::setw(16) << x; + output << std::setfill(' ') << std::setw(8) << y; + output << std::setfill(' ') << std::setw(8) << z; + output << '\n'; iIndx++; seq.next(); @@ -3066,26 +3061,26 @@ bool MeshOutput::SaveNastran(std::ostream& rstrOut) const iIndx = 1; for (clTIter.Init(); clTIter.More(); clTIter.Next()) { - rstrOut << "CTRIA3"; + output << "CTRIA3"; - rstrOut << std::setfill(' ') << std::setw(10) << iIndx; - rstrOut << std::setfill(' ') << std::setw(8) << (int)0; - rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[1] + 1; - rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[0] + 1; - rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[2] + 1; - rstrOut << '\n'; + output << std::setfill(' ') << std::setw(10) << iIndx; + output << std::setfill(' ') << std::setw(8) << (int)0; + output << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[1] + 1; + output << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[0] + 1; + output << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[2] + 1; + output << '\n'; iIndx++; seq.next(); } - rstrOut << "ENDDATA"; + output << "ENDDATA"; return true; } /** Writes a Cadmould FE file. */ -bool MeshOutput::SaveCadmouldFE(std::ostream& /*rstrOut*/) const +bool MeshOutput::SaveCadmouldFE(std::ostream& /*output*/) const { return false; } @@ -3117,9 +3112,9 @@ bool MeshOutput::SavePython(std::ostream& str) const } /** Writes a VRML file. */ -bool MeshOutput::SaveVRML(std::ostream& rstrOut) const +bool MeshOutput::SaveVRML(std::ostream& output) const { - if (!rstrOut || rstrOut.bad() || (_rclMesh.CountFacets() == 0)) { + if (!output || output.bad() || (_rclMesh.CountFacets() == 0)) { return false; } @@ -3128,124 +3123,123 @@ bool MeshOutput::SaveVRML(std::ostream& rstrOut) const Base::SequencerLauncher seq("Saving VRML file...", _rclMesh.CountPoints() + _rclMesh.CountFacets()); - rstrOut << "#VRML V2.0 utf8\n"; - rstrOut << "WorldInfo {\n" - << " title \"Exported triangle mesh to VRML97\"\n" - << " info [\"Created by FreeCAD\"\n" - << " \"\"]\n" - << "}\n\n"; + output << "#VRML V2.0 utf8\n"; + output << "WorldInfo {\n" + << " title \"Exported triangle mesh to VRML97\"\n" + << " info [\"Created by FreeCAD\"\n" + << " \"\"]\n" + << "}\n\n"; // Transform - rstrOut.precision(3); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); - rstrOut << "Transform {\n" - << " scale 1 1 1\n" - << " rotation 0 0 1 0\n" - << " scaleOrientation 0 0 1 0\n" - << " center " << 0.0f << " " << 0.0f << " " << 0.0f << "\n" - << " translation " << 0.0f << " " << 0.0f << " " << 0.0f << "\n"; - - rstrOut << " children\n"; - rstrOut << " Shape { \n"; + output.precision(3); + output.setf(std::ios::fixed | std::ios::showpoint); + output << "Transform {\n" + << " scale 1 1 1\n" + << " rotation 0 0 1 0\n" + << " scaleOrientation 0 0 1 0\n" + << " center " << 0.0F << " " << 0.0F << " " << 0.0F << "\n" + << " translation " << 0.0F << " " << 0.0F << " " << 0.0F << "\n"; + + output << " children\n"; + output << " Shape { \n"; // write appearance - rstrOut << " appearance\n" - << " Appearance {\n" - << " material\n" - << " Material {\n"; + output << " appearance\n" + << " Appearance {\n" + << " material\n" + << " Material {\n"; if (_material && _material->binding == MeshIO::OVERALL) { if (!_material->diffuseColor.empty()) { App::Color c = _material->diffuseColor.front(); - rstrOut << " diffuseColor " << c.r << " " << c.g << " " << c.b << "\n"; + output << " diffuseColor " << c.r << " " << c.g << " " << c.b << "\n"; } else { - rstrOut << " diffuseColor 0.8 0.8 0.8\n"; + output << " diffuseColor 0.8 0.8 0.8\n"; } } else { - rstrOut << " diffuseColor 0.8 0.8 0.8\n"; + output << " diffuseColor 0.8 0.8 0.8\n"; } - rstrOut << " }\n }\n"; // end write appearance + output << " }\n }\n"; // end write appearance // write IndexedFaceSet - rstrOut << " geometry\n" - << " IndexedFaceSet {\n"; + output << " geometry\n" + << " IndexedFaceSet {\n"; - rstrOut.precision(2); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); + output.precision(2); + output.setf(std::ios::fixed | std::ios::showpoint); // write coords - rstrOut << " coord\n Coordinate {\n point [\n"; + output << " coord\n Coordinate {\n point [\n"; MeshPointIterator pPIter(_rclMesh); pPIter.Transform(this->_transform); unsigned long i = 0, k = _rclMesh.CountPoints(); - rstrOut.precision(3); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); + output.precision(3); + output.setf(std::ios::fixed | std::ios::showpoint); for (pPIter.Init(); pPIter.More(); pPIter.Next()) { - rstrOut << " " << pPIter->x << " " << pPIter->y << " " << pPIter->z; + output << " " << pPIter->x << " " << pPIter->y << " " << pPIter->z; if (i++ < (k - 1)) { - rstrOut << ",\n"; + output << ",\n"; } else { - rstrOut << "\n"; + output << "\n"; } seq.next(); } - rstrOut << " ]\n }\n"; // end write coord + output << " ]\n }\n"; // end write coord if (_material && _material->binding != MeshIO::OVERALL) { // write colors for each vertex - rstrOut << " color\n Color {\n color [\n"; - rstrOut.precision(3); - rstrOut.setf(std::ios::fixed | std::ios::showpoint); - for (std::vector::const_iterator pCIter = _material->diffuseColor.begin(); - pCIter != _material->diffuseColor.end(); + output << " color\n Color {\n color [\n"; + output.precision(3); + output.setf(std::ios::fixed | std::ios::showpoint); + for (auto pCIter = _material->diffuseColor.begin(); pCIter != _material->diffuseColor.end(); ++pCIter) { - rstrOut << " " << float(pCIter->r) << " " << float(pCIter->g) << " " - << float(pCIter->b); + output << " " << float(pCIter->r) << " " << float(pCIter->g) << " " + << float(pCIter->b); if (pCIter < (_material->diffuseColor.end() - 1)) { - rstrOut << ",\n"; + output << ",\n"; } else { - rstrOut << "\n"; + output << "\n"; } } - rstrOut << " ]\n }\n"; + output << " ]\n }\n"; if (_material->binding == MeshIO::PER_VERTEX) { - rstrOut << " colorPerVertex TRUE\n"; + output << " colorPerVertex TRUE\n"; } else { - rstrOut << " colorPerVertex FALSE\n"; + output << " colorPerVertex FALSE\n"; } } // write face index - rstrOut << " coordIndex [\n"; + output << " coordIndex [\n"; MeshFacetIterator pFIter(_rclMesh); pFIter.Transform(this->_transform); i = 0, k = _rclMesh.CountFacets(); for (pFIter.Init(); pFIter.More(); pFIter.Next()) { MeshFacet clFacet = pFIter.GetIndices(); - rstrOut << " " << clFacet._aulPoints[0] << ", " << clFacet._aulPoints[1] << ", " - << clFacet._aulPoints[2] << ", -1"; + output << " " << clFacet._aulPoints[0] << ", " << clFacet._aulPoints[1] << ", " + << clFacet._aulPoints[2] << ", -1"; if (i++ < (k - 1)) { - rstrOut << ",\n"; + output << ",\n"; } else { - rstrOut << "\n"; + output << "\n"; } seq.next(); } - rstrOut << " ]\n }\n"; // End IndexedFaceSet - rstrOut << " }\n"; // End Shape - rstrOut << "}\n"; // close children and Transform + output << " ]\n }\n"; // End IndexedFaceSet + output << " }\n"; // End Shape + output << "}\n"; // close children and Transform return true; } @@ -3343,8 +3337,7 @@ void MeshCleanup::RemoveInvalidPoints() MeshPointArray::_TIterator p_end = pointArray.end(); std::vector::iterator decr_it = decrements.begin(); - for (MeshPointArray::_TIterator p_it = pointArray.begin(); p_it != p_end; - ++p_it, ++decr_it) { + for (auto p_it = pointArray.begin(); p_it != p_end; ++p_it, ++decr_it) { *decr_it = decr; if (!p_it->IsValid()) { decr++; @@ -3353,7 +3346,7 @@ void MeshCleanup::RemoveInvalidPoints() // correct point indices of the facets MeshFacetArray::_TIterator f_end = facetArray.end(); - for (MeshFacetArray::_TIterator f_it = facetArray.begin(); f_it != f_end; ++f_it) { + for (auto f_it = facetArray.begin(); f_it != f_end; ++f_it) { f_it->_aulPoints[0] -= decrements[f_it->_aulPoints[0]]; f_it->_aulPoints[1] -= decrements[f_it->_aulPoints[1]]; f_it->_aulPoints[2] -= decrements[f_it->_aulPoints[2]]; diff --git a/src/Mod/Mesh/App/Core/MeshIO.h b/src/Mod/Mesh/App/Core/MeshIO.h index c460186b5752..d005957a9220 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.h +++ b/src/Mod/Mesh/App/Core/MeshIO.h @@ -122,37 +122,37 @@ class MeshExport MeshInput /// Loads the file, decided by extension bool LoadAny(const char* FileName); /// Loads from a stream and the given format - bool LoadFormat(std::istream& str, MeshIO::Format fmt); + bool LoadFormat(std::istream& input, MeshIO::Format fmt); /** Loads an STL file either in binary or ASCII format. * Therefore the file header gets checked to decide if the file is binary or not. */ - bool LoadSTL(std::istream& rstrIn); + bool LoadSTL(std::istream& input); /** Loads an ASCII STL file. */ - bool LoadAsciiSTL(std::istream& rstrIn); + bool LoadAsciiSTL(std::istream& input); /** Loads a binary STL file. */ - bool LoadBinarySTL(std::istream& rstrIn); + bool LoadBinarySTL(std::istream& input); /** Loads an OBJ Mesh file. */ - bool LoadOBJ(std::istream& rstrIn); + bool LoadOBJ(std::istream& input); /** Loads an OBJ Mesh file. */ - bool LoadOBJ(std::istream& rstrIn, const char* filename); + bool LoadOBJ(std::istream& input, const char* filename); /** Loads an SMF Mesh file. */ - bool LoadSMF(std::istream& rstrIn); + bool LoadSMF(std::istream& input); /** Loads an OFF Mesh file. */ - bool LoadOFF(std::istream& rstrIn); + bool LoadOFF(std::istream& input); /** Loads a PLY Mesh file. */ - bool LoadPLY(std::istream& rstrIn); + bool LoadPLY(std::istream& input); /** Loads the mesh object from an XML file. */ void LoadXML(Base::XMLReader& reader); /** Loads the mesh object from a 3MF file. */ - bool Load3MF(std::istream& str); + bool Load3MF(std::istream& input); /** Loads a node from an OpenInventor file. */ - bool LoadMeshNode(std::istream& rstrIn); + bool LoadMeshNode(std::istream& input); /** Loads an OpenInventor file. */ - bool LoadInventor(std::istream& rstrIn); + bool LoadInventor(std::istream& input); /** Loads a Nastran file. */ - bool LoadNastran(std::istream& rstrIn); + bool LoadNastran(std::istream& input); /** Loads a Cadmould FE file. */ - bool LoadCadmouldFE(std::ifstream& rstrIn); + bool LoadCadmouldFE(std::ifstream& input); static std::vector supportedMeshFormats(); static MeshIO::Format getFormat(const char* FileName); @@ -208,53 +208,53 @@ class MeshExport MeshOutput bool SaveFormat(std::ostream& str, MeshIO::Format fmt) const; /** Saves the mesh object into an ASCII STL file. */ - bool SaveAsciiSTL(std::ostream& rstrOut) const; + bool SaveAsciiSTL(std::ostream& output) const; /** Saves the mesh object into a binary STL file. */ - bool SaveBinarySTL(std::ostream& rstrOut) const; + bool SaveBinarySTL(std::ostream& output) const; /** Saves the mesh object into an OBJ file. */ - bool SaveOBJ(std::ostream& rstrOut) const; + bool SaveOBJ(std::ostream& output) const; /** Saves the mesh object into an OBJ file. */ - bool SaveOBJ(std::ostream& rstrOut, const char* filename) const; + bool SaveOBJ(std::ostream& output, const char* filename) const; /** Saves the mesh object into an SMF file. */ - bool SaveSMF(std::ostream& rstrOut) const; + bool SaveSMF(std::ostream& output) const; /** Saves the mesh object into an OFF file. */ - bool SaveOFF(std::ostream& rstrOut) const; + bool SaveOFF(std::ostream& output) const; /** Saves the mesh object into a binary PLY file. */ - bool SaveBinaryPLY(std::ostream& rstrOut) const; + bool SaveBinaryPLY(std::ostream& output) const; /** Saves the mesh object into an ASCII PLY file. */ - bool SaveAsciiPLY(std::ostream& rstrOut) const; + bool SaveAsciiPLY(std::ostream& output) const; /** Saves the mesh object into an asymptote file. */ - bool SaveAsymptote(std::ostream& rstrOut) const; + bool SaveAsymptote(std::ostream& output) const; /** Saves the mesh object into an XML file. */ void SaveXML(Base::Writer& writer) const; /** Saves the mesh object into a 3MF file. */ - bool Save3MF(std::ostream& str) const; + bool Save3MF(std::ostream& output) const; /** Saves a node to an OpenInventor file. */ - bool SaveMeshNode(std::ostream& rstrIn); + bool SaveMeshNode(std::ostream& output); /** Writes an IDTF file. */ - bool SaveIDTF(std::ostream& rstrOut) const; + bool SaveIDTF(std::ostream& str) const; /** Writes an MGL file. */ - bool SaveMGL(std::ostream& rstrOut) const; + bool SaveMGL(std::ostream& str) const; /** Writes an OpenInventor file. */ - bool SaveInventor(std::ostream& rstrOut) const; + bool SaveInventor(std::ostream& output) const; /** Writes an X3D file. */ - bool SaveX3D(std::ostream& rstrOut) const; + bool SaveX3D(std::ostream& output) const; /** Writes an X3dom file. */ - bool SaveX3DOM(std::ostream& rstrOut) const; + bool SaveX3DOM(std::ostream& output) const; /** Writes a VRML file. */ - bool SaveVRML(std::ostream& rstrOut) const; + bool SaveVRML(std::ostream& output) const; /** Writes a Nastran file. */ - bool SaveNastran(std::ostream& rstrOut) const; + bool SaveNastran(std::ostream& output) const; /** Writes a Cadmould FE file. */ - bool SaveCadmouldFE(std::ostream& rstrOut) const; + bool SaveCadmouldFE(std::ostream& output) const; /** Writes a python module which creates a mesh */ - bool SavePython(std::ostream& rstrOut) const; + bool SavePython(std::ostream& str) const; static std::vector supportedMeshFormats(); protected: /** Writes an X3D file. */ - bool SaveX3DContent(std::ostream& rstrOut, bool exportViewpoints) const; + bool SaveX3DContent(std::ostream& out, bool exportViewpoints) const; private: const MeshKernel& _rclMesh; /**< reference to mesh data structure */ diff --git a/src/Mod/Mesh/App/Core/MeshKernel.cpp b/src/Mod/Mesh/App/Core/MeshKernel.cpp index 312cadca0d4e..72eadd086a12 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.cpp +++ b/src/Mod/Mesh/App/Core/MeshKernel.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ #include +#include #include #include #include @@ -150,8 +151,7 @@ void MeshKernel::AddFacet(const MeshGeomFacet& rclSFacet) PointIndex ulP1 = clFacet._aulPoints[1]; PointIndex ulP2 = clFacet._aulPoints[2]; FacetIndex ulCC = 0; - for (TMeshFacetArray::iterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); - ++pF, ulCC++) { + for (auto pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); ++pF, ulCC++) { for (int i = 0; i < 3; i++) { PointIndex ulP = pF->_aulPoints[i]; PointIndex ulQ = pF->_aulPoints[(i + 1) % 3]; @@ -215,8 +215,7 @@ unsigned long MeshKernel::AddFacets(const std::vector& rclFAry, bool this->_aclPointArray.ResetInvalid(); FacetIndex k = CountFacets(); std::map, std::list> edgeMap; - for (std::vector::const_iterator pF = rclFAry.begin(); pF != rclFAry.end(); - ++pF, k++) { + for (auto pF = rclFAry.begin(); pF != rclFAry.end(); ++pF, k++) { // reset INVALID flag for all candidates pF->ResetFlag(MeshFacet::INVALID); for (int i = 0; i < 3; i++) { @@ -234,8 +233,7 @@ unsigned long MeshKernel::AddFacets(const std::vector& rclFAry, bool // Check for the above edges in the current facet array k = 0; - for (MeshFacetArray::_TIterator pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); - ++pF, k++) { + for (auto pF = _aclFacetArray.begin(); pF != _aclFacetArray.end(); ++pF, k++) { // if none of the points references one of the edges ignore the facet if (!this->_aclPointArray[pF->_aulPoints[0]].IsFlag(MeshPoint::INVALID) && !this->_aclPointArray[pF->_aulPoints[1]].IsFlag(MeshPoint::INVALID) @@ -248,8 +246,7 @@ unsigned long MeshKernel::AddFacets(const std::vector& rclFAry, bool PointIndex ulP0 = std::min(ulT0, ulT1); PointIndex ulP1 = std::max(ulT0, ulT1); std::pair edge = std::make_pair(ulP0, ulP1); - std::map, std::list>::iterator pI = - edgeMap.find(edge); + auto pI = edgeMap.find(edge); // Does the current facet share the same edge? if (pI != edgeMap.end()) { pI->second.push_front(k); @@ -412,7 +409,7 @@ void MeshKernel::Merge(const MeshPointArray& rPoints, const MeshFacetArray& rFac this->_aclPointArray.reserve(this->_aclPointArray.size() + countNewPoints); // Now we can start inserting the points and adjust the point indices of the faces - for (std::vector::iterator it = increments.begin(); it != increments.end(); ++it) { + for (auto it = increments.begin(); it != increments.end(); ++it) { if (*it > 0) { // set the index of the point array *it = index++; @@ -422,8 +419,7 @@ void MeshKernel::Merge(const MeshPointArray& rPoints, const MeshFacetArray& rFac } } - for (MeshFacetArray::_TIterator pF = this->_aclFacetArray.begin() + countFacets; - pF != this->_aclFacetArray.end(); + for (auto pF = this->_aclFacetArray.begin() + countFacets; pF != this->_aclFacetArray.end(); ++pF) { for (PointIndex& index : pF->_aulPoints) { index = increments[index]; @@ -786,14 +782,14 @@ void MeshKernel::CutFacets(const MeshFacetGrid& rclGrid, DeleteFacets(aulFacets); } -void MeshKernel::CutFacets(const MeshFacetGrid& rclGrid, - const Base::ViewProjMethod* pclProj, - const Base::Polygon2d& rclPoly, +void MeshKernel::CutFacets(const MeshFacetGrid& grid, + const Base::ViewProjMethod* proj, + const Base::Polygon2d& poly, bool bInner, - std::vector& raclCutted) + std::vector& cut) { - MeshAlgorithm(*this).CheckFacets(rclGrid, pclProj, rclPoly, bInner, raclCutted); - DeleteFacets(raclCutted); + MeshAlgorithm(*this).CheckFacets(grid, proj, poly, bInner, cut); + DeleteFacets(cut); } std::vector MeshKernel::GetFacetPoints(const std::vector& facets) const @@ -1043,15 +1039,15 @@ void MeshKernel::Read(std::istream& rclIn) } // without edge array - if (ratio < 2.5f) { + if (ratio < 2.5F) { // the stored mesh kernel might be empty if (uCtPts > 0) { pointArray.resize(uCtPts); - rclIn.read((char*)&(pointArray[0]), uCtPts * sizeof(MeshPoint)); + rclIn.read((char*)pointArray.data(), uCtPts * sizeof(MeshPoint)); } if (uCtFts > 0) { facetArray.resize(uCtFts); - rclIn.read((char*)&(facetArray[0]), uCtFts * sizeof(MeshFacet)); + rclIn.read((char*)facetArray.data(), uCtFts * sizeof(MeshFacet)); } rclIn.read((char*)&_clBoundBox, sizeof(Base::BoundBox3f)); } @@ -1109,12 +1105,11 @@ void MeshKernel::operator*=(const Base::Matrix4D& rclMat) void MeshKernel::Transform(const Base::Matrix4D& rclMat) { - MeshPointArray::_TIterator clPIter = _aclPointArray.begin(), clPEIter = _aclPointArray.end(); - Base::Matrix4D clMatrix(rclMat); + auto clPIter = _aclPointArray.begin(), clPEIter = _aclPointArray.end(); _clBoundBox.SetVoid(); while (clPIter < clPEIter) { - *clPIter *= clMatrix; + *clPIter *= rclMat; _clBoundBox.Add(*clPIter); clPIter++; } @@ -1218,8 +1213,8 @@ float MeshKernel::GetVolume() const - p1.x * p3.y * p2.z - p2.x * p1.y * p3.z + p1.x * p2.y * p3.z); } - fVolume /= 6.0f; - fVolume = fabs(fVolume); + fVolume /= 6.0F; + fVolume = std::fabs(fVolume); return fVolume; } diff --git a/src/Mod/Mesh/App/Core/MeshKernel.h b/src/Mod/Mesh/App/Core/MeshKernel.h index 003ee2a0e48e..6e0f9e620eba 100644 --- a/src/Mod/Mesh/App/Core/MeshKernel.h +++ b/src/Mod/Mesh/App/Core/MeshKernel.h @@ -418,14 +418,14 @@ class MeshExport MeshKernel * checkNeighbourHood is true. */ void Assign(const MeshPointArray& rPoints, - const MeshFacetArray& rFaces, + const MeshFacetArray& rFacets, bool checkNeighbourHood = false); /** This method does basically the same as Assign() unless that it swaps the content of both * arrays. These arrays may be empty after assigning to the kernel. This method is a convenient * way to build up the mesh structure from outside and assign to a mesh kernel without copying * the data. Especially for huge meshes this saves memory and increases speed. */ - void Adopt(MeshPointArray& rPoints, MeshFacetArray& rFaces, bool checkNeighbourHood = false); + void Adopt(MeshPointArray& rPoints, MeshFacetArray& rFacets, bool checkNeighbourHood = false); /// Swaps the content of this kernel and \a mesh void Swap(MeshKernel& mesh); /// Transform the data structure with the given transformation matrix. @@ -441,7 +441,7 @@ class MeshExport MeshKernel /** Sets the point at the given index to the new \a rPoint. */ inline void SetPoint(PointIndex ulPtIndex, float x, float y, float z); /** Smoothes the mesh kernel. */ - void Smooth(int iterations, float d_max); + void Smooth(int iterations, float stepsize); /** * CheckFacets() is invoked within this method and all found facets get deleted from the mesh * structure. The facets to be deleted are returned with their geometric representation. @@ -456,11 +456,11 @@ class MeshExport MeshKernel * Does basically the same as method above unless that the facets to be deleted are returned * with their index number in the facet array of the mesh structure. */ - void CutFacets(const MeshFacetGrid& rclGrid, - const Base::ViewProjMethod* pclP, - const Base::Polygon2d& rclPoly, - bool bCutInner, - std::vector& raclCutted); + void CutFacets(const MeshFacetGrid& grid, + const Base::ViewProjMethod* proj, + const Base::Polygon2d& poly, + bool bInner, + std::vector& cut); //@} protected: @@ -568,7 +568,7 @@ inline void MeshKernel::AdjustNormal(MeshFacet& rclFacet, const Base::Vector3f& Base::Vector3f clN = (_aclPointArray[rclFacet._aulPoints[1]] - _aclPointArray[rclFacet._aulPoints[0]]) % (_aclPointArray[rclFacet._aulPoints[2]] - _aclPointArray[rclFacet._aulPoints[0]]); - if ((clN * rclNormal) < 0.0f) { + if ((clN * rclNormal) < 0.0F) { rclFacet.FlipNormal(); } } @@ -587,9 +587,9 @@ inline Base::Vector3f MeshKernel::GetGravityPoint(const MeshFacet& rclFacet) con const Base::Vector3f& p0 = _aclPointArray[rclFacet._aulPoints[0]]; const Base::Vector3f& p1 = _aclPointArray[rclFacet._aulPoints[1]]; const Base::Vector3f& p2 = _aclPointArray[rclFacet._aulPoints[2]]; - return Base::Vector3f((p0.x + p1.x + p2.x) / 3.0f, - (p0.y + p1.y + p2.y) / 3.0f, - (p0.z + p1.z + p2.z) / 3.0f); + return Base::Vector3f((p0.x + p1.x + p2.x) / 3.0F, + (p0.y + p1.y + p2.y) / 3.0F, + (p0.z + p1.z + p2.z) / 3.0F); } inline void MeshKernel::GetFacetPoints(FacetIndex ulFaIndex, diff --git a/src/Mod/Mesh/App/Core/Projection.cpp b/src/Mod/Mesh/App/Core/Projection.cpp index 0f660475413b..b3bd4d584e19 100644 --- a/src/Mod/Mesh/App/Core/Projection.cpp +++ b/src/Mod/Mesh/App/Core/Projection.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #include #endif @@ -69,7 +70,7 @@ bool MeshProjection::isPointInsideDistance(const Base::Vector3f& p1, Base::Vector3f move(pt - p1); proj.ProjectToLine(move, dir); proj = pt + proj; - return (((p1 - proj) * (p2 - proj)) < 0.0f); + return (((p1 - proj) * (p2 - proj)) < 0.0F); } bool MeshProjection::connectLines(std::list>& cutLines, @@ -77,8 +78,8 @@ bool MeshProjection::connectLines(std::list& polyline) const { - const float fMaxDist = float(sqrt(FLOAT_MAX)); // max. length of a gap - const float fMinEps = 1.0e-4f; + const float fMaxDist = float(std::sqrt(FLOAT_MAX)); // max. length of a gap + const float fMinEps = 1.0e-4F; polyline.clear(); polyline.push_back(startPoint); @@ -182,7 +183,7 @@ bool MeshProjection::projectLineOnMesh(const MeshFacetGrid& grid, } else { if (facet == f1) { // start facet - if (((e2 - v1) * dir) > 0.0f) { + if (((e2 - v1) * dir) > 0.0F) { cutLine.emplace_back(v1, e2); } else { @@ -193,7 +194,7 @@ bool MeshProjection::projectLineOnMesh(const MeshFacetGrid& grid, } if (facet == f2) { // end facet - if (((e2 - v2) * -dir) > 0.0f) { + if (((e2 - v2) * -dir) > 0.0F) { cutLine.emplace_back(v2, e2); } else { diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 9e30640d9f64..569de82d222c 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #endif #include "Algorithm.h" @@ -93,7 +94,7 @@ bool MeshDistancePlanarSegment::TestFacet(const MeshFacet& face) const } MeshGeomFacet triangle = kernel.GetFacet(face); for (auto pnt : triangle._aclPoints) { - if (fabs(fitter->GetDistanceToPlane(pnt)) > tolerance) { + if (std::fabs(fitter->GetDistanceToPlane(pnt)) > tolerance) { return false; } } @@ -156,9 +157,8 @@ bool PlaneSurfaceFit::Done() const if (!fitter) { return true; } - else { - return fitter->Done(); - } + + return fitter->Done(); } float PlaneSurfaceFit::Fit() @@ -166,9 +166,8 @@ float PlaneSurfaceFit::Fit() if (!fitter) { return 0; } - else { - return fitter->Fit(); - } + + return fitter->Fit(); } float PlaneSurfaceFit::GetDistanceToSurface(const Base::Vector3f& pnt) const @@ -176,9 +175,8 @@ float PlaneSurfaceFit::GetDistanceToSurface(const Base::Vector3f& pnt) const if (!fitter) { return pnt.DistanceToPlane(basepoint, normal); } - else { - return fitter->GetDistanceToPlane(pnt); - } + + return fitter->GetDistanceToPlane(pnt); } std::vector PlaneSurfaceFit::Parameters() const @@ -249,7 +247,7 @@ bool CylinderSurfaceFit::TestTriangle(const MeshGeomFacet& tria) const // This is to filter out triangles whose points lie on the cylinder and // that whose normals are more or less parallel to the cylinder axis float dot = axis.Dot(tria.GetNormal()); - return fabs(dot) < 0.5f; + return std::fabs(dot) < 0.5F; } bool CylinderSurfaceFit::Done() const @@ -424,7 +422,7 @@ bool MeshDistanceGenericSurfaceFitSegment::TestInitialFacet(FacetIndex index) co { MeshGeomFacet triangle = kernel.GetFacet(index); for (auto pnt : triangle._aclPoints) { - if (fabs(fitter->GetDistanceToSurface(pnt)) > tolerance) { + if (std::fabs(fitter->GetDistanceToSurface(pnt)) > tolerance) { return false; } } @@ -438,7 +436,7 @@ bool MeshDistanceGenericSurfaceFitSegment::TestFacet(const MeshFacet& face) cons } MeshGeomFacet triangle = kernel.GetFacet(face); for (auto ptIndex : triangle._aclPoints) { - if (fabs(fitter->GetDistanceToSurface(ptIndex)) > tolerance) { + if (std::fabs(fitter->GetDistanceToSurface(ptIndex)) > tolerance) { return false; } } @@ -463,10 +461,10 @@ bool MeshCurvaturePlanarSegment::TestFacet(const MeshFacet& rclFacet) const { for (PointIndex ptIndex : rclFacet._aulPoints) { const CurvatureInfo& ci = GetInfo(ptIndex); - if (fabs(ci.fMinCurvature) > tolerance) { + if (std::fabs(ci.fMinCurvature) > tolerance) { return false; } - if (fabs(ci.fMaxCurvature) > tolerance) { + if (std::fabs(ci.fMaxCurvature) > tolerance) { return false; } } @@ -478,12 +476,12 @@ bool MeshCurvatureCylindricalSegment::TestFacet(const MeshFacet& rclFacet) const { for (PointIndex ptIndex : rclFacet._aulPoints) { const CurvatureInfo& ci = GetInfo(ptIndex); - float fMax = std::max(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); - float fMin = std::min(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); + float fMax = std::max(std::fabs(ci.fMaxCurvature), std::fabs(ci.fMinCurvature)); + float fMin = std::min(std::fabs(ci.fMaxCurvature), std::fabs(ci.fMinCurvature)); if (fMin > toleranceMin) { return false; } - if (fabs(fMax - curvature) > toleranceMax) { + if (std::fabs(fMax - curvature) > toleranceMax) { return false; } } @@ -499,12 +497,12 @@ bool MeshCurvatureSphericalSegment::TestFacet(const MeshFacet& rclFacet) const return false; } float diff {}; - diff = fabs(ci.fMinCurvature) - curvature; - if (fabs(diff) > tolerance) { + diff = std::fabs(ci.fMinCurvature) - curvature; + if (std::fabs(diff) > tolerance) { return false; } - diff = fabs(ci.fMaxCurvature) - curvature; - if (fabs(diff) > tolerance) { + diff = std::fabs(ci.fMaxCurvature) - curvature; + if (std::fabs(diff) > tolerance) { return false; } } @@ -516,10 +514,10 @@ bool MeshCurvatureFreeformSegment::TestFacet(const MeshFacet& rclFacet) const { for (PointIndex ptIndex : rclFacet._aulPoints) { const CurvatureInfo& ci = GetInfo(ptIndex); - if (fabs(ci.fMinCurvature - c2) > toleranceMin) { + if (std::fabs(ci.fMinCurvature - c2) > toleranceMin) { return false; } - if (fabs(ci.fMaxCurvature - c1) > toleranceMax) { + if (std::fabs(ci.fMaxCurvature - c1) > toleranceMax) { return false; } } diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index f02dc0eae566..9dac6168705b 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -100,13 +100,13 @@ class MeshExport MeshDistancePlanarSegment: public MeshDistanceSurfaceSegment MeshDistancePlanarSegment& operator=(const MeshDistancePlanarSegment&) = delete; MeshDistancePlanarSegment& operator=(MeshDistancePlanarSegment&&) = delete; - bool TestFacet(const MeshFacet& rclFacet) const override; + bool TestFacet(const MeshFacet& face) const override; const char* GetType() const override { return "Plane"; } void Initialize(FacetIndex) override; - void AddFacet(const MeshFacet& rclFacet) override; + void AddFacet(const MeshFacet& face) override; private: Base::Vector3f basepoint; @@ -242,14 +242,14 @@ class MeshExport MeshDistanceGenericSurfaceFitSegment: public MeshDistanceSurfac MeshDistanceGenericSurfaceFitSegment& operator=(MeshDistanceGenericSurfaceFitSegment&&) = delete; - bool TestFacet(const MeshFacet& rclFacet) const override; + bool TestFacet(const MeshFacet& face) const override; const char* GetType() const override { return fitter->GetType(); } void Initialize(FacetIndex) override; bool TestInitialFacet(FacetIndex) const override; - void AddFacet(const MeshFacet& rclFacet) override; + void AddFacet(const MeshFacet& face) override; std::vector Parameters() const; private: diff --git a/src/Mod/Mesh/App/Core/SetOperations.cpp b/src/Mod/Mesh/App/Core/SetOperations.cpp index 89117aee42d8..e19987fee007 100644 --- a/src/Mod/Mesh/App/Core/SetOperations.cpp +++ b/src/Mod/Mesh/App/Core/SetOperations.cpp @@ -59,9 +59,9 @@ SetOperations::SetOperations(const MeshKernel& cutMesh1, void SetOperations::Do() { - _minDistanceToPoint = 0.000001f; + _minDistanceToPoint = 0.000001F; float saveMinMeshDistance = MeshDefinitions::_fMinPointDistance; - MeshDefinitions::SetMinPointDistance(0.000001f); + MeshDefinitions::SetMinPointDistance(0.000001F); // Base::Sequencer().start("set operation", 5); @@ -117,28 +117,28 @@ void SetOperations::Do() float mult0 {}, mult1 {}; switch (_operationType) { case Union: - mult0 = -1.0f; - mult1 = -1.0f; + mult0 = -1.0F; + mult1 = -1.0F; break; case Intersect: - mult0 = 1.0f; - mult1 = 1.0f; + mult0 = 1.0F; + mult1 = 1.0F; break; case Difference: - mult0 = -1.0f; - mult1 = 1.0f; + mult0 = -1.0F; + mult1 = 1.0F; break; case Inner: - mult0 = 1.0f; - mult1 = 0.0f; + mult0 = 1.0F; + mult1 = 0.0F; break; case Outer: - mult0 = -1.0f; - mult1 = 0.0f; + mult0 = -1.0F; + mult1 = 0.0F; break; default: - mult0 = 0.0f; - mult1 = 0.0f; + mult0 = 0.0F; + mult1 = 0.0F; break; } @@ -279,15 +279,14 @@ void SetOperations::Cut(std::set& facetsCuttingEdge0, _facet2points[1][fidx2].push_back(pit.first); } } - - } // if (f1.IntersectWithFacet(f2, p0, p1)) - } // for (it2 = vecFacets2.begin(); it2 != vecFacets2.end(); ++it2) - } // for (it1 = vecFacets1.begin(); it1 != vecFacets1.end(); ++it1) - } // if (vecFacets2.size() > 0) - } // if (grid1.GetCtElements(gx1, gy1, gz1) > 0) - } // for (gz1 = 0; gz1 < ctGz1; gz1++) - } // for (gy1 = 0; gy1 < ctGy1; gy1++) - } // for (gx1 = 0; gx1 < ctGx1; gx1++) + } + } + } + } + } + } + } + } } void SetOperations::TriangulateMesh(const MeshKernel& cutMesh, int side) @@ -387,15 +386,14 @@ void SetOperations::TriangulateMesh(const MeshKernel& cutMesh, int side) // } facet.CalcNormal(); - if ((facet.GetNormal() * f.GetNormal()) < 0.0f) { // adjust normal + if ((facet.GetNormal() * f.GetNormal()) < 0.0F) { // adjust normal std::swap(facet._aclPoints[0], facet._aclPoints[1]); facet.CalcNormal(); } for (int j = 0; j < 3; j++) { - std::map::iterator eit = - _edges.find(Edge(facet._aclPoints[j], facet._aclPoints[(j + 1) % 3])); + auto eit = _edges.find(Edge(facet._aclPoints[j], facet._aclPoints[(j + 1) % 3])); if (eit != _edges.end()) { @@ -414,9 +412,8 @@ void SetOperations::TriangulateMesh(const MeshKernel& cutMesh, int side) } _newMeshFacets[side].push_back(facet); - - } // for (i = 0; i < (out->numberoftriangles * 3); i += 3) - } // for (it1 = _facet2points[side].begin(); it1 != _facet2points[side].end(); ++it1) + } + } } void SetOperations::CollectFacets(int side, float mult) @@ -531,7 +528,7 @@ bool SetOperations::CollectFacetVisitor::AllowVisit(const MeshFacet& rclFacet, // Vector3f dir = ocDir % normal; // Vector3f dirOther = ocDirOther % normalOther; - bool match = ((ocDir * normalOther) * _mult) < 0.0f; + bool match = ((ocDir * normalOther) * _mult) < 0.0F; // if (matchCounter == 1) //{ @@ -625,11 +622,7 @@ bool MeshIntersection::hasIntersection() const return false; } - if (testIntersection(kernel1, kernel2)) { - return true; - } - - return false; + return (testIntersection(kernel1, kernel2)); } void MeshIntersection::getIntersection(std::list& intsct) const @@ -661,7 +654,7 @@ void MeshIntersection::getIntersection(std::list& intsc Base::Vector3f pt1, pt2; // Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh - for (MeshFacetArray::_TConstIterator it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { + for (auto it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { seq.next(); std::vector elements; cMeshFacetGrid.Inside(boxes2[index], elements, true); @@ -713,7 +706,7 @@ bool MeshIntersection::testIntersection(const MeshKernel& k1, const MeshKernel& Base::Vector3f pt1, pt2; // Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh - for (MeshFacetArray::_TConstIterator it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { + for (auto it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) { seq.next(); std::vector elements; cMeshFacetGrid.Inside(boxes2[index], elements, true); @@ -793,7 +786,7 @@ void MeshIntersection::connectLines(bool onlyclosed, bEndFirst = false; } - if (fFrontMin == 0.0f || fEndMin == 0.0f) { + if (fFrontMin == 0.0F || fEndMin == 0.0F) { break; } } diff --git a/src/Mod/Mesh/App/Core/SetOperations.h b/src/Mod/Mesh/App/Core/SetOperations.h index 4c31f8cba5bc..b8d23a6ed572 100644 --- a/src/Mod/Mesh/App/Core/SetOperations.h +++ b/src/Mod/Mesh/App/Core/SetOperations.h @@ -67,7 +67,7 @@ class MeshExport SetOperations const MeshKernel& cutMesh2, MeshKernel& result, OperationType opType, - float minDistanceToPoint = 1e-5f); + float minDistanceToPoint = 1e-5F); public: /** Cut this mesh with another one. The result is a list of polylines @@ -182,7 +182,7 @@ class MeshExport SetOperations std::vector _newMeshFacets[2]; /** Cut mesh 1 with mesh 2 */ - void Cut(std::set& facetsNotCuttingEdge0, std::set& facetsCuttingEdge1); + void Cut(std::set& facetsCuttingEdge0, std::set& facetsCuttingEdge1); /** Trianglute each facets cut with its cutting points */ void TriangulateMesh(const MeshKernel& cutMesh, int side); /** search facets for adding (with region growing) */ diff --git a/src/Mod/Mesh/App/Core/Smoothing.cpp b/src/Mod/Mesh/App/Core/Smoothing.cpp index 9c6672e1edd8..195bc5fa7e77 100644 --- a/src/Mod/Mesh/App/Core/Smoothing.cpp +++ b/src/Mod/Mesh/App/Core/Smoothing.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include @@ -76,7 +79,7 @@ void PlaneFitSmoothing::Smooth(unsigned int iterations) center += v_beg[*cv_it]; } - float scale = 1.0f / (static_cast(cv.size()) + 1.0f); + float scale = 1.0F / (static_cast(cv.size()) + 1.0F); center.Scale(scale, scale, scale); // get the mean plane of the current vertex with the surrounding vertices @@ -86,12 +89,12 @@ void PlaneFitSmoothing::Smooth(unsigned int iterations) // look in which direction we should move the vertex L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z); - if (N * L < 0.0f) { + if (N * L < 0.0F) { N.Scale(-1.0, -1.0, -1.0); } // maximum value to move is distance to mean plane - float d = std::min(fabs(this->maximum), fabs(N * L)); + float d = std::min(std::fabs(this->maximum), fabs(N * L)); N.Scale(d, d, d); PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z); @@ -133,7 +136,7 @@ void PlaneFitSmoothing::SmoothPoints(unsigned int iterations, center += v_beg[*cv_it]; } - float scale = 1.0f / (static_cast(cv.size()) + 1.0f); + float scale = 1.0F / (static_cast(cv.size()) + 1.0F); center.Scale(scale, scale, scale); // get the mean plane of the current vertex with the surrounding vertices @@ -143,12 +146,12 @@ void PlaneFitSmoothing::SmoothPoints(unsigned int iterations, // look in which direction we should move the vertex L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z); - if (N * L < 0.0f) { + if (N * L < 0.0F) { N.Scale(-1.0, -1.0, -1.0); } // maximum value to move is distance to mean plane - float d = std::min(fabs(this->maximum), fabs(N * L)); + float d = std::min(std::fabs(this->maximum), fabs(N * L)); N.Scale(d, d, d); PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z); @@ -309,14 +312,12 @@ inline Base::Vector3d find_median(std::vector& container) if ((container.size() % 2) == 1) { return container[n].second; } - else { - // even sized vector -> average the two middle values - auto max_it = - std::max_element(container.begin(), container.begin() + n, compare_angle_normal); - Base::Vector3d vec = (max_it->second + container[n].second) / 2.0; - vec.Normalize(); - return vec; - } + + // even sized vector -> average the two middle values + auto max_it = std::max_element(container.begin(), container.begin() + n, compare_angle_normal); + Base::Vector3d vec = (max_it->second + container[n].second) / 2.0; + vec.Normalize(); + return vec; } } // namespace diff --git a/src/Mod/Mesh/App/Core/SphereFit.cpp b/src/Mod/Mesh/App/Core/SphereFit.cpp index c455192958c1..7c7c1ebaad03 100644 --- a/src/Mod/Mesh/App/Core/SphereFit.cpp +++ b/src/Mod/Mesh/App/Core/SphereFit.cpp @@ -68,9 +68,8 @@ double SphereFit::GetRadius() const if (_bIsFitted) { return _dRadius; } - else { - return 0.0; - } + + return 0.0; } Base::Vector3d SphereFit::GetCenter() const @@ -78,9 +77,8 @@ Base::Vector3d SphereFit::GetCenter() const if (_bIsFitted) { return _vCenter; } - else { - return Base::Vector3d(); - } + + return Base::Vector3d(); } int SphereFit::GetNumIterations() const @@ -88,9 +86,8 @@ int SphereFit::GetNumIterations() const if (_bIsFitted) { return _numIter; } - else { - return 0; - } + + return 0; } float SphereFit::GetDistanceToSphere(const Base::Vector3f& rcPoint) const @@ -270,8 +267,7 @@ void SphereFit::setupNormalEquationMatrices(const std::vector& r double a[4] {}, b[3] {}; double f0 {}, qw {}; std::vector::const_iterator vIt = residuals.begin(); - std::list::const_iterator cIt; - for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { + for (auto cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { // if (using this point) { // currently all given points are used (could modify this if // eliminating outliers, etc.... setupObservation(*cIt, *vIt, a, f0, qw, b); @@ -384,8 +380,7 @@ bool SphereFit::computeResiduals(const Eigen::VectorXd& x, // double maxdVz = 0.0; // double rmsVv = 0.0; std::vector::iterator vIt = residuals.begin(); - std::list::const_iterator cIt; - for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { + for (auto cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt, ++vIt) { // if (using this point) { // currently all given points are used (could modify this if // eliminating outliers, etc.... ++nPtsUsed; diff --git a/src/Mod/Mesh/App/Core/Tools.cpp b/src/Mod/Mesh/App/Core/Tools.cpp index df8cf28d6160..f7fac2ade3cc 100644 --- a/src/Mod/Mesh/App/Core/Tools.cpp +++ b/src/Mod/Mesh/App/Core/Tools.cpp @@ -123,8 +123,7 @@ MeshSearchNeighbours::NeighboursFromFacet(FacetIndex ulFacetIdx, // copy points in result container raclResultPoints.resize(_aclResult.size()); size_t i = 0; - for (std::set::iterator pI = _aclResult.begin(); pI != _aclResult.end(); - ++pI, i++) { + for (auto pI = _aclResult.begin(); pI != _aclResult.end(); ++pI, i++) { raclResultPoints[i] = _rclPAry[*pI]; } @@ -272,9 +271,8 @@ bool MeshSearchNeighbours::ExpandRadius(unsigned long ulMinPoints) _fMaxDistanceP2 *= float(ulMinPoints) / float(_aclResult.size()); return true; } - else { - return false; - } + + return false; } unsigned long @@ -344,8 +342,7 @@ MeshSearchNeighbours::NeighboursFacetFromFacet(FacetIndex ulFacetIdx, // copy points in result container raclResultPoints.resize(_aclResult.size()); size_t i = 0; - for (std::set::iterator pI = _aclResult.begin(); pI != _aclResult.end(); - ++pI, i++) { + for (auto pI = _aclResult.begin(); pI != _aclResult.end(); ++pI, i++) { raclResultPoints[i] = _rclPAry[*pI]; } diff --git a/src/Mod/Mesh/App/Core/Tools.h b/src/Mod/Mesh/App/Core/Tools.h index 17f6d790c2b6..ab1a49bb9608 100644 --- a/src/Mod/Mesh/App/Core/Tools.h +++ b/src/Mod/Mesh/App/Core/Tools.h @@ -43,7 +43,7 @@ namespace MeshCore class MeshSearchNeighbours { public: - explicit MeshSearchNeighbours(const MeshKernel& rclM, float fSampleDistance = 1.0f); + explicit MeshSearchNeighbours(const MeshKernel& rclM, float fSampleDistance = 1.0F); ~MeshSearchNeighbours() = default; /** Re-initilaizes internal structures. */ void Reinit(float fSampleDistance); diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp index 8985138aa252..88d9bb0a620d 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include #include +#include #include #include #endif @@ -123,7 +124,7 @@ bool MeshTopoAlgorithm::SnapVertex(FacetIndex ulFacetPos, const Base::Vector3f& if (cNo3.Length() < FLOAT_EPS) { return SplitOpenEdge(ulFacetPos, i, rP); } - else if ((rP - rPt1) * cNo2 > 0.0f && fD2 >= fTV && fTV >= 0.0f) { + if ((rP - rPt1) * cNo2 > 0.0F && fD2 >= fTV && fTV >= 0.0F) { MeshFacet cTria; cTria._aulPoints[0] = this->GetOrAddIndex(rP); cTria._aulPoints[1] = rFace._aulPoints[(i + 1) % 3]; @@ -144,9 +145,7 @@ void MeshTopoAlgorithm::OptimizeTopology(float fMaxAngle) // For each internal edge get the adjacent facets. When doing an edge swap we must update // this structure. std::map, std::vector> aEdge2Face; - for (MeshFacetArray::_TIterator pI = _rclMesh._aclFacetArray.begin(); - pI != _rclMesh._aclFacetArray.end(); - ++pI) { + for (auto pI = _rclMesh._aclFacetArray.begin(); pI != _rclMesh._aclFacetArray.end(); ++pI) { for (int i = 0; i < 3; i++) { // ignore open edges if (pI->_aulNeighbours[i] != FACET_INDEX_MAX) { @@ -258,7 +257,7 @@ cos_maxangle(const Base::Vector3f& v1, const Base::Vector3f& v2, const Base::Vec float A = a * (b * b + c * c - a * a); float B = b * (c * c + a * a - b * b); float C = c * (a * a + b * b - c * c); - return 0.5f * std::min(std::min(A, B), C) + return 0.5F * std::min(std::min(A, B), C) / (a * b * c); // min cosine == max angle } @@ -269,8 +268,8 @@ static float swap_benefit(const Base::Vector3f& v1, { Base::Vector3f n124 = (v4 - v2) % (v1 - v2); Base::Vector3f n234 = (v3 - v2) % (v4 - v2); - if ((n124 * n234) <= 0.0f) { - return 0.0f; // avoid normal flip + if ((n124 * n234) <= 0.0F) { + return 0.0F; // avoid normal flip } return std::max(-cos_maxangle(v1, v2, v3), -cos_maxangle(v1, v3, v4)) @@ -284,7 +283,7 @@ float MeshTopoAlgorithm::SwapEdgeBenefit(FacetIndex f, int e) const FacetIndex n = faces[f]._aulNeighbours[e]; if (n == FACET_INDEX_MAX) { - return 0.0f; // border edge + return 0.0F; // border edge } PointIndex v1 = faces[f]._aulPoints[e]; @@ -294,13 +293,13 @@ float MeshTopoAlgorithm::SwapEdgeBenefit(FacetIndex f, int e) const if (s == USHRT_MAX) { std::cerr << "MeshTopoAlgorithm::SwapEdgeBenefit: error in neighbourhood " << "of faces " << f << " and " << n << std::endl; - return 0.0f; // topological error + return 0.0F; // topological error } PointIndex v4 = faces[n]._aulPoints[(s + 2) % 3]; if (v3 == v4) { std::cerr << "MeshTopoAlgorithm::SwapEdgeBenefit: duplicate faces " << f << " and " << n << std::endl; - return 0.0f; // duplicate faces + return 0.0F; // duplicate faces } return swap_benefit(vertices[v2], vertices[v3], vertices[v1], vertices[v4]); } @@ -318,7 +317,7 @@ void MeshTopoAlgorithm::OptimizeTopology() for (FacetIndex i = 0; i < nf; i++) { for (int j = 0; j < 3; j++) { float b = SwapEdgeBenefit(i, j); - if (b > 0.0f) { + if (b > 0.0F) { todo.push(std::make_pair(b, std::make_pair(i, j))); } } @@ -330,7 +329,7 @@ void MeshTopoAlgorithm::OptimizeTopology() int e = todo.top().second.second; todo.pop(); // Check again if the swap should still be done - if (SwapEdgeBenefit(f, e) <= 0.0f) { + if (SwapEdgeBenefit(f, e) <= 0.0F) { continue; } // OK, swap the edge @@ -339,13 +338,13 @@ void MeshTopoAlgorithm::OptimizeTopology() // Insert new edges into queue, if necessary for (int j = 0; j < 3; j++) { float b = SwapEdgeBenefit(f, j); - if (b > 0.0f) { + if (b > 0.0F) { todo.push(std::make_pair(b, std::make_pair(f, j))); } } for (int j = 0; j < 3; j++) { float b = SwapEdgeBenefit(f2, j); - if (b > 0.0f) { + if (b > 0.0F) { todo.push(std::make_pair(b, std::make_pair(f2, j))); } } @@ -357,8 +356,7 @@ void MeshTopoAlgorithm::DelaunayFlip(float fMaxAngle) // For each internal edge get the adjacent facets. std::set> aEdge2Face; FacetIndex index = 0; - for (MeshFacetArray::_TIterator pI = _rclMesh._aclFacetArray.begin(); - pI != _rclMesh._aclFacetArray.end(); + for (auto pI = _rclMesh._aclFacetArray.begin(); pI != _rclMesh._aclFacetArray.end(); ++pI, index++) { for (FacetIndex nbIndex : pI->_aulNeighbours) { // ignore open edges @@ -466,7 +464,7 @@ void MeshTopoAlgorithm::AdjustEdgesToCurvatureDirection() // Build map of edges to the referencing facets FacetIndex k = 0; std::map, std::list> aclEdgeMap; - for (std::vector::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt, k++) { + for (auto jt = raFts.begin(); jt != raFts.end(); ++jt, k++) { for (int i = 0; i < 3; i++) { PointIndex ulT0 = jt->_aulPoints[i]; PointIndex ulT1 = jt->_aulPoints[(i + 1) % 3]; @@ -479,9 +477,9 @@ void MeshTopoAlgorithm::AdjustEdgesToCurvatureDirection() // compute vertex based curvatures Wm4::MeshCurvature meshCurv(static_cast(_rclMesh.CountPoints()), - &(aPnts[0]), + aPnts.data(), static_cast(_rclMesh.CountFacets()), - &(aIdx[0])); + aIdx.data()); // get curvature information now const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); @@ -512,7 +510,7 @@ void MeshTopoAlgorithm::AdjustEdgesToCurvatureDirection() Wm4::Vector3 dir; float fActCurvature {}; - if (fabs(aMinCurv[uPt1]) > fabs(aMaxCurv[uPt1])) { + if (std::fabs(aMinCurv[uPt1]) > std::fabs(aMaxCurv[uPt1])) { fActCurvature = aMinCurv[uPt1]; dir = aMaxCurvDir[uPt1]; } @@ -536,8 +534,8 @@ void MeshTopoAlgorithm::AdjustEdgesToCurvatureDirection() float fLength12 = Base::Distance(raPts[uPt1], raPts[uPt2]); float fLength34 = Base::Distance(raPts[uPt3], raPts[uPt4]); if (fabs(cEdgeDir1 * cMinDir) < fabs(cEdgeDir2 * cMinDir)) { - if (IsSwapEdgeLegal(uFt1, uFt2) && fLength34 < 1.05f * fLength12 - && fActCurvature * fDist > 0.0f) { + if (IsSwapEdgeLegal(uFt1, uFt2) && fLength34 < 1.05F * fLength12 + && fActCurvature * fDist > 0.0F) { SwapEdge(uFt1, uFt2); rFace1.SetFlag(MeshFacet::VISIT); rFace2.SetFlag(MeshFacet::VISIT); @@ -627,12 +625,12 @@ bool MeshTopoAlgorithm::IsSwapEdgeLegal(FacetIndex ulFacetPos, FacetIndex ulNeig Base::Vector3f cV = cP4 - cP3; // build a helper plane through cP1 that must separate cP3 and cP4 Base::Vector3f cN1 = (cU % cV) % cU; - if (((cP3 - cP1) * cN1) * ((cP4 - cP1) * cN1) >= 0.0f) { + if (((cP3 - cP1) * cN1) * ((cP4 - cP1) * cN1) >= 0.0F) { return false; // not convex } // build a helper plane through cP3 that must separate cP1 and cP2 Base::Vector3f cN2 = (cU % cV) % cV; - if (((cP1 - cP3) * cN2) * ((cP2 - cP3) * cN2) >= 0.0f) { + if (((cP1 - cP3) * cN2) * ((cP2 - cP3) * cN2) >= 0.0F) { return false; // not convex } @@ -818,13 +816,13 @@ bool MeshTopoAlgorithm::SplitOpenEdge(FacetIndex ulFacetPos, bool MeshTopoAlgorithm::Vertex_Less::operator()(const Base::Vector3f& u, const Base::Vector3f& v) const { - if (fabs(u.x - v.x) > FLOAT_EPS) { + if (std::fabs(u.x - v.x) > FLOAT_EPS) { return u.x < v.x; } - if (fabs(u.y - v.y) > FLOAT_EPS) { + if (std::fabs(u.y - v.y) > FLOAT_EPS) { return u.y < v.y; } - if (fabs(u.z - v.z) > FLOAT_EPS) { + if (std::fabs(u.z - v.z) > FLOAT_EPS) { return u.z < v.z; } return false; @@ -832,9 +830,7 @@ bool MeshTopoAlgorithm::Vertex_Less::operator()(const Base::Vector3f& u, void MeshTopoAlgorithm::BeginCache() { - if (_cache) { - delete _cache; - } + delete _cache; _cache = new tCache(); PointIndex nbPoints = _rclMesh._aclPointArray.size(); for (unsigned int pntCpt = 0; pntCpt < nbPoints; ++pntCpt) { @@ -1073,7 +1069,7 @@ bool MeshTopoAlgorithm::IsCollapseEdgeLegal(const EdgeCollapse& ec) const f.Transpose(ec._fromPoint, ec._toPoint); MeshGeomFacet tria2 = _rclMesh.GetFacet(f); - if (tria1.GetNormal() * tria2.GetNormal() < 0.0f) { + if (tria1.GetNormal() * tria2.GetNormal() < 0.0F) { return false; } } @@ -1271,7 +1267,7 @@ void MeshTopoAlgorithm::SplitFacetOnOneEdge(FacetIndex ulFacetPos, const Base::V } } - if (fMinDist < 0.05f) { + if (fMinDist < 0.05F) { if (rFace._aulNeighbours[iEdgeNo] != FACET_INDEX_MAX) { SplitEdge(ulFacetPos, rFace._aulNeighbours[iEdgeNo], rP); } @@ -1307,7 +1303,7 @@ void MeshTopoAlgorithm::SplitFacetOnTwoEdges(FacetIndex ulFacetPos, } } - if (iEdgeNo1 == iEdgeNo2 || fMinDist1 >= 0.05f || fMinDist2 >= 0.05f) { + if (iEdgeNo1 == iEdgeNo2 || fMinDist1 >= 0.05F || fMinDist2 >= 0.05F) { return; // no valid configuration } @@ -1472,7 +1468,7 @@ void MeshTopoAlgorithm::HarmonizeNeighbours(FacetIndex facet1, FacetIndex facet2 void MeshTopoAlgorithm::SplitNeighbourFacet(FacetIndex ulFacetPos, unsigned short uFSide, - const Base::Vector3f rPoint) + const Base::Vector3f& rPoint) { MeshFacet& rclF = _rclMesh._aclFacetArray[ulFacetPos]; @@ -1570,7 +1566,7 @@ bool MeshTopoAlgorithm::RemoveDegeneratedFacet(FacetIndex index) - _rclMesh._aclPointArray[rFace._aulPoints[j]]; // adjust the neighbourhoods and point indices - if (cVec1 * cVec2 < 0.0f) { + if (cVec1 * cVec2 < 0.0F) { FacetIndex uN1 = rFace._aulNeighbours[(j + 1) % 3]; if (uN1 != FACET_INDEX_MAX) { // get the neighbour and common edge side @@ -1785,9 +1781,7 @@ void MeshTopoAlgorithm::HarmonizeNormals() void MeshTopoAlgorithm::FlipNormals() { - for (MeshFacetArray::_TIterator i = _rclMesh._aclFacetArray.begin(); - i < _rclMesh._aclFacetArray.end(); - ++i) { + for (auto i = _rclMesh._aclFacetArray.begin(); i < _rclMesh._aclFacetArray.end(); ++i) { i->FlipNormal(); } } diff --git a/src/Mod/Mesh/App/Core/TopoAlgorithm.h b/src/Mod/Mesh/App/Core/TopoAlgorithm.h index 108ff019176e..91f6cd8ec3c7 100644 --- a/src/Mod/Mesh/App/Core/TopoAlgorithm.h +++ b/src/Mod/Mesh/App/Core/TopoAlgorithm.h @@ -262,7 +262,7 @@ class MeshExport MeshTopoAlgorithm * Find topologic independent components with maximum \a count facets * and returns an array of the indices. */ - void FindComponents(unsigned long count, std::vector& aInds); + void FindComponents(unsigned long count, std::vector& findIndices); /** * Removes topologic independent components with maximum \a count facets. */ @@ -286,7 +286,7 @@ class MeshExport MeshTopoAlgorithm * Splits the neighbour facet of \a ulFacetPos on side \a uSide. */ void - SplitNeighbourFacet(FacetIndex ulFacetPos, unsigned short uSide, const Base::Vector3f rPoint); + SplitNeighbourFacet(FacetIndex ulFacetPos, unsigned short uFSide, const Base::Vector3f& rPoint); void SplitFacetOnOneEdge(FacetIndex ulFacetPos, const Base::Vector3f& rP1); void SplitFacetOnTwoEdges(FacetIndex ulFacetPos, const Base::Vector3f& rP1, @@ -315,7 +315,7 @@ class MeshExport MeshTopoAlgorithm struct Vertex_Less { - bool operator()(const Base::Vector3f& x, const Base::Vector3f& y) const; + bool operator()(const Base::Vector3f& u, const Base::Vector3f& v) const; }; // cache diff --git a/src/Mod/Mesh/App/Core/Triangulation.cpp b/src/Mod/Mesh/App/Core/Triangulation.cpp index 11c6c144ca61..f78a00ec4210 100644 --- a/src/Mod/Mesh/App/Core/Triangulation.cpp +++ b/src/Mod/Mesh/App/Core/Triangulation.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif @@ -44,12 +45,12 @@ bool TriangulationVerifier::Accept(const Base::Vector3f& n, { float ref_dist = (p2 - p1) * n; float tri_dist = (p3 - p1) * n; - return (ref_dist * tri_dist <= 0.0f); + return (ref_dist * tri_dist <= 0.0F); } bool TriangulationVerifier::MustFlip(const Base::Vector3f& n1, const Base::Vector3f& n2) const { - return n1.Dot(n2) <= 0.0f; + return n1.Dot(n2) <= 0.0F; } bool TriangulationVerifierV2::Accept(const Base::Vector3f& n, @@ -111,10 +112,9 @@ std::vector AbstractPolygonTriangulator::GetPolygon() const float AbstractPolygonTriangulator::GetLength() const { - float len = 0.0f; + float len = 0.0F; if (_points.size() > 2) { - for (std::vector::const_iterator it = _points.begin(); it != _points.end(); - ++it) { + for (auto it = _points.begin(); it != _points.end(); ++it) { std::vector::const_iterator jt = it + 1; if (jt == _points.end()) { jt = _points.begin(); @@ -336,12 +336,12 @@ float EarClippingTriangulator::Triangulate::Area(const std::vector, std::vector> aEdge2Face; - for (std::vector::iterator pI = _facets.begin(); pI != _facets.end(); ++pI) { + for (auto pI = _facets.begin(); pI != _facets.end(); ++pI) { for (int i = 0; i < 3; i++) { PointIndex ulPt0 = std::min(pI->_aulPoints[i], pI->_aulPoints[(i + 1) % 3]); PointIndex ulPt1 = std::max(pI->_aulPoints[i], pI->_aulPoints[(i + 1) % 3]); @@ -583,12 +583,12 @@ bool QuasiDelaunayTriangulator::Triangulate() Base::Vector3f cV = cP4 - cP3; // build a helper plane through cP1 that must separate cP3 and cP4 Base::Vector3f cN1 = (cU % cV) % cU; - if (((cP3 - cP1) * cN1) * ((cP4 - cP1) * cN1) >= 0.0f) { + if (((cP3 - cP1) * cN1) * ((cP4 - cP1) * cN1) >= 0.0F) { continue; // not convex } // build a helper plane through cP3 that must separate cP1 and cP2 Base::Vector3f cN2 = (cU % cV) % cV; - if (((cP1 - cP3) * cN2) * ((cP2 - cP3) * cN2) >= 0.0f) { + if (((cP1 - cP3) * cN2) * ((cP2 - cP3) * cN2) >= 0.0F) { continue; // not convex } @@ -655,25 +655,23 @@ struct Vertex2d_Less { bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const { - if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1) { - if (fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) { return false; } - else { - return p.y < q.y; - } - } - else { - return p.x < q.x; + + return p.y < q.y; } + + return p.x < q.x; } }; struct Vertex2d_EqualTo { bool operator()(const Base::Vector3f& p, const Base::Vector3f& q) const { - if (fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1 - && fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) { + if (std::fabs(p.x - q.x) < MeshDefinitions::_fMinPointDistanceD1 + && std::fabs(p.y - q.y) < MeshDefinitions::_fMinPointDistanceD1) { return true; } @@ -708,17 +706,18 @@ bool DelaunayTriangulator::Triangulate() } Wm4::Delaunay2d del(static_cast(akVertex.size()), - &(akVertex[0]), + akVertex.data(), 0.001, false, Wm4::Query::QT_INT64); int iTQuantity = del.GetSimplexQuantity(); - std::vector aiTVertex(static_cast(3 * iTQuantity)); + auto numFaces = static_cast(iTQuantity); + std::vector aiTVertex(3 * numFaces); bool succeeded = false; - if (iTQuantity > 0) { - size_t uiSize = static_cast(3 * iTQuantity) * sizeof(int); - Wm4::System::Memcpy(&(aiTVertex[0]), uiSize, del.GetIndices(), uiSize); + if (numFaces > 0) { + size_t uiSize = 3 * numFaces * sizeof(int); + Wm4::System::Memcpy(aiTVertex.data(), uiSize, del.GetIndices(), uiSize); // If H is the number of hull edges and N is the number of vertices, // then the triangulation must have 2*N-2-H triangles and 3*N-3-H @@ -737,9 +736,9 @@ bool DelaunayTriangulator::Triangulate() MeshGeomFacet triangle; MeshFacet facet; - for (int i = 0; i < iTQuantity; i++) { - for (int j = 0; j < 3; j++) { - size_t index = static_cast(aiTVertex[static_cast(3 * i + j)]); + for (std::size_t i = 0; i < numFaces; i++) { + for (std::size_t j = 0; j < 3; j++) { + auto index = static_cast(aiTVertex[3 * i + j]); facet._aulPoints[j] = static_cast(index); triangle._aclPoints[j].x = static_cast(akVertex[index].X()); triangle._aclPoints[j].y = static_cast(akVertex[index].Y()); diff --git a/src/Mod/Mesh/App/Core/Trim.cpp b/src/Mod/Mesh/App/Core/Trim.cpp index f48aa64bf0ca..f569acbc2e0d 100644 --- a/src/Mod/Mesh/App/Core/Trim.cpp +++ b/src/Mod/Mesh/App/Core/Trim.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #endif #include @@ -34,12 +35,12 @@ using namespace MeshCore; -MeshTrimming::MeshTrimming(MeshKernel& rclM, - const Base::ViewProjMethod* pclProj, - const Base::Polygon2d& rclPoly) - : myMesh(rclM) - , myProj(pclProj) - , myPoly(rclPoly) +MeshTrimming::MeshTrimming(MeshKernel& mesh, + const Base::ViewProjMethod* proj, + const Base::Polygon2d& poly) + : myMesh(mesh) + , myProj(proj) + , myPoly(poly) {} void MeshTrimming::SetInnerOrOuter(TMode tMode) @@ -117,9 +118,8 @@ bool MeshTrimming::HasIntersection(const MeshGeomFacet& rclFacet) const if (myPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) == myInner) { return true; } - else { - clPoly.Add(Base::Vector2d(clPt2d.x, clPt2d.y)); - } + + clPoly.Add(Base::Vector2d(clPt2d.x, clPt2d.y)); } // is corner of polygon inside the facet @@ -195,7 +195,7 @@ bool MeshTrimming::IsPolygonPointInFacet(FacetIndex ulIndex, Base::Vector3f& clP w = fDetPAB / fDetABC; // point is on edge or no valid convex combination - if (u == 0.0f || v == 0.0f || w == 0.0f || fabs(u + v + w - 1.0f) >= 0.001f) { + if (u == 0.0F || v == 0.0F || w == 0.0F || std::fabs(u + v + w - 1.0F) >= 0.001F) { return false; } // 3d point @@ -266,7 +266,7 @@ bool MeshTrimming::GetIntersectionPointsOfPolygonAndFacet( float s = fSP4 / fP3P4; // is intersection point convex combination? - if ((fabs(l + m - 1.0f) < 0.001f) && (fabs(r + s - 1.0f) < 0.001f)) { + if ((std::fabs(l + m - 1.0F) < 0.001F) && (std::fabs(r + s - 1.0F) < 0.001F)) { Base::Vector3f clIntersection(m * clFac._aclPoints[j] + l * clFac._aclPoints[(j + 1) % 3]); @@ -431,7 +431,7 @@ bool MeshTrimming::CreateFacets(FacetIndex ulFacetPos, aclNewFacets.push_back(clNew); break; } - else if (myPoly.Contains(P2) == myInner) { + if (myPoly.Contains(P2) == myInner) { MeshGeomFacet clNew; clNew._aclPoints[0] = raclPoints[0]; clNew._aclPoints[1] = clFac._aclPoints[(j + 2) % 3]; diff --git a/src/Mod/Mesh/App/Core/Trim.h b/src/Mod/Mesh/App/Core/Trim.h index 8ced23c795c6..4c067db2dbc9 100644 --- a/src/Mod/Mesh/App/Core/Trim.h +++ b/src/Mod/Mesh/App/Core/Trim.h @@ -44,9 +44,7 @@ class MeshExport MeshTrimming }; public: - MeshTrimming(MeshKernel& mesh, - const Base::ViewProjMethod* pclProj, - const Base::Polygon2d& rclPoly); + MeshTrimming(MeshKernel& mesh, const Base::ViewProjMethod* proj, const Base::Polygon2d& poly); public: /** diff --git a/src/Mod/Mesh/App/Core/TrimByPlane.cpp b/src/Mod/Mesh/App/Core/TrimByPlane.cpp index 0930725fdf28..6965dcfad6cb 100644 --- a/src/Mod/Mesh/App/Core/TrimByPlane.cpp +++ b/src/Mod/Mesh/App/Core/TrimByPlane.cpp @@ -32,8 +32,8 @@ using namespace MeshCore; -MeshTrimByPlane::MeshTrimByPlane(MeshKernel& rclM) - : myMesh(rclM) +MeshTrimByPlane::MeshTrimByPlane(MeshKernel& mesh) + : myMesh(mesh) {} void MeshTrimByPlane::CheckFacets(const MeshFacetGrid& rclGrid, @@ -53,7 +53,7 @@ void MeshTrimByPlane::CheckFacets(const MeshFacetGrid& rclGrid, // save all elements in checkElements clGridIter.GetElements(checkElements); } - else if (clBBox3d.CalcPoint(Base::BoundBox3f::TLB).DistanceToPlane(base, normal) > 0.0f) { + else if (clBBox3d.CalcPoint(Base::BoundBox3f::TLB).DistanceToPlane(base, normal) > 0.0F) { // save all elements in removeFacets clGridIter.GetElements(removeFacets); } @@ -71,7 +71,7 @@ void MeshTrimByPlane::CheckFacets(const MeshFacetGrid& rclGrid, trimFacets.push_back(element); removeFacets.push_back(element); } - else if (clFacet._aclPoints[0].DistanceToPlane(base, normal) > 0.0f) { + else if (clFacet._aclPoints[0].DistanceToPlane(base, normal) > 0.0F) { removeFacets.push_back(element); } } @@ -155,23 +155,23 @@ void MeshTrimByPlane::TrimFacets(const std::vector& trimFacets, float dist3 = facet._aclPoints[2].DistanceToPlane(base, normal); // only one point below - if (dist1 < 0.0f && dist2 > 0.0f && dist3 > 0.0f) { + if (dist1 < 0.0F && dist2 > 0.0F && dist3 > 0.0F) { CreateOneFacet(base, normal, 0, facet, trimmedFacets); } - else if (dist1 > 0.0f && dist2 < 0.0f && dist3 > 0.0f) { + else if (dist1 > 0.0F && dist2 < 0.0F && dist3 > 0.0F) { CreateOneFacet(base, normal, 1, facet, trimmedFacets); } - else if (dist1 > 0.0f && dist2 > 0.0f && dist3 < 0.0f) { + else if (dist1 > 0.0F && dist2 > 0.0F && dist3 < 0.0F) { CreateOneFacet(base, normal, 2, facet, trimmedFacets); } // two points below - else if (dist1 < 0.0f && dist2 < 0.0f && dist3 > 0.0f) { + else if (dist1 < 0.0F && dist2 < 0.0F && dist3 > 0.0F) { CreateTwoFacet(base, normal, 0, facet, trimmedFacets); } - else if (dist1 > 0.0f && dist2 < 0.0f && dist3 < 0.0f) { + else if (dist1 > 0.0F && dist2 < 0.0F && dist3 < 0.0F) { CreateTwoFacet(base, normal, 1, facet, trimmedFacets); } - else if (dist1 < 0.0f && dist2 > 0.0f && dist3 < 0.0f) { + else if (dist1 < 0.0F && dist2 > 0.0F && dist3 < 0.0F) { CreateTwoFacet(base, normal, 2, facet, trimmedFacets); } } diff --git a/src/Mod/Mesh/App/Core/Visitor.cpp b/src/Mod/Mesh/App/Core/Visitor.cpp index 04002243089a..de260b58c8b5 100644 --- a/src/Mod/Mesh/App/Core/Visitor.cpp +++ b/src/Mod/Mesh/App/Core/Visitor.cpp @@ -21,6 +21,9 @@ ***************************************************************************/ #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif #include "Algorithm.h" #include "Approximation.h" @@ -73,14 +76,13 @@ unsigned long MeshKernel::VisitNeighbourFacets(MeshFacetVisitor& rclFVisitor, if (clNBFacet->IsFlag(MeshFacet::VISIT)) { continue; // neighbour facet already visited } - else { - // visit and mark - ulVisited++; - clNextLevel.push_back(j); - clNBFacet->SetFlag(MeshFacet::VISIT); - if (!rclFVisitor.Visit(*clNBFacet, *clCurrFacet, j, ulLevel)) { - return ulVisited; - } + + // visit and mark + ulVisited++; + clNextLevel.push_back(j); + clNBFacet->SetFlag(MeshFacet::VISIT); + if (!rclFVisitor.Visit(*clNBFacet, *clCurrFacet, j, ulLevel)) { + return ulVisited; } } } @@ -111,8 +113,7 @@ unsigned long MeshKernel::VisitNeighbourFacetsOverCorners(MeshFacetVisitor& rclF while (!aclCurrentLevel.empty()) { // visit all neighbours of the current level - for (std::vector::iterator pCurrFacet = aclCurrentLevel.begin(); - pCurrFacet < aclCurrentLevel.end(); + for (auto pCurrFacet = aclCurrentLevel.begin(); pCurrFacet < aclCurrentLevel.end(); ++pCurrFacet) { for (int i = 0; i < 3; i++) { const MeshFacet& rclFacet = raclFAry[*pCurrFacet]; @@ -234,7 +235,7 @@ bool MeshPlaneVisitor::AllowVisit(const MeshFacet& face, } MeshGeomFacet triangle = mesh.GetFacet(face); for (const auto& pnt : triangle._aclPoints) { - if (fabs(fitter->GetDistanceToPlane(pnt)) > max_deviation) { + if (std::fabs(fitter->GetDistanceToPlane(pnt)) > max_deviation) { return false; } } diff --git a/src/Mod/Mesh/App/Core/Visitor.h b/src/Mod/Mesh/App/Core/Visitor.h index ce7d89563deb..64e88b484093 100644 --- a/src/Mod/Mesh/App/Core/Visitor.h +++ b/src/Mod/Mesh/App/Core/Visitor.h @@ -135,7 +135,7 @@ inline bool MeshSearchNeighbourFacetsVisitor::Visit(const MeshFacet& rclFacet, class MeshExport MeshTopFacetVisitor: public MeshFacetVisitor { public: - MeshTopFacetVisitor(std::vector& raulNB) + explicit MeshTopFacetVisitor(std::vector& raulNB) : _raulNeighbours(raulNB) {} ~MeshTopFacetVisitor() override = default; diff --git a/src/Mod/Mesh/App/Edge.cpp b/src/Mod/Mesh/App/Edge.cpp index 35deaaf83d0e..54c68e4f50db 100644 --- a/src/Mod/Mesh/App/Edge.cpp +++ b/src/Mod/Mesh/App/Edge.cpp @@ -66,14 +66,8 @@ Edge::~Edge() = default; Edge& Edge::operator=(const Edge& e) { - MeshCore::MeshGeomEdge::operator=(e); - Mesh = e.Mesh; - Index = e.Index; - for (int i = 0; i < 2; i++) { - PIndex[i] = e.PIndex[i]; - NIndex[i] = e.NIndex[i]; - } - + Edge c = e; + *this = std::move(c); return *this; } diff --git a/src/Mod/Mesh/App/Edge.h b/src/Mod/Mesh/App/Edge.h index dfc2cf8c33bd..c0eee7d9675c 100644 --- a/src/Mod/Mesh/App/Edge.h +++ b/src/Mod/Mesh/App/Edge.h @@ -51,8 +51,8 @@ class MeshExport Edge: public MeshCore::MeshGeomEdge return Index != -1; } void unbound(); - Edge& operator=(const Edge& f); - Edge& operator=(Edge&& f); + Edge& operator=(const Edge& e); + Edge& operator=(Edge&& e); int Index {-1}; MeshCore::PointIndex PIndex[2]; diff --git a/src/Mod/Mesh/App/EdgePyImp.cpp b/src/Mod/Mesh/App/EdgePyImp.cpp index a2bfd60669b0..ac9243acb07e 100644 --- a/src/Mod/Mesh/App/EdgePyImp.cpp +++ b/src/Mod/Mesh/App/EdgePyImp.cpp @@ -95,7 +95,7 @@ Py::Long EdgePy::getIndex() const PyObject* EdgePy::intersectWithEdge(PyObject* args) { - PyObject* object; + PyObject* object {}; if (!PyArg_ParseTuple(args, "O!", &EdgePy::Type, &object)) { return nullptr; } diff --git a/src/Mod/Mesh/App/Exporter.cpp b/src/Mod/Mesh/App/Exporter.cpp index 90c451362fcf..facaee57be36 100644 --- a/src/Mod/Mesh/App/Exporter.cpp +++ b/src/Mod/Mesh/App/Exporter.cpp @@ -393,17 +393,14 @@ class ExporterAMF::VertLess if (a.z == b.z) { return false; } - else { - return a.z < b.z; - } - } - else { - return a.y < b.y; + + return a.z < b.z; } + + return a.y < b.y; } - else { - return a.x < b.x; - } + + return a.x < b.x; } }; diff --git a/src/Mod/Mesh/App/Exporter.h b/src/Mod/Mesh/App/Exporter.h index 3085f7bba243..3f95fdee5f47 100644 --- a/src/Mod/Mesh/App/Exporter.h +++ b/src/Mod/Mesh/App/Exporter.h @@ -205,7 +205,7 @@ class MeshExport Extension3MFFactory class MeshExport Exporter3MF: public Exporter { public: - Exporter3MF(std::string fileName, const std::vector& = {}); + explicit Exporter3MF(std::string fileName, const std::vector& = {}); ~Exporter3MF() override; Exporter3MF(const Exporter3MF&) = delete; diff --git a/src/Mod/Mesh/App/Facet.cpp b/src/Mod/Mesh/App/Facet.cpp index bcbf6f8c4990..5664bf2e9d65 100644 --- a/src/Mod/Mesh/App/Facet.cpp +++ b/src/Mod/Mesh/App/Facet.cpp @@ -75,14 +75,8 @@ Facet::~Facet() = default; Facet& Facet::operator=(const Facet& f) { - MeshCore::MeshGeomFacet::operator=(f); - Mesh = f.Mesh; - Index = f.Index; - for (int i = 0; i < 3; i++) { - PIndex[i] = f.PIndex[i]; - NIndex[i] = f.NIndex[i]; - } - + Facet c = f; + *this = std::move(c); return *this; } diff --git a/src/Mod/Mesh/App/FacetPyImp.cpp b/src/Mod/Mesh/App/FacetPyImp.cpp index 61d85a6e6542..0f5c4b60da10 100644 --- a/src/Mod/Mesh/App/FacetPyImp.cpp +++ b/src/Mod/Mesh/App/FacetPyImp.cpp @@ -41,7 +41,7 @@ class Index FacetIndex index; public: - Index(FacetIndex index) + explicit Index(FacetIndex index) : index {index} {} diff --git a/src/Mod/Mesh/App/FeatureMeshDefects.cpp b/src/Mod/Mesh/App/FeatureMeshDefects.cpp index fa00cd59cfbd..2a8c5de810e0 100644 --- a/src/Mod/Mesh/App/FeatureMeshDefects.cpp +++ b/src/Mod/Mesh/App/FeatureMeshDefects.cpp @@ -207,7 +207,7 @@ PROPERTY_SOURCE(Mesh::FixDeformations, Mesh::FixDefects) FixDeformations::FixDeformations() { - ADD_PROPERTY(MaxAngle, (5.0f)); + ADD_PROPERTY(MaxAngle, (5.0F)); } App::DocumentObjectExecReturn* FixDeformations::execute() @@ -260,7 +260,7 @@ PROPERTY_SOURCE(Mesh::FillHoles, Mesh::FixDefects) FillHoles::FillHoles() { ADD_PROPERTY(FillupHolesOfLength, (0)); - ADD_PROPERTY(MaxArea, (0.1f)); + ADD_PROPERTY(MaxArea, (0.1F)); } App::DocumentObjectExecReturn* FillHoles::execute() diff --git a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp index 814bf51fd5e5..f402424c98fe 100644 --- a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.cpp @@ -71,7 +71,7 @@ App::DocumentObjectExecReturn* SegmentByMesh::execute() if (!kernel) { return new App::DocumentObjectExecReturn("No mesh specified.\n"); } - else if (mesh->isError()) { + if (mesh->isError()) { return new App::DocumentObjectExecReturn("No valid mesh.\n"); } @@ -86,7 +86,7 @@ App::DocumentObjectExecReturn* SegmentByMesh::execute() if (!toolmesh) { return new App::DocumentObjectExecReturn("No toolmesh specified.\n"); } - else if (tool->isError()) { + if (tool->isError()) { return new App::DocumentObjectExecReturn("No valid toolmesh.\n"); } @@ -105,18 +105,17 @@ App::DocumentObjectExecReturn* SegmentByMesh::execute() } std::vector faces; - std::vector aFaces; MeshAlgorithm cAlg(rMeshKernel); - if (cNormal.Length() > 0.1f) { // not a null vector + if (cNormal.Length() > 0.1F) { // not a null vector cAlg.GetFacetsFromToolMesh(rToolMesh, cNormal, faces); } else { - cAlg.GetFacetsFromToolMesh(rToolMesh, Base::Vector3f(0.0, 1.0f, 0.0f), faces); + cAlg.GetFacetsFromToolMesh(rToolMesh, Base::Vector3f(0.0, 1.0F, 0.0F), faces); } // if the clipping plane was set then we want only the visible facets - if (cNormal.Length() > 0.1f) { // not a null vector + if (cNormal.Length() > 0.1F) { // not a null vector // now we have too many facets since we have (invisible) facets near to the back clipping // plane, so we need the nearest facet to the front clipping plane // @@ -149,6 +148,8 @@ App::DocumentObjectExecReturn* SegmentByMesh::execute() } } + std::vector aFaces; + aFaces.reserve(faces.size()); for (MeshCore::FacetIndex it : faces) { aFaces.push_back(rMeshKernel.GetFacet(it)); } diff --git a/src/Mod/Mesh/App/FeatureMeshSetOperations.cpp b/src/Mod/Mesh/App/FeatureMeshSetOperations.cpp index a764763d0c37..01dd37862bd7 100644 --- a/src/Mod/Mesh/App/FeatureMeshSetOperations.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSetOperations.cpp @@ -95,7 +95,7 @@ App::DocumentObjectExecReturn* SetOperations::execute() meshKernel2.getKernel(), pcKernel->getKernel(), type, - 1.0e-5f); + 1.0e-5F); setOp.Do(); Mesh.setValuePtr(pcKernel.release()); } diff --git a/src/Mod/Mesh/App/FeatureMeshSolid.cpp b/src/Mod/Mesh/App/FeatureMeshSolid.cpp index 3115cef31ec6..490428e5d233 100644 --- a/src/Mod/Mesh/App/FeatureMeshSolid.cpp +++ b/src/Mod/Mesh/App/FeatureMeshSolid.cpp @@ -58,14 +58,13 @@ App::DocumentObjectExecReturn* Sphere::execute() { std::unique_ptr mesh( MeshObject::createSphere((float)Radius.getValue(), Sampling.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create sphere", this); - } + + return new App::DocumentObjectExecReturn("Cannot create sphere", this); } void Sphere::handleChangedPropertyType(Base::XMLReader& reader, @@ -109,14 +108,13 @@ App::DocumentObjectExecReturn* Ellipsoid::execute() std::unique_ptr mesh(MeshObject::createEllipsoid((float)Radius1.getValue(), (float)Radius2.getValue(), Sampling.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create ellipsoid", this); - } + + return new App::DocumentObjectExecReturn("Cannot create ellipsoid", this); } void Ellipsoid::handleChangedPropertyType(Base::XMLReader& reader, @@ -167,14 +165,13 @@ App::DocumentObjectExecReturn* Cylinder::execute() Closed.getValue(), (float)EdgeLength.getValue(), Sampling.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create cylinder", this); - } + + return new App::DocumentObjectExecReturn("Cannot create cylinder", this); } void Cylinder::handleChangedPropertyType(Base::XMLReader& reader, @@ -228,14 +225,13 @@ App::DocumentObjectExecReturn* Cone::execute() Closed.getValue(), (float)EdgeLength.getValue(), Sampling.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create cone", this); - } + + return new App::DocumentObjectExecReturn("Cannot create cone", this); } void Cone::handleChangedPropertyType(Base::XMLReader& reader, @@ -280,14 +276,13 @@ App::DocumentObjectExecReturn* Torus::execute() std::unique_ptr mesh(MeshObject::createTorus((float)Radius1.getValue(), (float)Radius2.getValue(), Sampling.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create torus", this); - } + + return new App::DocumentObjectExecReturn("Cannot create torus", this); } void Torus::handleChangedPropertyType(Base::XMLReader& reader, @@ -311,9 +306,9 @@ PROPERTY_SOURCE(Mesh::Cube, Mesh::Feature) Cube::Cube() { - ADD_PROPERTY_TYPE(Length, (10.0f), "Cube", App::Prop_None, "The length of the cube"); - ADD_PROPERTY_TYPE(Width, (10.0f), "Cube", App::Prop_None, "The width of the cube"); - ADD_PROPERTY_TYPE(Height, (10.0f), "Cube", App::Prop_None, "The height of the cube"); + ADD_PROPERTY_TYPE(Length, (10.0F), "Cube", App::Prop_None, "The length of the cube"); + ADD_PROPERTY_TYPE(Width, (10.0F), "Cube", App::Prop_None, "The width of the cube"); + ADD_PROPERTY_TYPE(Height, (10.0F), "Cube", App::Prop_None, "The height of the cube"); Length.setConstraints(&floatRange); Width.setConstraints(&floatRange); Height.setConstraints(&floatRange); @@ -332,14 +327,13 @@ App::DocumentObjectExecReturn* Cube::execute() std::unique_ptr mesh(MeshObject::createCube((float)Length.getValue(), (float)Width.getValue(), (float)Height.getValue())); - if (mesh.get()) { + if (mesh) { mesh->setPlacement(this->Placement.getValue()); Mesh.setValue(mesh->getKernel()); return App::DocumentObject::StdReturn; } - else { - return new App::DocumentObjectExecReturn("Cannot create cube", this); - } + + return new App::DocumentObjectExecReturn("Cannot create cube", this); } void Cube::handleChangedPropertyType(Base::XMLReader& reader, diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 1de8503d7781..dffcaaf98140 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -109,7 +109,7 @@ unsigned long MeshObject::countSubElements(const char* Type) const if (element == "Mesh") { return 1; } - else if (element == "Segment") { + if (element == "Segment") { return countSegments(); } return 0; @@ -123,7 +123,7 @@ Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) cons segm->mesh = new MeshObject(*this); return segm; } - else if (element == "Segment" && n < countSegments()) { + if (element == "Segment" && n < countSegments()) { MeshSegment* segm = new MeshSegment(); segm->mesh = new MeshObject(*this); const Segment& faces = getSegment(n); @@ -703,10 +703,9 @@ void MeshObject::deletedFacets(const std::vector& remFacets) // remove the invalid indices std::sort(segm.begin(), segm.end()); - std::vector::iterator ft = - std::find_if(segm.begin(), segm.end(), [](FacetIndex v) { - return v == MeshCore::FACET_INDEX_MAX; - }); + auto ft = std::find_if(segm.begin(), segm.end(), [](FacetIndex v) { + return v == MeshCore::FACET_INDEX_MAX; + }); if (ft != segm.end()) { segm.erase(ft, segm.end()); } @@ -941,8 +940,7 @@ void MeshObject::offset(float fSize) unsigned int i = 0; // go through all the vertex normals - for (std::vector::iterator It = normals.begin(); It != normals.end(); - ++It, i++) { + for (auto It = normals.begin(); It != normals.end(); ++It, i++) { // and move each mesh point in the normal direction _kernel.MovePoint(i, It->Normalize() * fSize); } @@ -964,8 +962,7 @@ void MeshObject::offsetSpecial2(float fSize) unsigned int i = 0; // go through all the vertex normals - for (std::vector::iterator It = PointNormals.begin(); It != PointNormals.end(); - ++It, i++) { + for (auto It = PointNormals.begin(); It != PointNormals.end(); ++It, i++) { Base::Line3f line {_kernel.GetPoint(i), _kernel.GetPoint(i) + It->Normalize() * fSize}; Base::DrawStyle drawStyle; builder.addNode(Base::LineItem {line, drawStyle}); @@ -1022,8 +1019,7 @@ void MeshObject::offsetSpecial(float fSize, float zmax, float zmin) unsigned int i = 0; // go through all the vertex normals - for (std::vector::iterator It = normals.begin(); It != normals.end(); - ++It, i++) { + for (auto It = normals.begin(); It != normals.end(); ++It, i++) { auto Pnt = _kernel.GetPoint(i); if (Pnt.z < zmax && Pnt.z > zmin) { Pnt.z = 0; @@ -1349,8 +1345,8 @@ void MeshObject::refine() // x < 30 deg => cos(x) > sqrt(3)/2 or x > 120 deg => cos(x) < -0.5 for (unsigned long i = 0; i < cnt; i++) { cF.Set(i); - if (!cF->IsDeformed(0.86f, -0.5f)) { - topalg.InsertVertexAndSwapEdge(i, cF->GetGravityPoint(), 0.1f); + if (!cF->IsDeformed(0.86F, -0.5F)) { + topalg.InsertVertexAndSwapEdge(i, cF->GetGravityPoint(), 0.1F); } } @@ -1378,7 +1374,7 @@ void MeshObject::validateCaps(float fMaxAngle, float fSplitFactor) void MeshObject::optimizeTopology(float fMaxAngle) { MeshCore::MeshTopoAlgorithm topalg(_kernel); - if (fMaxAngle > 0.0f) { + if (fMaxAngle > 0.0F) { topalg.OptimizeTopology(fMaxAngle); } else { @@ -1402,8 +1398,7 @@ void MeshObject::splitEdges() MeshCore::MeshAlgorithm alg(_kernel); alg.ResetFacetFlag(MeshCore::MeshFacet::VISIT); const MeshCore::MeshFacetArray& rFacets = _kernel.GetFacets(); - for (MeshCore::MeshFacetArray::_TConstIterator pF = rFacets.begin(); pF != rFacets.end(); - ++pF) { + for (auto pF = rFacets.begin(); pF != rFacets.end(); ++pF) { int id = 2; if (pF->_aulNeighbours[id] != MeshCore::FACET_INDEX_MAX) { const MeshCore::MeshFacet& rFace = rFacets[pF->_aulNeighbours[id]]; @@ -1420,7 +1415,7 @@ void MeshObject::splitEdges() MeshCore::MeshTopoAlgorithm topalg(_kernel); for (const auto& it : adjacentFacet) { cIter.Set(it.first); - Base::Vector3f mid = 0.5f * (cIter->_aclPoints[0] + cIter->_aclPoints[2]); + Base::Vector3f mid = 0.5F * (cIter->_aclPoints[0] + cIter->_aclPoints[2]); topalg.SplitEdge(it.first, it.second, mid); } @@ -1751,8 +1746,8 @@ void MeshObject::validateDeformations(float fMaxAngle, float fEps) { unsigned long count = _kernel.CountFacets(); MeshCore::MeshFixDeformedFacets eval(_kernel, - Base::toRadians(15.0f), - Base::toRadians(150.0f), + Base::toRadians(15.0F), + Base::toRadians(150.0F), fMaxAngle, fEps); eval.Fixup(); @@ -2143,10 +2138,10 @@ MeshObject::const_point_iterator::const_point_iterator(const MeshObject* mesh, P this->_point.Mesh = _mesh; } -MeshObject::const_point_iterator::const_point_iterator(const MeshObject::const_point_iterator& fi) = +MeshObject::const_point_iterator::const_point_iterator(const MeshObject::const_point_iterator& pi) = default; -MeshObject::const_point_iterator::const_point_iterator(MeshObject::const_point_iterator&& fi) = +MeshObject::const_point_iterator::const_point_iterator(MeshObject::const_point_iterator&& pi) = default; MeshObject::const_point_iterator::~const_point_iterator() = default; diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index 66bbb678c381..57acce92acc8 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -209,7 +209,7 @@ class MeshExport MeshObject: public Data::ComplexGeoData // Save and load in internal format void save(std::ostream&) const; void load(std::istream&); - void writeInventor(std::ostream& str, float creaseangle = 0.0f) const; + void writeInventor(std::ostream& str, float creaseangle = 0.0F) const; //@} /** @name Manipulation */ @@ -249,7 +249,7 @@ class MeshExport MeshObject: public Data::ComplexGeoData * The point degree information is stored in \a point_degree. The return value * gives the number of points which will have a degree of zero. */ - unsigned long getPointDegree(const std::vector& facets, + unsigned long getPointDegree(const std::vector& indices, std::vector& point_degree) const; void fillupHoles(unsigned long, int, MeshCore::AbstractPolygonTriangulator&); void offset(float fSize); @@ -260,7 +260,7 @@ class MeshExport MeshObject: public Data::ComplexGeoData void transformToEigenSystem(); Base::Matrix4D getEigenSystem(Base::Vector3d& v) const; void movePoint(PointIndex, const Base::Vector3d& v); - void setPoint(PointIndex, const Base::Vector3d& v); + void setPoint(PointIndex index, const Base::Vector3d& p); void smooth(int iterations, float d_max); void decimate(float fTolerance, float fReduction); void decimate(int targetSize); @@ -268,7 +268,7 @@ class MeshExport MeshObject: public Data::ComplexGeoData std::vector getPointNormals() const; void crossSections(const std::vector&, std::vector& sections, - float fMinEps = 1.0e-2f, + float fMinEps = 1.0e-2F, bool bConnectPolygons = false) const; void cut(const Base::Polygon2d& polygon, const Base::ViewProjMethod& proj, CutType); void trim(const Base::Polygon2d& polygon, const Base::ViewProjMethod& proj, CutType); @@ -385,12 +385,12 @@ class MeshExport MeshObject: public Data::ComplexGeoData const_point_iterator(const_point_iterator&& pi); ~const_point_iterator(); - const_point_iterator& operator=(const const_point_iterator& fi); - const_point_iterator& operator=(const_point_iterator&& fi); + const_point_iterator& operator=(const const_point_iterator& pi); + const_point_iterator& operator=(const_point_iterator&& pi); const MeshPoint& operator*(); const MeshPoint* operator->(); - bool operator==(const const_point_iterator& fi) const; - bool operator!=(const const_point_iterator& fi) const; + bool operator==(const const_point_iterator& pi) const; + bool operator!=(const const_point_iterator& pi) const; const_point_iterator& operator++(); const_point_iterator& operator--(); @@ -463,7 +463,7 @@ class MeshExport MeshObject: public Data::ComplexGeoData void deletedFacets(const std::vector& remFacets); void updateMesh(const std::vector&) const; void updateMesh() const; - void swapKernel(MeshCore::MeshKernel& m, const std::vector& g); + void swapKernel(MeshCore::MeshKernel& kernel, const std::vector& g); void copySegments(const MeshObject&); void swapSegments(MeshObject&); diff --git a/src/Mod/Mesh/App/MeshFeature.h b/src/Mod/Mesh/App/MeshFeature.h index 8017e4271d03..584782b1774a 100644 --- a/src/Mod/Mesh/App/MeshFeature.h +++ b/src/Mod/Mesh/App/MeshFeature.h @@ -47,7 +47,6 @@ class MeshKernel; namespace Mesh { -class Property; class MeshFeaturePy; /** Base class of all mesh feature classes in FreeCAD. diff --git a/src/Mod/Mesh/App/MeshPoint.h b/src/Mod/Mesh/App/MeshPoint.h index 5580237004fe..1b5043b7f2bd 100644 --- a/src/Mod/Mesh/App/MeshPoint.h +++ b/src/Mod/Mesh/App/MeshPoint.h @@ -26,6 +26,7 @@ #include #include +#include #ifndef MESH_GLOBAL_H #include diff --git a/src/Mod/Mesh/App/MeshProperties.cpp b/src/Mod/Mesh/App/MeshProperties.cpp index bcfa6cbb87e3..8b9cb66f1c0a 100644 --- a/src/Mod/Mesh/App/MeshProperties.cpp +++ b/src/Mod/Mesh/App/MeshProperties.cpp @@ -244,7 +244,7 @@ std::vector PropertyCurvatureList::getCurvature(int mode) const // Mean curvature if (mode == MeanCurvature) { for (const auto& it : fCurvInfo) { - fValues.push_back(0.5f * (it.fMaxCurvature + it.fMinCurvature)); + fValues.push_back(0.5F * (it.fMaxCurvature + it.fMinCurvature)); } } // Gaussian curvature diff --git a/src/Mod/Mesh/App/MeshProperties.h b/src/Mod/Mesh/App/MeshProperties.h index d30048f24f26..d3be55dc462a 100644 --- a/src/Mod/Mesh/App/MeshProperties.h +++ b/src/Mod/Mesh/App/MeshProperties.h @@ -188,11 +188,11 @@ class MeshExport PropertyMaterial: public App::Property /** Sets the property */ - void setValue(const MeshCore::Material& mat); - void setAmbientColor(const std::vector& col); - void setDiffuseColor(const std::vector& col); - void setSpecularColor(const std::vector& col); - void setEmissiveColor(const std::vector& col); + void setValue(const MeshCore::Material& value); + void setAmbientColor(const std::vector& value); + void setDiffuseColor(const std::vector& value); + void setSpecularColor(const std::vector& value); + void setEmissiveColor(const std::vector& value); void setShininess(const std::vector&); void setTransparency(const std::vector&); void setBinding(MeshCore::MeshIO::Binding); diff --git a/src/Mod/Mesh/App/MeshTexture.cpp b/src/Mod/Mesh/App/MeshTexture.cpp index 607131613f59..90326148d4b7 100644 --- a/src/Mod/Mesh/App/MeshTexture.cpp +++ b/src/Mod/Mesh/App/MeshTexture.cpp @@ -50,7 +50,7 @@ void MeshTexture::apply(const Mesh::MeshObject& mesh, const App::Color& defaultColor, MeshCore::Material& material) { - apply(mesh, true, defaultColor, -1.0f, material); + apply(mesh, true, defaultColor, -1.0F, material); } void MeshTexture::apply(const Mesh::MeshObject& mesh, @@ -64,7 +64,7 @@ void MeshTexture::apply(const Mesh::MeshObject& mesh, void MeshTexture::apply(const Mesh::MeshObject& mesh, MeshCore::Material& material) { App::Color defaultColor; - apply(mesh, false, defaultColor, -1.0f, material); + apply(mesh, false, defaultColor, -1.0F, material); } void MeshTexture::apply(const Mesh::MeshObject& mesh, float max_dist, MeshCore::Material& material) @@ -85,7 +85,7 @@ void MeshTexture::apply(const Mesh::MeshObject& mesh, material.diffuseColor.clear(); material.binding = MeshCore::MeshIO::OVERALL; - if (kdTree.get()) { + if (kdTree) { // the points of the current mesh std::vector diffuseColor; const MeshCore::MeshPointArray& points = mesh.getKernel().GetPoints(); diff --git a/src/Mod/Mesh/App/MeshTexture.h b/src/Mod/Mesh/App/MeshTexture.h index 88ebd0374f4b..5251713b2d99 100644 --- a/src/Mod/Mesh/App/MeshTexture.h +++ b/src/Mod/Mesh/App/MeshTexture.h @@ -85,14 +85,13 @@ class MeshExport MeshTexture MeshCore::Material& material); PointIndex findIndex(const Base::Vector3f& p, float max_dist) const { - if (max_dist < 0.0f) { + if (max_dist < 0.0F) { return kdTree->FindExact(p); } - else { - Base::Vector3f n; - float dist {}; - return kdTree->FindNearest(p, max_dist, n, dist); - } + + Base::Vector3f n; + float dist {}; + return kdTree->FindNearest(p, max_dist, n, dist); } private: diff --git a/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp index cdda5fe0e479..ec0eb00ecb5f 100644 --- a/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp +++ b/src/Mod/Mesh/Gui/DlgSettingsImportExportImp.cpp @@ -89,7 +89,7 @@ void DlgSettingsImportExport::changeEvent(QEvent* e) ui->retranslateUi(this); } else { - QWidget::changeEvent(e); + PreferencePage::changeEvent(e); } } diff --git a/src/Mod/Mesh/Gui/DlgSettingsMeshView.cpp b/src/Mod/Mesh/Gui/DlgSettingsMeshView.cpp index ce3b6705942a..0481bce8729e 100644 --- a/src/Mod/Mesh/Gui/DlgSettingsMeshView.cpp +++ b/src/Mod/Mesh/Gui/DlgSettingsMeshView.cpp @@ -87,7 +87,7 @@ void DlgSettingsMeshView::changeEvent(QEvent* e) ui->retranslateUi(this); } else { - QWidget::changeEvent(e); + PreferencePage::changeEvent(e); } } diff --git a/src/Mod/Mesh/Gui/PreCompiled.h b/src/Mod/Mesh/Gui/PreCompiled.h index 8e9b804a4ebb..6c31c3511c07 100644 --- a/src/Mod/Mesh/Gui/PreCompiled.h +++ b/src/Mod/Mesh/Gui/PreCompiled.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Mod/Mesh/Gui/PropertyEditorMesh.cpp b/src/Mod/Mesh/Gui/PropertyEditorMesh.cpp index 69c6f46a7597..d5311c4a78dd 100644 --- a/src/Mod/Mesh/Gui/PropertyEditorMesh.cpp +++ b/src/Mod/Mesh/Gui/PropertyEditorMesh.cpp @@ -67,7 +67,7 @@ QVariant PropertyMeshKernelItem::value(const App::Property*) const const std::vector& props = getPropertyData(); for (auto prop : props) { - Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)prop; + Mesh::PropertyMeshKernel* pPropMesh = static_cast(prop); const MeshKernel& rMesh = pPropMesh->getValue().getKernel(); ctP += (int)rMesh.CountPoints(); ctE += (int)rMesh.CountEdges(); @@ -113,7 +113,7 @@ int PropertyMeshKernelItem::countPoints() const int ctP = 0; const std::vector& props = getPropertyData(); for (auto prop : props) { - Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)prop; + Mesh::PropertyMeshKernel* pPropMesh = static_cast(prop); const MeshKernel& rMesh = pPropMesh->getValue().getKernel(); ctP += (int)rMesh.CountPoints(); } @@ -126,7 +126,7 @@ int PropertyMeshKernelItem::countEdges() const int ctE = 0; const std::vector& props = getPropertyData(); for (auto prop : props) { - Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)prop; + Mesh::PropertyMeshKernel* pPropMesh = static_cast(prop); const MeshKernel& rMesh = pPropMesh->getValue().getKernel(); ctE += (int)rMesh.CountEdges(); } @@ -139,7 +139,7 @@ int PropertyMeshKernelItem::countFaces() const int ctF = 0; const std::vector& props = getPropertyData(); for (auto prop : props) { - Mesh::PropertyMeshKernel* pPropMesh = (Mesh::PropertyMeshKernel*)prop; + Mesh::PropertyMeshKernel* pPropMesh = static_cast(prop); const MeshKernel& rMesh = pPropMesh->getValue().getKernel(); ctF += (int)rMesh.CountFacets(); } diff --git a/src/Mod/Mesh/Gui/RemeshGmsh.cpp b/src/Mod/Mesh/Gui/RemeshGmsh.cpp index b49851fbfdbd..35b6362ef513 100644 --- a/src/Mod/Mesh/Gui/RemeshGmsh.cpp +++ b/src/Mod/Mesh/Gui/RemeshGmsh.cpp @@ -321,8 +321,9 @@ bool RemeshGmsh::writeProject(QString& inpFile, QString& outFile) // Parameters int algorithm = meshingAlgorithm(); double maxSize = getMaxSize(); - if (maxSize == 0.0) + if (maxSize == 0.0) { maxSize = 1.0e22; + } double minSize = getMinSize(); double angle = getAngle(); int maxAngle = 120; diff --git a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp index 426d89292eb9..33d8c6447fd6 100644 --- a/src/Mod/Mesh/Gui/SoFCMeshObject.cpp +++ b/src/Mod/Mesh/Gui/SoFCMeshObject.cpp @@ -210,11 +210,11 @@ SbBool SoSFMeshObject::readValue(SoInput* in) int32_t countPt {}; in->read(countPt); std::vector verts(countPt); - in->readBinaryArray(&(verts[0]), countPt); + in->readBinaryArray(verts.data(), countPt); MeshCore::MeshPointArray rPoints; rPoints.reserve(countPt / 3); - for (std::vector::iterator it = verts.begin(); it != verts.end();) { + for (auto it = verts.begin(); it != verts.end();) { Base::Vector3f p; p.x = *it; ++it; @@ -228,11 +228,11 @@ SbBool SoSFMeshObject::readValue(SoInput* in) int32_t countFt {}; in->read(countFt); std::vector faces(countFt); - in->readBinaryArray(&(faces[0]), countFt); + in->readBinaryArray(faces.data(), countFt); MeshCore::MeshFacetArray rFacets; rFacets.reserve(countFt / 3); - for (std::vector::iterator it = faces.begin(); it != faces.end();) { + for (auto it = faces.begin(); it != faces.end();) { MeshCore::MeshFacet f; f._aulPoints[0] = *it; ++it; @@ -282,7 +282,7 @@ void SoSFMeshObject::writeValue(SoOutput* out) const int32_t countPt = (int32_t)verts.size(); out->write(countPt); - out->writeBinaryArray(&(verts[0]), countPt); + out->writeBinaryArray(verts.data(), countPt); const MeshCore::MeshFacetArray& rFacets = value->getKernel().GetFacets(); std::vector faces; @@ -295,7 +295,7 @@ void SoSFMeshObject::writeValue(SoOutput* out) const int32_t countFt = (int32_t)faces.size(); out->write(countFt); - out->writeBinaryArray((const int32_t*)&(faces[0]), countFt); + out->writeBinaryArray((const int32_t*)faces.data(), countFt); } // ------------------------------------------------------- @@ -319,8 +319,8 @@ void SoFCMeshObjectElement::set(SoState* const state, SoNode* const node, const Mesh::MeshObject* const mesh) { - SoFCMeshObjectElement* elem = - (SoFCMeshObjectElement*)SoReplacedElement::getElement(state, classStackIndex, node); + SoFCMeshObjectElement* elem = static_cast( + SoReplacedElement::getElement(state, classStackIndex, node)); if (elem) { elem->mesh = mesh; elem->nodeId = node->getNodeId(); @@ -334,7 +334,8 @@ const Mesh::MeshObject* SoFCMeshObjectElement::get(SoState* const state) const SoFCMeshObjectElement* SoFCMeshObjectElement::getInstance(SoState* state) { - return (const SoFCMeshObjectElement*)SoElement::getConstElement(state, classStackIndex); + return static_cast( + SoElement::getConstElement(state, classStackIndex)); } void SoFCMeshObjectElement::print(FILE* /* file */) const @@ -377,7 +378,7 @@ void SoFCMeshPickNode::notify(SoNotList* list) MeshCore::MeshAlgorithm alg(meshObject->getKernel()); float fAvgLen = alg.GetAverageEdgeLength(); delete meshGrid; - meshGrid = new MeshCore::MeshFacetGrid(meshObject->getKernel(), 5.0f * fAvgLen); + meshGrid = new MeshCore::MeshFacetGrid(meshObject->getKernel(), 5.0F * fAvgLen); } } } @@ -452,7 +453,7 @@ void SoFCMeshGridNode::GLRender(SoGLRenderAction* /*action*/) float dx = (maxX - minX) / (float)u; float dy = (maxY - minY) / (float)v; float dz = (maxZ - minZ) / (float)w; - glColor3f(0.0f, 1.0f, 0.0); + glColor3f(0.0F, 1.0F, 0.0); glBegin(GL_LINES); for (short i = 0; i < u + 1; i++) { for (short j = 0; j < v + 1; j++) { @@ -733,9 +734,7 @@ void SoFCMeshObjectShape::drawFaces(const Mesh::MeshObject* mesh, glBegin(GL_TRIANGLES); if (ccw) { // counterclockwise ordering - for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); - it != rFacets.end(); - ++it) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it) { const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]]; const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]]; const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]]; @@ -807,16 +806,14 @@ void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject* mesh, const MeshCore::MeshFacetArray& rFacets = mesh->getKernel().GetFacets(); int mod = rFacets.size() / renderTriangleLimit + 1; - float size = std::min((float)mod, 3.0f); + float size = std::min((float)mod, 3.0F); glPointSize(size); if (needNormals) { glBegin(GL_POINTS); int ct = 0; if (ccw) { - for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); - it != rFacets.end(); - ++it, ct++) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]]; const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]]; @@ -830,18 +827,16 @@ void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject* mesh, // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glNormal3fv(n); glVertex3fv(p); } } } else { - for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); - it != rFacets.end(); - ++it, ct++) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]]; const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]]; @@ -855,9 +850,9 @@ void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject* mesh, // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glNormal3fv(n); glVertex3fv(p); } @@ -868,17 +863,16 @@ void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject* mesh, else { glBegin(GL_POINTS); int ct = 0; - for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); - ++it, ct++) { + for (auto it = rFacets.begin(); it != rFacets.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]]; const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]]; const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]]; // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glVertex3fv(p); } } @@ -932,8 +926,8 @@ void SoFCMeshObjectShape::renderFacesGLArray(SoGLRenderAction* action) glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); - glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0])); - glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, &(index_array[0])); + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, index_array.data()); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); @@ -947,8 +941,8 @@ void SoFCMeshObjectShape::renderCoordsGLArray(SoGLRenderAction* action) glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); - glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0])); - glDrawElements(GL_POINTS, cnt, GL_UNSIGNED_INT, &(index_array[0])); + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + glDrawElements(GL_POINTS, cnt, GL_UNSIGNED_INT, index_array.data()); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); @@ -1203,7 +1197,7 @@ void SoFCMeshObjectShape::computeBBox(SoAction* action, SbBox3f& box, SbVec3f& c } else { box.setBounds(SbVec3f(0, 0, 0), SbVec3f(0, 0, 0)); - center.setValue(0.0f, 0.0f, 0.0f); + center.setValue(0.0F, 0.0F, 0.0F); } } @@ -1426,16 +1420,14 @@ void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject* mesh, mesh->getSegment(this->index.getValue()).getIndices(); int mod = rSegm.size() / renderTriangleLimit + 1; - float size = std::min((float)mod, 3.0f); + float size = std::min((float)mod, 3.0F); glPointSize(size); if (needNormals) { glBegin(GL_POINTS); int ct = 0; if (ccw) { - for (std::vector::const_iterator it = rSegm.begin(); - it != rSegm.end(); - ++it, ct++) { + for (auto it = rSegm.begin(); it != rSegm.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshFacet& f = rFacets[*it]; const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]]; @@ -1450,18 +1442,16 @@ void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject* mesh, // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glNormal3fv(n); glVertex3fv(p); } } } else { - for (std::vector::const_iterator it = rSegm.begin(); - it != rSegm.end(); - ++it, ct++) { + for (auto it = rSegm.begin(); it != rSegm.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshFacet& f = rFacets[*it]; const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]]; @@ -1476,9 +1466,9 @@ void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject* mesh, // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glNormal3fv(n); glVertex3fv(p); } @@ -1489,8 +1479,7 @@ void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject* mesh, else { glBegin(GL_POINTS); int ct = 0; - for (std::vector::const_iterator it = rSegm.begin(); it != rSegm.end(); - ++it, ct++) { + for (auto it = rSegm.begin(); it != rSegm.end(); ++it, ct++) { if (ct % mod == 0) { const MeshCore::MeshFacet& f = rFacets[*it]; const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]]; @@ -1498,9 +1487,9 @@ void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject* mesh, const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]]; // Calculate the center point p=(v0+v1+v2)/3 float p[3]; - p[0] = (v0.x + v1.x + v2.x) / 3.0f; - p[1] = (v0.y + v1.y + v2.y) / 3.0f; - p[2] = (v0.z + v1.z + v2.z) / 3.0f; + p[0] = (v0.x + v1.x + v2.x) / 3.0F; + p[1] = (v0.y + v1.y + v2.y) / 3.0F; + p[2] = (v0.z + v1.z + v2.z) / 3.0F; glVertex3fv(p); } } @@ -1605,7 +1594,7 @@ void SoFCMeshSegmentShape::generatePrimitives(SoAction* action) void SoFCMeshSegmentShape::computeBBox(SoAction* action, SbBox3f& box, SbVec3f& center) { box.setBounds(SbVec3f(0, 0, 0), SbVec3f(0, 0, 0)); - center.setValue(0.0f, 0.0f, 0.0f); + center.setValue(0.0F, 0.0F, 0.0F); SoState* state = action->getState(); const Mesh::MeshObject* mesh = SoFCMeshObjectElement::get(state); @@ -1694,7 +1683,7 @@ void SoFCMeshObjectBoundary::drawLines(const Mesh::MeshObject* mesh) const // When rendering open edges use the given line width * 3 GLfloat lineWidth {}; glGetFloatv(GL_LINE_WIDTH, &lineWidth); - glLineWidth(3.0f * lineWidth); + glLineWidth(3.0F * lineWidth); // Use the data structure directly and not through MeshFacetIterator as this // class is quite slowly (at least for rendering) @@ -1779,7 +1768,7 @@ void SoFCMeshObjectBoundary::computeBBox(SoAction* action, SbBox3f& box, SbVec3f } else { box.setBounds(SbVec3f(0, 0, 0), SbVec3f(0, 0, 0)); - center.setValue(0.0f, 0.0f, 0.0f); + center.setValue(0.0F, 0.0F, 0.0F); } } diff --git a/src/Mod/Mesh/Gui/SoFCMeshObject.h b/src/Mod/Mesh/Gui/SoFCMeshObject.h index 5ca888c3cd7b..ec03cf1fec6d 100644 --- a/src/Mod/Mesh/Gui/SoFCMeshObject.h +++ b/src/Mod/Mesh/Gui/SoFCMeshObject.h @@ -211,7 +211,7 @@ class MeshGuiExport SoFCMeshObjectShape: public SoShape }; private: - void notify(SoNotList* list) override; + void notify(SoNotList* node) override; Binding findMaterialBinding(SoState* const state) const; // Draw faces void drawFaces(const Mesh::MeshObject*, diff --git a/src/Mod/Mesh/Gui/ViewProvider.cpp b/src/Mod/Mesh/Gui/ViewProvider.cpp index 01bb8727412e..70f11bb96888 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.cpp +++ b/src/Mod/Mesh/Gui/ViewProvider.cpp @@ -24,13 +24,14 @@ #ifndef _PreComp_ #include #include +#include #include +#include #include #include #include #include -#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #endif #include @@ -102,6 +104,7 @@ using MeshCore::MeshGeomFacet; using MeshCore::MeshKernel; using MeshCore::MeshPointIterator; +// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-pro-bounds*) void ViewProviderMeshBuilder::buildNodes(const App::Property* prop, std::vector& nodes) const { @@ -132,7 +135,7 @@ void ViewProviderMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces) const { - const Mesh::PropertyMeshKernel* mesh = static_cast(prop); + const auto mesh = dynamic_cast(prop); const MeshCore::MeshKernel& rcMesh = mesh->getValue().getKernel(); createMesh(rcMesh, coords, faces); } @@ -147,7 +150,7 @@ void ViewProviderMeshBuilder::createMesh(const MeshCore::MeshKernel& kernel, coords->point.setNum(kernel.CountPoints()); SbVec3f* verts = coords->point.startEditing(); int i = 0; - for (MeshCore::MeshPointArray::_TConstIterator it = cP.begin(); it != cP.end(); ++it, i++) { + for (auto it = cP.begin(); it != cP.end(); ++it, i++) { verts[i].setValue(it->x, it->y, it->z); } coords->point.finishEditing(); @@ -157,7 +160,7 @@ void ViewProviderMeshBuilder::createMesh(const MeshCore::MeshKernel& kernel, const MeshCore::MeshFacetArray& cF = kernel.GetFacets(); faces->coordIndex.setNum(4 * kernel.CountFacets()); int32_t* indices = faces->coordIndex.startEditing(); - for (MeshCore::MeshFacetArray::_TConstIterator it = cF.begin(); it != cF.end(); ++it, j++) { + for (auto it = cF.begin(); it != cF.end(); ++it, j++) { for (int i = 0; i < 3; i++) { indices[4 * j + i] = it->_aulPoints[i]; } @@ -186,48 +189,18 @@ const char* ViewProviderExport::getDefaultDisplayMode() const QIcon ViewProviderExport::getIcon() const { - // clang-format off - const char * Mesh_Feature_xpm[] = { - "22 22 6 1", - ". c None", - "# c #000000", - "c c #ffff00", - "a c #808080", - "b c #c0c0c0", - "f c #008000", - ".............##.......", - ".............###......", - ".............#f##.....", - ".#....####...#ff##....", - ".##.##....#..#fff##...", - ".###.........#ffff##..", - ".####........#fffff##.", - ".#####.......#ffffff##", - ".............#########", - ".####.................", - "#abab##########.......", - "#babababababab#.......", - "#ababababababa#.......", - "#babab################", - "#abab##cccccccccccc##.", - "#bab##cccccccccccc##..", - "#ab##cccccccccccc##...", - "#b##cccccccccccc##....", - "###cccccccccccc##.....", - "##cccccccccccc##......", - "###############.......", - "......................"}; - QPixmap px(Mesh_Feature_xpm); - return px; - // clang-format on + static QIcon icon = Gui::BitmapFactory().pixmap("Mesh_Export"); + return icon; } // ------------------------------------------------------ -App::PropertyFloatConstraint::Constraints ViewProviderMesh::floatRange = {1.0F, 64.0F, 1.0F}; -App::PropertyFloatConstraint::Constraints ViewProviderMesh::angleRange = {0.0F, 180.0F, 1.0F}; -App::PropertyIntegerConstraint::Constraints ViewProviderMesh::intPercent = {0, 100, 5}; -const char* ViewProviderMesh::LightingEnums[] = {"One side", "Two side", nullptr}; +// clang-format off +const App::PropertyFloatConstraint::Constraints ViewProviderMesh::floatRange = {1.0F, 64.0F, 1.0F}; +const App::PropertyFloatConstraint::Constraints ViewProviderMesh::angleRange = {0.0F, 180.0F, 1.0F}; +const App::PropertyIntegerConstraint::Constraints ViewProviderMesh::intPercent = {0, 100, 5}; +std::array ViewProviderMesh::LightingEnums = {"One side", "Two side", nullptr}; +// clang-format on PROPERTY_SOURCE(MeshGui::ViewProviderMesh, Gui::ViewProviderGeometryObject) @@ -237,6 +210,7 @@ ViewProviderMesh::ViewProviderMesh() // NOLINTBEGIN static const char* osgroup = "Object Style"; + // clang-format off ADD_PROPERTY_TYPE(LineTransparency, (0), osgroup, App::Prop_None, "Set line transparency."); LineTransparency.setConstraints(&intPercent); ADD_PROPERTY_TYPE(LineWidth, (1.0f), osgroup, App::Prop_None, "Set line width."); @@ -247,13 +221,11 @@ ViewProviderMesh::ViewProviderMesh() CreaseAngle.setConstraints(&angleRange); ADD_PROPERTY_TYPE(OpenEdges, (false), osgroup, App::Prop_None, "Set open edges."); ADD_PROPERTY_TYPE(Coloring, (false), osgroup, App::Prop_None, "Set coloring."); - ADD_PROPERTY_TYPE(Lighting, - (1), - osgroup, - App::Prop_None, + ADD_PROPERTY_TYPE(Lighting, (1), osgroup, App::Prop_None, "Set if the illumination comes from two sides\n or one side in the 3D view."); - Lighting.setEnums(LightingEnums); + Lighting.setEnums(LightingEnums.data()); ADD_PROPERTY_TYPE(LineColor, (0, 0, 0), osgroup, App::Prop_None, "Set line color."); + // clang-format on // Create the selection node pcHighlight = Gui::ViewProviderBuilder::createSelection(); @@ -412,6 +384,21 @@ void ViewProviderMesh::setOpenEdgeColorFrom(const App::Color& c) pOpenColor->rgb.setValue(r, g, b); } +const Mesh::PropertyMeshKernel& ViewProviderMesh::getMeshProperty() const +{ + return Base::freecad_dynamic_cast(getObject())->Mesh; +} + +Mesh::PropertyMeshKernel& ViewProviderMesh::getMeshProperty() +{ + return Base::freecad_dynamic_cast(getObject())->Mesh; +} + +const Mesh::MeshObject& ViewProviderMesh::getMeshObject() const +{ + return getMeshProperty().getValue(); +} + SoShape* ViewProviderMesh::getShapeNode() const { return nullptr; @@ -426,12 +413,12 @@ SoNode* ViewProviderMesh::getCoordNode() const * Extracts the mesh data from the feature \a pcFeature and creates * an Inventor node \a SoNode with these data. */ -void ViewProviderMesh::attach(App::DocumentObject* pcFeat) +void ViewProviderMesh::attach(App::DocumentObject* obj) { - ViewProviderGeometryObject::attach(pcFeat); + ViewProviderGeometryObject::attach(obj); - pcHighlight->objectName = pcFeat->getNameInDocument(); - pcHighlight->documentName = pcFeat->getDocument()->getName(); + pcHighlight->objectName = obj->getNameInDocument(); + pcHighlight->documentName = obj->getDocument()->getName(); pcHighlight->subElementName = "Main"; // Note: Since for mesh data the SoFCSelection node has no SoSeparator but @@ -441,7 +428,7 @@ void ViewProviderMesh::attach(App::DocumentObject* pcFeat) // highlighting or selection we would need an SoSeparator as parent node below. // faces - SoGroup* pcFlatRoot = new SoGroup(); + auto pcFlatRoot = new SoGroup(); pcFlatRoot->addChild(pShapeHints); pcFlatRoot->addChild(pcShapeMaterial); pcFlatRoot->addChild(pcMatBinding); @@ -449,7 +436,7 @@ void ViewProviderMesh::attach(App::DocumentObject* pcFeat) addDisplayMaskMode(pcFlatRoot, "Shaded"); // points - SoGroup* pcPointRoot = new SoGroup(); + auto pcPointRoot = new SoGroup(); pcPointRoot->addChild(pcPointStyle); pcPointRoot->addChild(pShapeHints); pcPointRoot->addChild(pcShapeMaterial); @@ -458,12 +445,12 @@ void ViewProviderMesh::attach(App::DocumentObject* pcFeat) addDisplayMaskMode(pcPointRoot, "Point"); // wires - SoLightModel* pcLightModel = new SoLightModel(); + auto pcLightModel = new SoLightModel(); pcLightModel->model = SoLightModel::BASE_COLOR; - SoGroup* pcWireRoot = new SoGroup(); + auto pcWireRoot = new SoGroup(); pcWireRoot->addChild(pcLineStyle); pcWireRoot->addChild(pcLightModel); - SoMaterialBinding* binding = new SoMaterialBinding; + auto binding = new SoMaterialBinding; binding->value = SoMaterialBinding::OVERALL; // doesn't set several colors pcWireRoot->addChild(binding); pcWireRoot->addChild(pLineColor); @@ -473,19 +460,19 @@ void ViewProviderMesh::attach(App::DocumentObject* pcFeat) // faces+wires // Avoid any Z-buffer artifacts, so that the lines always // appear on top of the faces - SoPolygonOffset* offset = new SoPolygonOffset(); + auto offset = new SoPolygonOffset(); offset->styles = SoPolygonOffset::FILLED; offset->factor = 1.0F; offset->units = 1.0F; - SoSeparator* pcWireSep = new SoSeparator(); + auto pcWireSep = new SoSeparator(); pcWireSep->addChild(pcLineStyle); pcWireSep->addChild(pcLightModel); pcWireSep->addChild(binding); pcWireSep->addChild(pLineColor); pcWireSep->addChild(pcHighlight); - SoGroup* pcFlatWireRoot = new SoGroup(); + auto pcFlatWireRoot = new SoGroup(); pcFlatWireRoot->addChild(pcWireSep); pcFlatWireRoot->addChild(offset); pcFlatWireRoot->addChild(pShapeHints); @@ -533,7 +520,7 @@ App::PropertyColorList* ViewProviderMesh::getColorProperty() const for (const auto& it : Map) { Base::Type type = it.second->getTypeId(); if (type == App::PropertyColorList::getClassTypeId()) { - App::PropertyColorList* colors = static_cast(it.second); + auto colors = static_cast(it.second); return colors; } } @@ -544,8 +531,7 @@ App::PropertyColorList* ViewProviderMesh::getColorProperty() const void ViewProviderMesh::tryColorPerVertexOrFace(bool on) { if (on) { - const Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - const Mesh::MeshObject& mesh = meshProp.getValue(); + const Mesh::MeshObject& mesh = getMeshObject(); int numPoints = static_cast(mesh.countPoints()); int numFacets = static_cast(mesh.countFacets()); @@ -604,7 +590,7 @@ void ViewProviderMesh::tryColorPerVertexOrFace(bool on) pcMatBinding->value = SoMaterialBinding::OVERALL; const App::Color& c = ShapeAppearance.getDiffuseColor(); pcShapeMaterial->diffuseColor.setValue(c.r, c.g, c.b); - pcShapeMaterial->transparency.setValue(Transparency.getValue() / 100.0f); + pcShapeMaterial->transparency.setValue(Transparency.getValue() / 100.0F); } } @@ -661,7 +647,7 @@ Mesh::PropertyMaterial* ViewProviderMesh::getMaterialProperty() const for (const auto& it : Map) { Base::Type type = it.second->getTypeId(); if (type == Mesh::PropertyMaterial::getClassTypeId()) { - Mesh::PropertyMaterial* material = static_cast(it.second); + auto material = static_cast(it.second); return material; } } @@ -705,13 +691,13 @@ bool ViewProviderMesh::exportToVrml(const char* filename, const MeshCore::Material& mat, bool binary) const { - SoCoordinate3* coords = new SoCoordinate3(); - SoIndexedFaceSet* faces = new SoIndexedFaceSet(); + auto coords = new SoCoordinate3(); + auto faces = new SoIndexedFaceSet(); ViewProviderMeshBuilder builder; builder.createMesh(&static_cast(pcObject)->Mesh, coords, faces); - SoMaterialBinding* binding = new SoMaterialBinding; - SoMaterial* material = new SoMaterial; + auto binding = new SoMaterialBinding; + auto material = new SoMaterial; if (static_cast(mat.diffuseColor.size()) == coords->point.getNum()) { binding->value = SoMaterialBinding::PER_VERTEX_INDEXED; @@ -729,7 +715,7 @@ bool ViewProviderMesh::exportToVrml(const char* filename, material->diffuseColor.finishEditing(); } - SoGroup* group = new SoGroup(); + auto group = new SoGroup(); group->addChild(material); group->addChild(binding); group->addChild(new SoTransform()); @@ -805,7 +791,7 @@ void ViewProviderMesh::setupContextMenu(QMenu* menu, QObject* receiver, const ch ViewProviderGeometryObject::setupContextMenu(menu, receiver, member); // toggle command to display components - Gui::ActionFunction* func = new Gui::ActionFunction(menu); + auto func = new Gui::ActionFunction(menu); QAction* act = menu->addAction(QObject::tr("Display components")); act->setCheckable(true); act->setChecked(pcMatBinding->value.getValue() == SoMaterialBinding::PER_FACE @@ -836,7 +822,7 @@ bool ViewProviderMesh::setEdit(int ModNum) if (ModNum == ViewProvider::Transform) { return ViewProviderGeometryObject::setEdit(ModNum); } - else if (ModNum == ViewProvider::Color) { + if (ModNum == ViewProvider::Color) { highlightComponents(); } return true; @@ -857,14 +843,21 @@ bool ViewProviderMesh::createToolMesh(const std::vector& rclPoly, const Base::Vector3f& rcNormal, std::vector& aFaces) { - float fX {}, fY {}, fZ {}; - SbVec3f pt1, pt2, pt3, pt4; + float fX {}; + float fY {}; + float fZ {}; + SbVec3f pt1; + SbVec3f pt2; + SbVec3f pt3; + SbVec3f pt4; MeshGeomFacet face; - std::vector top, bottom, polygon; + std::vector top; + std::vector bottom; + std::vector polygon; - for (std::vector::const_iterator it = rclPoly.begin(); it != rclPoly.end(); ++it) { + for (auto it = rclPoly.begin(); it != rclPoly.end(); ++it) { // the following element - std::vector::const_iterator nt = it + 1; + auto nt = it + 1; if (nt == rclPoly.end()) { nt = rclPoly.begin(); } @@ -904,7 +897,7 @@ bool ViewProviderMesh::createToolMesh(const std::vector& rclPoly, bottom.emplace_back(fX, fY, fZ); // polygon we need to triangulate (in x,y-plane) it->getValue(fX, fY); - polygon.emplace_back(fX, fY, 0.0f); + polygon.emplace_back(fX, fY, 0.0F); } } @@ -982,8 +975,8 @@ class MeshSplit Gui::Document* gui = mesh->getDocument(); App::Document* doc = gui->getDocument(); - Mesh::Feature* cpy = static_cast(doc->addObject("Mesh::Feature")); - Mesh::Feature* org = static_cast(mesh->getObject()); + auto cpy = static_cast(doc->addObject("Mesh::Feature")); + auto org = static_cast(mesh->getObject()); cpy->Label.setValue(org->Label.getValue()); cpy->Mesh.setValue(org->Mesh.getValue()); @@ -997,16 +990,16 @@ class MeshSplit }; } // namespace MeshGui -void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* cb) { // show the wait cursor because this could take quite some time Gui::WaitCursor wc; // When this callback function is invoked we must in either case leave the edit mode - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + auto view = static_cast(cb->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), clipMeshCallback, ud); - n->setHandled(); + cb->setHandled(); Gui::SelectionRole role {}; std::vector clPoly = view->getGLPolygon(&role); @@ -1024,7 +1017,7 @@ void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* n) QT_TRANSLATE_NOOP("Command", "Cut")); bool commitCommand = false; for (auto it : views) { - ViewProviderMesh* self = static_cast(it); + auto self = static_cast(it); if (self->getEditingMode() > -1) { self->finishEditing(); SoCamera* cam = view->getSoRenderManager()->getCamera(); @@ -1045,9 +1038,9 @@ void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* n) // We must delay the split because it adds a new // node to the scenegraph which cannot be done while // traversing it - Gui::TimerFunction* func = new Gui::TimerFunction(); + auto func = new Gui::TimerFunction(); func->setAutoDelete(true); - MeshSplit* split = new MeshSplit(self, clPoly, proj); + auto split = new MeshSplit(self, clPoly, proj); func->setFunction([split]() { split->cutMesh(); }); @@ -1067,16 +1060,16 @@ void ViewProviderMesh::clipMeshCallback(void* ud, SoEventCallback* n) } } -void ViewProviderMesh::trimMeshCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::trimMeshCallback(void* ud, SoEventCallback* cb) { // show the wait cursor because this could take quite some time Gui::WaitCursor wc; // When this callback function is invoked we must in either case leave the edit mode - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + auto view = static_cast(cb->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), trimMeshCallback, ud); - n->setHandled(); + cb->setHandled(); Gui::SelectionRole role {}; std::vector clPoly = view->getGLPolygon(&role); @@ -1094,7 +1087,7 @@ void ViewProviderMesh::trimMeshCallback(void* ud, SoEventCallback* n) QT_TRANSLATE_NOOP("Command", "Trim")); bool commitCommand = false; for (auto it : views) { - ViewProviderMesh* self = static_cast(it); + auto self = static_cast(it); if (self->getEditingMode() > -1) { self->finishEditing(); SoCamera* cam = view->getSoRenderManager()->getCamera(); @@ -1115,9 +1108,9 @@ void ViewProviderMesh::trimMeshCallback(void* ud, SoEventCallback* n) // We must delay the split because it adds a new // node to the scenegraph which cannot be done while // traversing it - Gui::TimerFunction* func = new Gui::TimerFunction(); + auto func = new Gui::TimerFunction(); func->setAutoDelete(true); - MeshSplit* split = new MeshSplit(self, clPoly, proj); + auto split = new MeshSplit(self, clPoly, proj); func->setFunction([split]() { split->trimMesh(); }); @@ -1143,7 +1136,7 @@ void ViewProviderMesh::partMeshCallback(void* ud, SoEventCallback* cb) Gui::WaitCursor wc; // When this callback function is invoked we must in either case leave the edit mode - Gui::View3DInventorViewer* view = static_cast(cb->getUserData()); + auto view = static_cast(cb->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), partMeshCallback, ud); cb->setHandled(); @@ -1158,7 +1151,8 @@ void ViewProviderMesh::partMeshCallback(void* ud, SoEventCallback* cb) } // get the normal of the front clipping plane - SbVec3f b, n; + SbVec3f b; + SbVec3f n; view->getNearPlane(b, n); Base::Vector3f cNormal(n[0], n[1], n[2]); SoCamera* pCam = view->getSoRenderManager()->getCamera(); @@ -1184,7 +1178,7 @@ void ViewProviderMesh::partMeshCallback(void* ud, SoEventCallback* cb) std::vector views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId()); for (auto view : views) { - ViewProviderMesh* that = static_cast(view); + auto that = static_cast(view); if (that->getEditingMode() > -1) { that->finishEditing(); Base::Placement plm = @@ -1216,7 +1210,7 @@ void ViewProviderMesh::segmMeshCallback(void* ud, SoEventCallback* cb) Gui::WaitCursor wc; // When this callback function is invoked we must in either case leave the edit mode - Gui::View3DInventorViewer* view = static_cast(cb->getUserData()); + auto view = static_cast(cb->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), segmMeshCallback, ud); cb->setHandled(); @@ -1231,7 +1225,8 @@ void ViewProviderMesh::segmMeshCallback(void* ud, SoEventCallback* cb) } // get the normal of the front clipping plane - SbVec3f b, n; + SbVec3f b; + SbVec3f n; view->getNearPlane(b, n); Base::Vector3f cNormal(n[0], n[1], n[2]); SoCamera* pCam = view->getSoRenderManager()->getCamera(); @@ -1257,7 +1252,7 @@ void ViewProviderMesh::segmMeshCallback(void* ud, SoEventCallback* cb) std::vector views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId()); for (auto view : views) { - ViewProviderMesh* that = static_cast(view); + auto that = static_cast(view); if (that->getEditingMode() > -1) { that->finishEditing(); Base::Placement plm = @@ -1283,22 +1278,23 @@ void ViewProviderMesh::segmMeshCallback(void* ud, SoEventCallback* cb) view->redraw(); } -void ViewProviderMesh::selectGLCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::selectGLCallback(void* ud, SoEventCallback* cb) { // When this callback function is invoked we must in either case leave the edit mode - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + auto view = static_cast(cb->getUserData()); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectGLCallback, ud); - n->setHandled(); + cb->setHandled(); std::vector clPoly = view->getGLPolygon(); if (clPoly.size() != 2) { return; } - const SoEvent* ev = n->getEvent(); + const SoEvent* ev = cb->getEvent(); SbVec2f pos = clPoly[0]; - float pX {}, pY {}; + float pX {}; + float pY {}; pos.getValue(pX, pY); const SbVec2s& sz = view->getSoRenderManager()->getViewportRegion().getViewportSizePixels(); float fRatio = view->getSoRenderManager()->getViewportRegion().getViewportAspectRatio(); @@ -1311,8 +1307,8 @@ void ViewProviderMesh::selectGLCallback(void* ud, SoEventCallback* n) pos.setValue(pX, pY); } - short x1 = (short)(pX * sz[0] + 0.5F); - short y1 = (short)(pY * sz[1] + 0.5F); + short x1 = short(std::lround(pX * sz[0])); + short y1 = short(std::lround(pY * sz[1])); SbVec2s loc = ev->getPosition(); short x2 = loc[0]; short y2 = loc[1]; @@ -1331,7 +1327,7 @@ void ViewProviderMesh::selectGLCallback(void* ud, SoEventCallback* n) std::vector views; views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId()); for (auto it : views) { - ViewProviderMesh* that = static_cast(it); + auto that = static_cast(it); if (that->getEditingMode() > -1) { that->finishEditing(); that->selectArea(x, @@ -1358,13 +1354,13 @@ void ViewProviderMesh::getFacetsFromPolygon(const std::vector& picked, } // Get the attached mesh property - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - MeshCore::MeshAlgorithm cAlg(meshProp.getValue().getKernel()); + const Mesh::MeshObject& mesh = getMeshObject(); + MeshCore::MeshAlgorithm cAlg(mesh.getKernel()); cAlg.CheckFacets(&proj, polygon, true, indices); if (!inner) { // get the indices that are completely outside - std::vector complete(meshProp.getValue().countFacets()); + std::vector complete(mesh.countFacets()); std::generate(complete.begin(), complete.end(), Base::iotaGen(0)); std::sort(indices.begin(), indices.end()); std::vector complementary; @@ -1383,7 +1379,7 @@ std::vector ViewProviderMesh::getFacetsOfRegion(const SbViewpo const SbViewportRegion& region, SoCamera* camera) const { - SoSeparator* root = new SoSeparator(); + auto root = new SoSeparator(); root->ref(); root->addChild(camera); root->addChild(this->getCoordNode()); @@ -1430,7 +1426,8 @@ void ViewProviderMesh::boxZoom(const SbBox2s& box, const SbViewportRegion& vp, S { SbViewVolume vv = cam->getViewVolume(vp.getViewportAspectRatio()); - short sizeX {}, sizeY {}; + short sizeX {}; + short sizeY {}; box.getSize(sizeX, sizeY); SbVec2s size = vp.getViewportSizePixels(); @@ -1446,9 +1443,10 @@ void ViewProviderMesh::boxZoom(const SbBox2s& box, const SbViewportRegion& vp, S short ymin {}; short ymax {}; box.getBounds(xmin, ymin, xmax, ymax); - const SbVec2f center((float)((xmin + xmax) / 2) / (float)std::max((int)(size[0] - 1), 1), - (float)(size[1] - (ymin + ymax) / 2) - / (float)std::max((int)(size[1] - 1), 1)); + // clang-format off + const SbVec2f center((float)( (xmin + xmax) / 2) / (float)std::max((int)(size[0] - 1), 1), + (float)(size[1] - (ymin + ymax) / 2) / (float)std::max((int)(size[1] - 1), 1)); + // clang-format on SbPlane plane = vv.getPlane(cam->focalDistance.getValue()); panCamera(cam, vp.getViewportAspectRatio(), plane, SbVec2f(0.5, 0.5), center); @@ -1483,7 +1481,7 @@ ViewProviderMesh::getVisibleFacetsAfterZoom(const SbBox2s& rect, void ViewProviderMesh::renderGLCallback(void* ud, SoAction* action) { if (action->isOfType(SoGLRenderAction::getClassTypeId())) { - ViewProviderMesh* mesh = static_cast(ud); + auto mesh = static_cast(ud); Gui::SoVisibleFaceAction fa; fa.apply(mesh->getRoot()); } @@ -1520,18 +1518,17 @@ class Vertex std::vector ViewProviderMesh::getVisibleFacets(const SbViewportRegion& vp, SoCamera* camera) const { - const Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - const Mesh::MeshObject& mesh = meshProp.getValue(); + const Mesh::MeshObject& mesh = getMeshObject(); uint32_t count = (uint32_t)mesh.countFacets(); - SoSeparator* root = new SoSeparator; + auto root = new SoSeparator; root->ref(); root->addChild(camera); - SoLightModel* lm = new SoLightModel(); + auto lm = new SoLightModel(); lm->model = SoLightModel::BASE_COLOR; root->addChild(lm); - SoMaterial* mat = new SoMaterial(); + auto mat = new SoMaterial(); mat->diffuseColor.setNum(count); SbColor* diffcol = mat->diffuseColor.startEditing(); for (uint32_t i = 0; i < count; i++) { @@ -1541,7 +1538,7 @@ std::vector ViewProviderMesh::getVisibleFacets(const SbViewpor mat->diffuseColor.finishEditing(); - SoMaterialBinding* bind = new SoMaterialBinding(); + auto bind = new SoMaterialBinding(); bind->value = SoMaterialBinding::PER_FACE; root->addChild(mat); @@ -1580,13 +1577,13 @@ std::vector ViewProviderMesh::getVisibleFacets(const SbViewpor return faces; } -void ViewProviderMesh::cutMesh(const std::vector& picked, +void ViewProviderMesh::cutMesh(const std::vector& polygon, const Base::ViewProjMethod& proj, SbBool inner) { // Get the facet indices inside the tool mesh std::vector indices; - getFacetsFromPolygon(picked, proj, inner, indices); + getFacetsFromPolygon(polygon, proj, inner, indices); removeFacets(indices); } @@ -1594,7 +1591,8 @@ void ViewProviderMesh::trimMesh(const std::vector& polygon, const Base::ViewProjMethod& proj, SbBool inner) { - Mesh::MeshObject* mesh = static_cast(pcObject)->Mesh.startEditing(); + Mesh::PropertyMeshKernel& prop = getMeshProperty(); + Mesh::MeshObject* mesh = prop.startEditing(); Base::Polygon2d polygon2d; for (auto it : polygon) { @@ -1603,8 +1601,8 @@ void ViewProviderMesh::trimMesh(const std::vector& polygon, Mesh::MeshObject::CutType type = inner ? Mesh::MeshObject::INNER : Mesh::MeshObject::OUTER; mesh->trim(polygon2d, proj, type); - static_cast(pcObject)->Mesh.finishEditing(); - pcObject->purgeTouched(); + prop.finishEditing(); + getObject()->purgeTouched(); } void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, @@ -1612,7 +1610,7 @@ void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, SbBool clip_inner) { // Get the attached mesh property - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; + Mesh::PropertyMeshKernel& meshProp = getMeshProperty(); const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel(); // Get the facet indices inside the tool mesh @@ -1634,12 +1632,12 @@ void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, // Remove the facets from the mesh and create a new one Mesh::MeshObject* kernel = meshProp.getValue().meshFromSegment(indices); removeFacets(indices); - Mesh::Feature* splitMesh = static_cast( - App::GetApplication().getActiveDocument()->addObject("Mesh::Feature", - pcObject->getNameInDocument())); + auto doc = App::GetApplication().getActiveDocument(); + const char* name = pcObject->getNameInDocument(); + auto splitMesh = dynamic_cast(doc->addObject("Mesh::Feature", name)); // Note: deletes also kernel splitMesh->Mesh.setValuePtr(kernel); - static_cast(pcObject)->purgeTouched(); + getObject()->purgeTouched(); } void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh, @@ -1647,7 +1645,7 @@ void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh, SbBool clip_inner) { // Get the attached mesh property - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; + Mesh::PropertyMeshKernel& meshProp = getMeshProperty(); const MeshCore::MeshKernel& meshPropKernel = meshProp.getValue().getKernel(); // Get the facet indices inside the tool mesh @@ -1669,19 +1667,19 @@ void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh, Mesh::MeshObject* kernel = meshProp.startEditing(); kernel->addSegment(indices); meshProp.finishEditing(); - static_cast(pcObject)->purgeTouched(); + getObject()->purgeTouched(); } -void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* cb) { - const SoMouseButtonEvent* mbe = static_cast(n->getEvent()); - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + const auto mbe = static_cast(cb->getEvent()); + auto view = static_cast(cb->getUserData()); // Mark all incoming mouse button events as handled, especially, to deactivate the selection // node - n->getAction()->setHandled(); + cb->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { - n->setHandled(); + cb->setHandled(); // context-menu QMenu menu; QAction* cl = menu.addAction(QObject::tr("Leave info mode")); @@ -1705,13 +1703,13 @@ void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n) } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { - const SoPickedPoint* point = n->getPickedPoint(); + const SoPickedPoint* point = cb->getPickedPoint(); if (!point) { Base::Console().Message("No facet picked.\n"); return; } - n->setHandled(); + cb->setHandled(); // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry @@ -1726,11 +1724,11 @@ void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n) // For a proper solution it's best to move the Flag class to the QGraphicsView API. view->setEnabledNaviCube(false); - ViewProviderMesh* that = static_cast(vp); + auto that = static_cast(vp); const SoDetail* detail = point->getDetail(that->getShapeNode()); if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { // get the boundary to the picked facet - const SoFaceDetail* faceDetail = static_cast(detail); + const auto faceDetail = static_cast(detail); Mesh::FacetIndex uFacet = faceDetail->getFaceIndex(); that->faceInfo(uFacet); Gui::GLFlagWindow* flags = nullptr; @@ -1750,7 +1748,7 @@ void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n) static_cast(faceDetail->getPoint(1))->getCoordinateIndex(); int point3 = static_cast(faceDetail->getPoint(2))->getCoordinateIndex(); - Gui::Flag* flag = new Gui::Flag; + auto flag = new Gui::Flag; flag->setText(QObject::tr("Index: %1").arg(uFacet)); QString toolTip = QString::fromLatin1("Facet index: %1\n" "Points: <%2, %3, %4>") @@ -1765,16 +1763,16 @@ void ViewProviderMesh::faceInfoCallback(void* ud, SoEventCallback* n) } } -void ViewProviderMesh::fillHoleCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::fillHoleCallback(void* ud, SoEventCallback* cb) { - const SoMouseButtonEvent* mbe = static_cast(n->getEvent()); - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + const auto mbe = static_cast(cb->getEvent()); + auto view = static_cast(cb->getUserData()); // Mark all incoming mouse button events as handled, especially, to deactivate the selection // node - n->getAction()->setHandled(); + cb->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { - n->setHandled(); + cb->setHandled(); // context-menu QMenu menu; QAction* cl = menu.addAction(QObject::tr("Leave hole-filling mode")); @@ -1788,43 +1786,41 @@ void ViewProviderMesh::fillHoleCallback(void* ud, SoEventCallback* n) } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { - const SoPickedPoint* point = n->getPickedPoint(); + const SoPickedPoint* point = cb->getPickedPoint(); if (!point) { Base::Console().Message("No facet picked.\n"); return; } - n->setHandled(); + cb->setHandled(); // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath()); - if (!vp || !vp->isDerivedFrom()) { - return; - } - ViewProviderMesh* that = static_cast(vp); - const SoDetail* detail = point->getDetail(that->getShapeNode()); - if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { - // get the boundary to the picked facet - Mesh::FacetIndex uFacet = ((SoFaceDetail*)detail)->getFaceIndex(); - that->fillHole(uFacet); + if (auto that = dynamic_cast(vp)) { + const SoDetail* detail = point->getDetail(that->getShapeNode()); + if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { + // get the boundary to the picked facet + Mesh::FacetIndex uFacet = static_cast(detail)->getFaceIndex(); + that->fillHole(uFacet); + } } } } -void ViewProviderMesh::markPartCallback(void* ud, SoEventCallback* n) +void ViewProviderMesh::markPartCallback(void* ud, SoEventCallback* cb) { // handle only mouse button events - if (n->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) { - const SoMouseButtonEvent* mbe = static_cast(n->getEvent()); - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + if (cb->getEvent()->isOfType(SoMouseButtonEvent::getClassTypeId())) { + const auto mbe = static_cast(cb->getEvent()); + auto view = static_cast(cb->getUserData()); // Mark all incoming mouse button events as handled, especially, to deactivate the selection // node - n->getAction()->setHandled(); + cb->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { - n->setHandled(); + cb->setHandled(); // context-menu QMenu menu; QAction* cl = menu.addAction(QObject::tr("Leave removal mode")); @@ -1865,26 +1861,25 @@ void ViewProviderMesh::markPartCallback(void* ud, SoEventCallback* n) } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { - const SoPickedPoint* point = n->getPickedPoint(); + const SoPickedPoint* point = cb->getPickedPoint(); if (!point) { Base::Console().Message("No facet picked.\n"); return; } - n->setHandled(); + cb->setHandled(); // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath()); - if (!vp || !vp->isDerivedFrom()) { - return; - } - ViewProviderMesh* that = static_cast(vp); - const SoDetail* detail = point->getDetail(that->getShapeNode()); - if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { - // get the boundary to the picked facet - Mesh::FacetIndex uFacet = static_cast(detail)->getFaceIndex(); - that->selectComponent(uFacet); + if (auto that = dynamic_cast(vp)) { + const SoDetail* detail = point->getDetail(that->getShapeNode()); + if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { + // get the boundary to the picked facet + Mesh::FacetIndex uFacet = + static_cast(detail)->getFaceIndex(); + that->selectComponent(uFacet); + } } } } @@ -1892,8 +1887,7 @@ void ViewProviderMesh::markPartCallback(void* ud, SoEventCallback* n) void ViewProviderMesh::faceInfo(Mesh::FacetIndex uFacet) { - Mesh::Feature* fea = static_cast(this->getObject()); - const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rKernel = getMeshObject().getKernel(); const MeshCore::MeshFacetArray& facets = rKernel.GetFacets(); if (uFacet < facets.size()) { MeshCore::MeshFacet face = facets[uFacet]; @@ -1901,7 +1895,7 @@ void ViewProviderMesh::faceInfo(Mesh::FacetIndex uFacet) Base::Console().Message( "Mesh: %s Facet %lu: Points: <%lu, %lu, %lu>, Neighbours: <%lu, %lu, %lu>\n" "Triangle: <[%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f], [%.6f, %.6f, %.6f]>\n", - fea->getNameInDocument(), + getObject()->getNameInDocument(), uFacet, face._aulPoints[0], face._aulPoints[1], @@ -1930,8 +1924,7 @@ void ViewProviderMesh::fillHole(Mesh::FacetIndex uFacet) // get the boundary to the picked facet std::list aBorder; - Mesh::Feature* fea = static_cast(this->getObject()); - const MeshCore::MeshKernel& rKernel = fea->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rKernel = getMeshObject().getKernel(); MeshCore::MeshRefPointToFacets cPt2Fac(rKernel); MeshCore::MeshAlgorithm meshAlg(rKernel); meshAlg.GetFacetBorder(uFacet, aBorder); @@ -1961,7 +1954,7 @@ void ViewProviderMesh::fillHole(Mesh::FacetIndex uFacet) unsigned long countBoundaryPoints = boundary.size(); unsigned long countDifference = points.size() - countBoundaryPoints; if (countDifference > 0) { - MeshCore::MeshPointArray::_TIterator pt = points.begin() + countBoundaryPoints; + auto pt = points.begin() + countBoundaryPoints; for (unsigned long i = 0; i < countDifference; i++, pt++) { boundary.push_back(numberOfOldPoints++); newPoints.push_back(*pt); @@ -1983,9 +1976,10 @@ void ViewProviderMesh::fillHole(Mesh::FacetIndex uFacet) // add the facets to the mesh and open a transaction object for the undo/redo stuff Gui::Application::Instance->activeDocument()->openCommand( QT_TRANSLATE_NOOP("Command", "Fill hole")); - Mesh::MeshObject* kernel = fea->Mesh.startEditing(); + auto& prop = getMeshProperty(); + Mesh::MeshObject* kernel = prop.startEditing(); kernel->addFacets(newFacets, newPoints, true); - fea->Mesh.finishEditing(); + prop.finishEditing(); Gui::Application::Instance->activeDocument()->commitCommand(); } @@ -2020,13 +2014,15 @@ void ViewProviderMesh::resetFacetTransparency() } /*! The triangles with the passed indices are already added to the mesh. */ -void ViewProviderMesh::appendFacets(const std::vector&) -{} +void ViewProviderMesh::appendFacets(const std::vector& facets) +{ + (void)facets; +} void ViewProviderMesh::removeFacets(const std::vector& facets) { // Get the attached mesh property - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; + Mesh::PropertyMeshKernel& meshProp = getMeshProperty(); Mesh::MeshObject* kernel = meshProp.startEditing(); // get the colour property if there @@ -2088,7 +2084,7 @@ void ViewProviderMesh::selectFacet(Mesh::FacetIndex facet) std::vector selection; selection.push_back(facet); - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.addFacetsToSelection(selection); // Colorize the selection @@ -2108,7 +2104,7 @@ void ViewProviderMesh::deselectFacet(Mesh::FacetIndex facet) std::vector selection; selection.push_back(facet); - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.removeFacetsFromSelection(selection); // Colorize the selection @@ -2131,7 +2127,7 @@ void ViewProviderMesh::deselectFacet(Mesh::FacetIndex facet) bool ViewProviderMesh::isFacetSelected(Mesh::FacetIndex facet) { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); const MeshCore::MeshFacetArray& faces = rMesh.getKernel().GetFacets(); return faces[facet].IsFlag(MeshCore::MeshFacet::SELECTED); } @@ -2142,7 +2138,7 @@ void ViewProviderMesh::selectComponent(Mesh::FacetIndex uFacet) selection.push_back(uFacet); MeshCore::MeshTopFacetVisitor clVisitor(selection); - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); const MeshCore::MeshKernel& rKernel = rMesh.getKernel(); MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT); rKernel.VisitNeighbourFacets(clVisitor, uFacet); @@ -2158,7 +2154,7 @@ void ViewProviderMesh::deselectComponent(Mesh::FacetIndex uFacet) selection.push_back(uFacet); MeshCore::MeshTopFacetVisitor clVisitor(selection); - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); const MeshCore::MeshKernel& rKernel = rMesh.getKernel(); MeshCore::MeshAlgorithm(rKernel).ResetFacetFlag(MeshCore::MeshFacet::VISIT); rKernel.VisitNeighbourFacets(clVisitor, uFacet); @@ -2175,7 +2171,7 @@ void ViewProviderMesh::deselectComponent(Mesh::FacetIndex uFacet) void ViewProviderMesh::setSelection(const std::vector& indices) { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.clearFacetSelection(); rMesh.addFacetsToSelection(indices); @@ -2190,7 +2186,7 @@ void ViewProviderMesh::setSelection(const std::vector& indices void ViewProviderMesh::addSelection(const std::vector& indices) { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.addFacetsToSelection(indices); // Colorize the selection @@ -2199,7 +2195,7 @@ void ViewProviderMesh::addSelection(const std::vector& indices void ViewProviderMesh::removeSelection(const std::vector& indices) { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.removeFacetsFromSelection(indices); // Colorize the selection @@ -2213,7 +2209,7 @@ void ViewProviderMesh::removeSelection(const std::vector& indi void ViewProviderMesh::invertSelection() { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); const MeshCore::MeshFacetArray& faces = rMesh.getKernel().GetFacets(); MeshCore::MeshIsNotFlag flag; unsigned long num_notsel = @@ -2222,9 +2218,9 @@ void ViewProviderMesh::invertSelection() }); std::vector notselect; notselect.reserve(num_notsel); - MeshCore::MeshFacetArray::_TConstIterator beg = faces.begin(); - MeshCore::MeshFacetArray::_TConstIterator end = faces.end(); - for (MeshCore::MeshFacetArray::_TConstIterator jt = beg; jt != end; ++jt) { + auto beg = faces.begin(); + auto end = faces.end(); + for (auto jt = beg; jt != end; ++jt) { if (!jt->IsFlag(MeshCore::MeshFacet::SELECTED)) { notselect.push_back(jt - beg); } @@ -2234,7 +2230,7 @@ void ViewProviderMesh::invertSelection() void ViewProviderMesh::clearSelection() { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.clearFacetSelection(); unhighlightSelection(); } @@ -2242,8 +2238,7 @@ void ViewProviderMesh::clearSelection() void ViewProviderMesh::deleteSelection() { std::vector indices; - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - const Mesh::MeshObject& rMesh = meshProp.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.getFacetsFromSelection(indices); if (!indices.empty()) { rMesh.clearFacetSelection(); @@ -2254,8 +2249,7 @@ void ViewProviderMesh::deleteSelection() bool ViewProviderMesh::hasSelection() const { - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - const Mesh::MeshObject& rMesh = meshProp.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); return rMesh.hasSelectedFacets(); } @@ -2270,7 +2264,7 @@ void ViewProviderMesh::selectArea(short x, vp.setViewportPixels(x, y, w, h); std::vector faces = getFacetsOfRegion(vp, region, camera); - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.addFacetsToSelection(faces); // Colorize the selected part @@ -2280,7 +2274,7 @@ void ViewProviderMesh::selectArea(short x, void ViewProviderMesh::highlightSelection() { std::vector selection; - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); rMesh.getFacetsFromSelection(selection); if (selection.empty()) { // If no faces are selected then simply return even @@ -2326,7 +2320,7 @@ void ViewProviderMesh::setHighlightedComponents(bool on) void ViewProviderMesh::highlightComponents() { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); std::vector> comps = rMesh.getComponents(); // Colorize the components @@ -2334,12 +2328,19 @@ void ViewProviderMesh::highlightComponents() int uCtFacets = (int)rMesh.countFacets(); pcShapeMaterial->diffuseColor.setNum(uCtFacets); + auto intRandom = [](int max) -> int { + static std::mt19937 generator; + std::uniform_int_distribution distribution(0, max); + return distribution(generator); + }; + + const int maxValue = 255; SbColor* cols = pcShapeMaterial->diffuseColor.startEditing(); for (const auto& comp : comps) { - float fMax = (float)RAND_MAX; - float fRed = (float)rand() / fMax; - float fGrn = (float)rand() / fMax; - float fBlu = (float)rand() / fMax; + float fMax = float(maxValue); + float fRed = float(intRandom(maxValue)) / fMax; + float fGrn = float(intRandom(maxValue)) / fMax; + float fBlu = float(intRandom(maxValue)) / fMax; for (Mesh::FacetIndex jt : comp) { cols[jt].setValue(fRed, fGrn, fBlu); } @@ -2362,7 +2363,7 @@ void ViewProviderMesh::setHighlightedSegments(bool on) void ViewProviderMesh::highlightSegments() { std::vector colors; - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); unsigned long numSegm = rMesh.countSegments(); colors.resize(numSegm, this->ShapeAppearance.getDiffuseColor()); @@ -2378,7 +2379,7 @@ void ViewProviderMesh::highlightSegments() void ViewProviderMesh::highlightSegments(const std::vector& colors) { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); unsigned long numSegm = rMesh.countSegments(); if (numSegm > 0 && numSegm == colors.size()) { // Colorize the components @@ -2421,16 +2422,16 @@ void ViewProviderMesh::setHighlightedColors(bool on) void ViewProviderMesh::highlightColors() { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); { - App::PropertyColorList* prop = Base::freecad_dynamic_cast( + auto prop = Base::freecad_dynamic_cast( pcObject->getPropertyByName("FaceColors")); if (prop && prop->getSize() == int(rMesh.countFacets())) { setColorPerFace(prop); } } { - App::PropertyColorList* prop = Base::freecad_dynamic_cast( + auto prop = Base::freecad_dynamic_cast( pcObject->getPropertyByName("VertexColors")); if (prop && prop->getSize() == int(rMesh.countPoints())) { setColorPerVertex(prop); @@ -2440,16 +2441,16 @@ void ViewProviderMesh::highlightColors() bool ViewProviderMesh::canHighlightColors() const { - const Mesh::MeshObject& rMesh = static_cast(pcObject)->Mesh.getValue(); + const Mesh::MeshObject& rMesh = getMeshObject(); { - App::PropertyColorList* prop = Base::freecad_dynamic_cast( + auto prop = Base::freecad_dynamic_cast( pcObject->getPropertyByName("FaceColors")); if (prop && prop->getSize() == int(rMesh.countFacets())) { return true; } } { - App::PropertyColorList* prop = Base::freecad_dynamic_cast( + auto prop = Base::freecad_dynamic_cast( pcObject->getPropertyByName("VertexColors")); if (prop && prop->getSize() == int(rMesh.countPoints())) { return true; @@ -2486,9 +2487,9 @@ ViewProviderIndexedFaceSet::~ViewProviderIndexedFaceSet() = default; * Extracts the mesh data from the feature \a pcFeature and creates * an Inventor node \a SoNode with these data. */ -void ViewProviderIndexedFaceSet::attach(App::DocumentObject* pcFeat) +void ViewProviderIndexedFaceSet::attach(App::DocumentObject* obj) { - ViewProviderMesh::attach(pcFeat); + ViewProviderMesh::attach(obj); pcMeshCoord = new SoCoordinate3; pcHighlight->addChild(pcMeshCoord); @@ -2499,7 +2500,7 @@ void ViewProviderIndexedFaceSet::attach(App::DocumentObject* pcFeat) // read the threshold from the preferences Base::Reference hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh"); - int size = hGrp->GetInt("RenderTriangleLimit", -1); + long size = hGrp->GetInt("RenderTriangleLimit", -1); if (size > 0) { static_cast(pcMeshFaces)->renderTriangleLimit = (unsigned int)(pow(10.0F, size)); @@ -2531,7 +2532,7 @@ void ViewProviderIndexedFaceSet::showOpenEdges(bool show) pcOpenEdge->addChild(pOpenColor); pcOpenEdge->addChild(pcMeshCoord); - SoIndexedLineSet* lines = new SoIndexedLineSet; + auto lines = new SoIndexedLineSet; pcOpenEdge->addChild(lines); // add to the highlight node @@ -2539,8 +2540,7 @@ void ViewProviderIndexedFaceSet::showOpenEdges(bool show) // Build up the lines with indices to the list of vertices 'pcMeshCoord' int index = 0; - const MeshCore::MeshKernel& rMesh = - static_cast(pcObject)->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshObject().getKernel(); const MeshCore::MeshFacetArray& rFaces = rMesh.GetFacets(); for (const auto& rFace : rFaces) { for (int i = 0; i < 3; i++) { @@ -2578,9 +2578,9 @@ ViewProviderMeshObject::ViewProviderMeshObject() ViewProviderMeshObject::~ViewProviderMeshObject() = default; -void ViewProviderMeshObject::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshObject::attach(App::DocumentObject* obj) { - ViewProviderMesh::attach(pcFeat); + ViewProviderMesh::attach(obj); pcMeshNode = new SoFCMeshObjectNode; pcHighlight->addChild(pcMeshNode); @@ -2591,7 +2591,7 @@ void ViewProviderMeshObject::attach(App::DocumentObject* pcFeat) // read the threshold from the preferences Base::Reference hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh"); - int size = hGrp->GetInt("RenderTriangleLimit", -1); + long size = hGrp->GetInt("RenderTriangleLimit", -1); if (size > 0) { pcMeshShape->renderTriangleLimit = (unsigned int)(pow(10.0F, size)); } @@ -2600,8 +2600,7 @@ void ViewProviderMeshObject::attach(App::DocumentObject* pcFeat) void ViewProviderMeshObject::updateData(const App::Property* prop) { ViewProviderMesh::updateData(prop); - if (prop->is()) { - const Mesh::PropertyMeshKernel* mesh = static_cast(prop); + if (const auto mesh = dynamic_cast(prop)) { this->pcMeshNode->mesh.setValue( Base::Reference(mesh->getValuePtr())); // Needs to update internal bounding box caches @@ -2639,3 +2638,4 @@ SoNode* ViewProviderMeshObject::getCoordNode() const { return this->pcMeshNode; } +// NOLINTEND(readability-magic-numbers,cppcoreguidelines-pro-bounds*) diff --git a/src/Mod/Mesh/Gui/ViewProvider.h b/src/Mod/Mesh/Gui/ViewProvider.h index 0858b415e72a..8f0ab1e23db0 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.h +++ b/src/Mod/Mesh/Gui/ViewProvider.h @@ -75,8 +75,10 @@ struct Material; namespace Mesh { +class MeshObject; class PropertyMaterial; -} +class PropertyMeshKernel; +} // namespace Mesh namespace MeshGui { @@ -87,7 +89,7 @@ class MeshGuiExport ViewProviderMeshBuilder: public Gui::ViewProviderBuilder { public: ViewProviderMeshBuilder() = default; - void buildNodes(const App::Property*, std::vector&) const override; + void buildNodes(const App::Property* prop, std::vector& nodes) const override; void createMesh(const App::Property*, SoCoordinate3*, SoIndexedFaceSet*) const; void createMesh(const MeshCore::MeshKernel&, SoCoordinate3*, SoIndexedFaceSet*) const; }; @@ -140,8 +142,8 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject App::PropertyColor LineColor; // NOLINTEND - void attach(App::DocumentObject*) override; - void updateData(const App::Property*) override; + void attach(App::DocumentObject* obj) override; + void updateData(const App::Property* prop) override; bool useNewSelectionModel() const override { return false; @@ -157,7 +159,7 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject std::vector getDisplayModes() const override; bool exportToVrml(const char* filename, const MeshCore::Material&, bool binary = false) const; void exportMesh(const char* filename, const char* fmt = nullptr) const; - void setupContextMenu(QMenu*, QObject*, const char*) override; + void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override; /// Get the python wrapper for that ViewProvider PyObject* getPyObject() override; @@ -189,9 +191,9 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject getVisibleFacetsAfterZoom(const SbBox2s&, const SbViewportRegion&, SoCamera*) const; std::vector getVisibleFacets(const SbViewportRegion&, SoCamera*) const; virtual void - cutMesh(const std::vector& picked, const Base::ViewProjMethod& proj, SbBool inner); + cutMesh(const std::vector& polygon, const Base::ViewProjMethod& proj, SbBool inner); virtual void - trimMesh(const std::vector& picked, const Base::ViewProjMethod& proj, SbBool inner); + trimMesh(const std::vector& polygon, const Base::ViewProjMethod& proj, SbBool inner); virtual void appendFacets(const std::vector&); virtual void removeFacets(const std::vector&); /*! The size of the array must be equal to the number of facets. */ @@ -235,6 +237,9 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject void tryColorPerVertexOrFace(bool); void setColorPerVertex(const App::PropertyColorList*); void setColorPerFace(const App::PropertyColorList*); + const Mesh::MeshObject& getMeshObject() const; + const Mesh::PropertyMeshKernel& getMeshProperty() const; + Mesh::PropertyMeshKernel& getMeshProperty(); void setColorField(const std::vector&, SoMFColor&); void setAmbientColor(const std::vector&); @@ -246,14 +251,14 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject virtual SoNode* getCoordNode() const; public: - static void faceInfoCallback(void* ud, SoEventCallback* n); - static void fillHoleCallback(void* ud, SoEventCallback* n); - static void markPartCallback(void* ud, SoEventCallback* n); - static void clipMeshCallback(void* ud, SoEventCallback* n); - static void trimMeshCallback(void* ud, SoEventCallback* n); - static void partMeshCallback(void* ud, SoEventCallback* n); - static void segmMeshCallback(void* ud, SoEventCallback* n); - static void selectGLCallback(void* ud, SoEventCallback* n); + static void faceInfoCallback(void* ud, SoEventCallback* cb); + static void fillHoleCallback(void* ud, SoEventCallback* cb); + static void markPartCallback(void* ud, SoEventCallback* cb); + static void clipMeshCallback(void* ud, SoEventCallback* cb); + static void trimMeshCallback(void* ud, SoEventCallback* cb); + static void partMeshCallback(void* ud, SoEventCallback* cb); + static void segmMeshCallback(void* ud, SoEventCallback* cb); + static void selectGLCallback(void* ud, SoEventCallback* cb); /// Creates a tool mesh from the previous picked polygon on the viewer static bool createToolMesh(const std::vector& rclPoly, const SbViewVolume& vol, @@ -287,10 +292,10 @@ class MeshGuiExport ViewProviderMesh: public Gui::ViewProviderGeometryObject // NOLINTEND private: - static App::PropertyFloatConstraint::Constraints floatRange; - static App::PropertyFloatConstraint::Constraints angleRange; - static App::PropertyIntegerConstraint::Constraints intPercent; - static const char* LightingEnums[]; + static const App::PropertyFloatConstraint::Constraints floatRange; + static const App::PropertyFloatConstraint::Constraints angleRange; + static const App::PropertyIntegerConstraint::Constraints intPercent; + static std::array LightingEnums; FC_DISABLE_COPY_MOVE(ViewProviderMesh) }; @@ -308,12 +313,12 @@ class MeshGuiExport ViewProviderIndexedFaceSet: public ViewProviderMesh ViewProviderIndexedFaceSet(); ~ViewProviderIndexedFaceSet() override; - void attach(App::DocumentObject*) override; + void attach(App::DocumentObject* obj) override; /// Update the Mesh representation - void updateData(const App::Property*) override; + void updateData(const App::Property* prop) override; protected: - void showOpenEdges(bool) override; + void showOpenEdges(bool show) override; SoShape* getShapeNode() const override; SoNode* getCoordNode() const override; @@ -337,13 +342,13 @@ class MeshGuiExport ViewProviderMeshObject: public ViewProviderMesh ViewProviderMeshObject(); ~ViewProviderMeshObject() override; - void attach(App::DocumentObject* pcFeat) override; - void updateData(const App::Property*) override; + void attach(App::DocumentObject* obj) override; + void updateData(const App::Property* prop) override; protected: SoShape* getShapeNode() const override; SoNode* getCoordNode() const override; - void showOpenEdges(bool) override; + void showOpenEdges(bool show) override; private: SoFCMeshObjectNode* pcMeshNode; diff --git a/src/Mod/Mesh/Gui/ViewProviderCurvature.cpp b/src/Mod/Mesh/Gui/ViewProviderCurvature.cpp index c3bfd13e025c..8124a7574311 100644 --- a/src/Mod/Mesh/Gui/ViewProviderCurvature.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderCurvature.cpp @@ -93,6 +93,7 @@ ViewProviderMeshCurvature::ViewProviderMeshCurvature() App::Material mat; const SbColor* cols {}; + // NOLINTBEGIN if (pcColorMat->ambientColor.getNum() == 1) { cols = pcColorMat->ambientColor.getValues(0); mat.ambientColor.setPackedValue(cols[0].getPackedValue()); @@ -117,6 +118,7 @@ ViewProviderMeshCurvature::ViewProviderMeshCurvature() const float* trans = pcColorMat->transparency.getValues(0); mat.transparency = trans[0]; } + // NOLINTEND ADD_PROPERTY(TextureMaterial, (mat)); SelectionStyle.setValue(1); // BBOX @@ -162,10 +164,12 @@ void ViewProviderMeshCurvature::show() pcColorStyle->style = SoDrawStyle::FILLED; } -void ViewProviderMeshCurvature::init(const Mesh::PropertyCurvatureList* pCurvInfo) +void ViewProviderMeshCurvature::init(const Mesh::PropertyCurvatureList* prop) { - std::vector aMinValues, aMaxValues; - const std::vector& fCurvInfo = pCurvInfo->getValues(); + // NOLINTBEGIN(readability-magic-numbers) + std::vector aMinValues; + std::vector aMaxValues; + const std::vector& fCurvInfo = prop->getValues(); aMinValues.reserve(fCurvInfo.size()); aMaxValues.reserve(fCurvInfo.size()); @@ -191,7 +195,7 @@ void ViewProviderMeshCurvature::init(const Mesh::PropertyCurvatureList* pCurvInf float fRMin = -1.0F; for (const auto& mIt : aHistogram) { if ((float)mIt.second / (float)aMinValues.size() > 0.15F) { - fRMin = mIt.first * (fMax - fMin) / 10.0F + fMin; + fRMin = float(mIt.first) * (fMax - fMin) / 10.0F + fMin; break; } } @@ -207,13 +211,13 @@ void ViewProviderMeshCurvature::init(const Mesh::PropertyCurvatureList* pCurvInf } float fRMax = 1.0F; - for (std::map::reverse_iterator rIt2 = aHistogram.rbegin(); rIt2 != aHistogram.rend(); - ++rIt2) { + for (auto rIt2 = aHistogram.rbegin(); rIt2 != aHistogram.rend(); ++rIt2) { if ((float)rIt2->second / (float)aMaxValues.size() > 0.15F) { - fRMax = rIt2->first * (fMax - fMin) / 10.0F + fMin; + fRMax = float(rIt2->first) * (fMax - fMin) / 10.0F + fMin; break; } } + // NOLINTEND(readability-magic-numbers) float fAbs = std::max(fabs(fRMin), fabs(fRMax)); fRMin = -fAbs; @@ -228,15 +232,17 @@ void ViewProviderMeshCurvature::slotChangedObject(const App::DocumentObject& Obj { // we get this for any object for that a property has changed. Thus, we must regard that object // which is linked by our link property - App::DocumentObject* object = static_cast(pcObject)->Source.getValue(); + App::DocumentObject* object = dynamic_cast(pcObject)->Source.getValue(); if (object == &Obj) { - const Mesh::PropertyMeshKernel& mesh = static_cast(object)->Mesh; - if ((&mesh) == (&Prop)) { - const Mesh::MeshObject& kernel = mesh.getValue(); - pcColorMat->diffuseColor.setNum((int)kernel.countPoints()); - pcColorMat->transparency.setNum((int)kernel.countPoints()); - // make sure to recompute the feature - static_cast(pcObject)->Source.touch(); + if (auto meshObject = dynamic_cast(object)) { + const Mesh::PropertyMeshKernel& mesh = meshObject->Mesh; + if ((&mesh) == (&Prop)) { + const Mesh::MeshObject& kernel = mesh.getValue(); + pcColorMat->diffuseColor.setNum((int)kernel.countPoints()); + pcColorMat->transparency.setNum((int)kernel.countPoints()); + // make sure to recompute the feature + dynamic_cast(pcObject)->Source.touch(); + } } } } @@ -254,19 +260,19 @@ void ViewProviderMeshCurvature::attach(App::DocumentObject* pcFeat) inherited::attach(pcFeat); attachDocument(pcFeat->getDocument()); - SoShapeHints* flathints = new SoShapeHints; + auto flathints = new SoShapeHints; flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; - SoGroup* pcColorShadedRoot = new SoGroup(); + auto pcColorShadedRoot = new SoGroup(); pcColorShadedRoot->addChild(flathints); // color shaded - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcColorShadedRoot->addChild(pcFlatStyle); - SoMaterialBinding* pcMatBinding = new SoMaterialBinding; + auto pcMatBinding = new SoMaterialBinding; pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED; pcColorShadedRoot->addChild(pcColorMat); pcColorShadedRoot->addChild(pcMatBinding); @@ -275,9 +281,8 @@ void ViewProviderMeshCurvature::attach(App::DocumentObject* pcFeat) addDisplayMaskMode(pcColorShadedRoot, "ColorShaded"); // Check for an already existing color bar - Gui::SoFCColorBar* pcBar = - ((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId())); - if (pcBar) { + auto node = findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()); + if (auto pcBar = dynamic_cast(node)) { float fMin = pcColorBar->getMinValue(); float fMax = pcColorBar->getMaxValue(); @@ -296,9 +301,8 @@ void ViewProviderMeshCurvature::attach(App::DocumentObject* pcFeat) void ViewProviderMeshCurvature::updateData(const App::Property* prop) { // set to the expected size - if (prop->isDerivedFrom()) { - Mesh::Feature* object = - static_cast(prop)->getValue(); + if (auto link = dynamic_cast(prop)) { + auto object = link->getValue(); Gui::coinRemoveAllChildren(this->pcLinkRoot); if (object) { const Mesh::MeshObject& kernel = object->Mesh.getValue(); @@ -308,23 +312,19 @@ void ViewProviderMeshCurvature::updateData(const App::Property* prop) // get the view provider of the associated mesh feature App::Document* rDoc = pcObject->getDocument(); Gui::Document* pDoc = Gui::Application::Instance->getDocument(rDoc); - ViewProviderMesh* view = static_cast(pDoc->getViewProvider(object)); - this->pcLinkRoot->addChild(view->getHighlightNode()); + if (auto view = dynamic_cast(pDoc->getViewProvider(object))) { + this->pcLinkRoot->addChild(view->getHighlightNode()); - Base::Placement p = - static_cast(view->getObject())->Placement.getValue(); - ViewProviderMesh::updateTransform(p, pcTransform); + auto mesh = dynamic_cast(view->getObject()); + Base::Placement plm = mesh->Placement.getValue(); + ViewProviderMesh::updateTransform(plm, pcTransform); + } } } - else if (prop->is()) { - const Mesh::PropertyCurvatureList* curv = - static_cast(prop); + else if (auto curv = dynamic_cast(prop)) { if (curv->getSize() < 3) { // invalid array return; } -#if 0 // FIXME: Do not always change the range - init(curv); // init color bar -#endif setActiveMode(); } } @@ -337,7 +337,6 @@ SoSeparator* ViewProviderMeshCurvature::getFrontRoot() const void ViewProviderMeshCurvature::setVertexCurvatureMode(int mode) { using PropertyMap = std::map; - Mesh::PropertyCurvatureList* pCurvInfo = nullptr; PropertyMap Map; pcObject->getPropertyMap(Map); @@ -350,20 +349,22 @@ void ViewProviderMeshCurvature::setVertexCurvatureMode(int mode) return; // cannot display this feature type due to missing curvature property } - pCurvInfo = static_cast(it->second); + auto pCurvInfo = dynamic_cast(it->second); // curvature values std::vector fValues = pCurvInfo->getCurvature(mode); - pcColorMat->diffuseColor.setNum(fValues.size()); - pcColorMat->transparency.setNum(fValues.size()); + pcColorMat->diffuseColor.setNum(int(fValues.size())); + pcColorMat->transparency.setNum(int(fValues.size())); SbColor* diffcol = pcColorMat->diffuseColor.startEditing(); float* transp = pcColorMat->transparency.startEditing(); for (auto const& value : fValues | boost::adaptors::indexed(0)) { App::Color c = pcColorBar->getColor(value.value()); + // NOLINTBEGIN diffcol[value.index()].setValue(c.r, c.g, c.b); transp[value.index()] = c.transparency(); + // NOLINTEND } pcColorMat->diffuseColor.finishEditing(); @@ -459,7 +460,7 @@ class Annotation static void run(void* data, SoSensor* sensor) { - Annotation* self = static_cast(data); + auto self = static_cast(data); self->show(); delete self; delete sensor; @@ -469,22 +470,21 @@ class Annotation { App::Document* doc = vp->getObject()->getDocument(); - std::vector groups = - doc->getObjectsOfType(App::DocumentObjectGroup::getClassTypeId()); + auto groups = doc->getObjectsOfType(); App::DocumentObjectGroup* group = nullptr; std::string internalname = "CurvatureGroup"; for (const auto& it : groups) { if (internalname == it->getNameInDocument()) { - group = static_cast(it); + group = it; break; } } if (!group) { - group = static_cast( + group = dynamic_cast( doc->addObject("App::DocumentObjectGroup", internalname.c_str())); } - App::AnnotationLabel* anno = static_cast( + auto anno = dynamic_cast( group->addObject("App::AnnotationLabel", internalname.c_str())); QStringList lines = s.split(QLatin1String("\n")); std::vector text; @@ -510,13 +510,13 @@ class Annotation void ViewProviderMeshCurvature::curvatureInfoCallback(void* ud, SoEventCallback* n) { - Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + auto view = static_cast(n->getUserData()); const SoEvent* ev = n->getEvent(); if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) { - const SoMouseButtonEvent* mbe = static_cast(ev); + const auto mbe = static_cast(ev); // NOLINT - // Mark all incoming mouse button events as handled, especially, to deactivate the selection - // node + // Mark all incoming mouse button events as handled, especially, to deactivate the + // selection node n->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { @@ -552,28 +552,26 @@ void ViewProviderMeshCurvature::curvatureInfoCallback(void* ud, SoEventCallback* // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath()); - if (!vp || !vp->isDerivedFrom()) { - return; - } - ViewProviderMeshCurvature* self = static_cast(vp); - const SoDetail* detail = point->getDetail(point->getPath()->getTail()); - if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { - const SoFaceDetail* facedetail = static_cast(detail); - // get the curvature info of the three points of the picked facet - int index1 = facedetail->getPoint(0)->getCoordinateIndex(); - int index2 = facedetail->getPoint(1)->getCoordinateIndex(); - int index3 = facedetail->getPoint(2)->getCoordinateIndex(); - std::string info = self->curvatureInfo(true, index1, index2, index3); - QString text = QString::fromLatin1(info.c_str()); - if (addflag) { - SbVec3f pt = point->getPoint(); - SbVec3f nl = point->getNormal(); - Annotation* anno = new Annotation(self, text, pt, nl); - SoIdleSensor* sensor = new SoIdleSensor(Annotation::run, anno); - sensor->schedule(); - } - else { - Gui::ToolTip::showText(QCursor::pos(), text); + if (auto self = dynamic_cast(vp)) { + const SoDetail* detail = point->getDetail(point->getPath()->getTail()); + if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { + const auto facedetail = static_cast(detail); // NOLINT + // get the curvature info of the three points of the picked facet + int index1 = facedetail->getPoint(0)->getCoordinateIndex(); + int index2 = facedetail->getPoint(1)->getCoordinateIndex(); + int index3 = facedetail->getPoint(2)->getCoordinateIndex(); + std::string info = self->curvatureInfo(true, index1, index2, index3); + QString text = QString::fromLatin1(info.c_str()); + if (addflag) { + SbVec3f pt = point->getPoint(); + SbVec3f nl = point->getNormal(); + auto anno = new Annotation(self, text, pt, nl); + auto sensor = new SoIdleSensor(Annotation::run, anno); + sensor->schedule(); + } + else { + Gui::ToolTip::showText(QCursor::pos(), text); + } } } } @@ -588,19 +586,17 @@ void ViewProviderMeshCurvature::curvatureInfoCallback(void* ud, SoEventCallback* // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath()); - if (!vp || !vp->isDerivedFrom()) { - return; - } - ViewProviderMeshCurvature* that = static_cast(vp); - const SoDetail* detail = point->getDetail(point->getPath()->getTail()); - if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { - const SoFaceDetail* facedetail = static_cast(detail); - // get the curvature info of the three points of the picked facet - int index1 = facedetail->getPoint(0)->getCoordinateIndex(); - int index2 = facedetail->getPoint(1)->getCoordinateIndex(); - int index3 = facedetail->getPoint(2)->getCoordinateIndex(); - std::string info = that->curvatureInfo(false, index1, index2, index3); - Gui::getMainWindow()->setPaneText(1, QString::fromLatin1(info.c_str())); + if (auto self = dynamic_cast(vp)) { + const SoDetail* detail = point->getDetail(point->getPath()->getTail()); + if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) { + const auto facedetail = static_cast(detail); // NOLINT + // get the curvature info of the three points of the picked facet + int index1 = facedetail->getPoint(0)->getCoordinateIndex(); + int index2 = facedetail->getPoint(1)->getCoordinateIndex(); + int index3 = facedetail->getPoint(2)->getCoordinateIndex(); + std::string info = self->curvatureInfo(false, index1, index2, index3); + Gui::getMainWindow()->setPaneText(1, QString::fromLatin1(info.c_str())); + } } } } @@ -611,8 +607,7 @@ ViewProviderMeshCurvature::curvatureInfo(bool detail, int index1, int index2, in // get the curvature info of the three points of the picked facet App::Property* prop = pcObject->getPropertyByName("CurvInfo"); std::stringstream str; - if (prop && prop->is()) { - Mesh::PropertyCurvatureList* curv = static_cast(prop); + if (auto curv = dynamic_cast(prop)) { const Mesh::CurvatureInfo& cVal1 = (*curv)[index1]; const Mesh::CurvatureInfo& cVal2 = (*curv)[index2]; const Mesh::CurvatureInfo& cVal3 = (*curv)[index3]; @@ -638,9 +633,11 @@ ViewProviderMeshCurvature::curvatureInfo(bool detail, int index1, int index2, in fVal3 = cVal3.fMaxCurvature * cVal3.fMinCurvature; } else if (mode == "Mean curvature") { + // NOLINTBEGIN(readability-magic-numbers) fVal1 = 0.5F * (cVal1.fMaxCurvature + cVal1.fMinCurvature); fVal2 = 0.5F * (cVal2.fMaxCurvature + cVal2.fMinCurvature); fVal3 = 0.5F * (cVal3.fMaxCurvature + cVal3.fMinCurvature); + // NOLINTEND(readability-magic-numbers) } else if (mode == "Absolute curvature") { fVal1 = fabs(cVal1.fMaxCurvature) > fabs(cVal1.fMinCurvature) ? cVal1.fMaxCurvature @@ -659,12 +656,13 @@ ViewProviderMeshCurvature::curvatureInfo(bool detail, int index1, int index2, in str << mode << ": <" << fVal1 << ", " << fVal2 << ", " << fVal3 << ">"; } else { + const int prec = 5; str.setf(std::ios::fixed | std::ios::showpoint); - str.precision(5); + str.precision(prec); str << mode << std::endl - << "v1: " << std::setw(5) << fVal1 << std::endl - << "v2: " << std::setw(5) << fVal2 << std::endl - << "v3: " << std::setw(5) << fVal3; + << "v1: " << std::setw(prec) << fVal1 << std::endl + << "v2: " << std::setw(prec) << fVal2 << std::endl + << "v3: " << std::setw(prec) << fVal3; } } else if (!detail) { diff --git a/src/Mod/Mesh/Gui/ViewProviderCurvature.h b/src/Mod/Mesh/Gui/ViewProviderCurvature.h index f015e4a16d13..488148c9e67a 100644 --- a/src/Mod/Mesh/Gui/ViewProviderCurvature.h +++ b/src/Mod/Mesh/Gui/ViewProviderCurvature.h @@ -90,7 +90,7 @@ class MeshGuiExport ViewProviderMeshCurvature: public Gui::ViewProviderDocumentO /// Returns a list of all possible modes std::vector getDisplayModes() const override; /// Updates the mesh feature representation - void updateData(const App::Property*) override; + void updateData(const App::Property* prop) override; /// Returns a pixmap for the associated feature type QIcon getIcon() const override; /// Once the color bar settinhs has been changed this method gets called to update the feature's diff --git a/src/Mod/Mesh/Gui/ViewProviderDefects.cpp b/src/Mod/Mesh/Gui/ViewProviderDefects.cpp index a16646a1fad0..161decef1283 100644 --- a/src/Mod/Mesh/Gui/ViewProviderDefects.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderDefects.cpp @@ -45,7 +45,7 @@ using namespace Mesh; using namespace MeshGui; - +// NOLINTBEGIN PROPERTY_SOURCE_ABSTRACT(MeshGui::ViewProviderMeshDefects, Gui::ViewProviderDocumentObject) PROPERTY_SOURCE(MeshGui::ViewProviderMeshOrientation, MeshGui::ViewProviderMeshDefects) PROPERTY_SOURCE(MeshGui::ViewProviderMeshNonManifolds, MeshGui::ViewProviderMeshDefects) @@ -56,7 +56,9 @@ PROPERTY_SOURCE(MeshGui::ViewProviderMeshDegenerations, MeshGui::ViewProviderMes PROPERTY_SOURCE(MeshGui::ViewProviderMeshIndices, MeshGui::ViewProviderMeshDefects) PROPERTY_SOURCE(MeshGui::ViewProviderMeshSelfIntersections, MeshGui::ViewProviderMeshDefects) PROPERTY_SOURCE(MeshGui::ViewProviderMeshFolds, MeshGui::ViewProviderMeshDefects) +// NOLINTEND +// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-pro-bounds*) ViewProviderMeshDefects::ViewProviderMeshDefects() { ADD_PROPERTY(LineWidth, (2.0F)); @@ -66,7 +68,7 @@ ViewProviderMeshDefects::ViewProviderMeshDefects() pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); pcDrawStyle->style = SoDrawStyle::LINES; - pcDrawStyle->lineWidth = LineWidth.getValue(); + pcDrawStyle->lineWidth = float(LineWidth.getValue()); } ViewProviderMeshDefects::~ViewProviderMeshDefects() @@ -78,7 +80,7 @@ ViewProviderMeshDefects::~ViewProviderMeshDefects() void ViewProviderMeshDefects::onChanged(const App::Property* prop) { if (prop == &LineWidth) { - pcDrawStyle->lineWidth = LineWidth.getValue(); + pcDrawStyle->lineWidth = float(LineWidth.getValue()); } // Visibility changes must be handled here because in the base class it changes the attribute of // the feature and thus affects the visibility of the mesh view provider which is undesired @@ -91,6 +93,24 @@ void ViewProviderMeshDefects::onChanged(const App::Property* prop) } } +SoMarkerSet* ViewProviderMeshDefects::makeMarkerSet() const +{ + auto marker = new SoMarkerSet; + marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( + "PLUS", + int(App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") + ->GetInt("MarkerSize", 7))); + return marker; +} + +const MeshCore::MeshKernel& ViewProviderMeshDefects::getMeshKernel() const +{ + auto mf = dynamic_cast(pcObject); + const Mesh::MeshObject& mesh = mf->Mesh.getValue(); + return mesh.getKernel(); +} + // ---------------------------------------------------------------------- ViewProviderMeshOrientation::ViewProviderMeshOrientation() @@ -106,38 +126,33 @@ ViewProviderMeshOrientation::~ViewProviderMeshOrientation() pcFaces->unref(); } -void ViewProviderMeshOrientation::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshOrientation::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcFaceRoot = new SoGroup(); + auto pcFaceRoot = new SoGroup(); - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcFaceRoot->addChild(pcFlatStyle); - SoShapeHints* flathints = new SoShapeHints; + auto flathints = new SoShapeHints; flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; pcFaceRoot->addChild(flathints); // Draw faces - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); linesep->addChild(pcFaces); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -148,11 +163,10 @@ void ViewProviderMeshOrientation::attach(App::DocumentObject* pcFeat) void ViewProviderMeshOrientation::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(3 * inds.size()); + pcCoords->point.setNum(int(3 * inds.size())); MeshCore::MeshFacetIterator cF(rMesh); int i = 0; int j = 0; @@ -184,17 +198,17 @@ ViewProviderMeshNonManifolds::~ViewProviderMeshNonManifolds() pcLines->unref(); } -void ViewProviderMeshNonManifolds::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshNonManifolds::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcLineRoot = new SoGroup(); + auto pcLineRoot = new SoGroup(); pcDrawStyle->lineWidth = 3; pcLineRoot->addChild(pcDrawStyle); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.0F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -202,14 +216,9 @@ void ViewProviderMeshNonManifolds::attach(App::DocumentObject* pcFeat) pcLineRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -221,16 +230,14 @@ void ViewProviderMeshNonManifolds::showDefects(const std::vector(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(inds.size()); + pcCoords->point.setNum(int(inds.size())); MeshCore::MeshPointIterator cP(rMesh); int i = 0; int j = 0; - for (std::vector::const_iterator it = inds.begin(); it != inds.end(); - ++it) { + for (auto it = inds.begin(); it != inds.end(); ++it) { cP.Set(*it); pcCoords->point.set1Value(i++, cP->x, cP->y, cP->z); ++it; // go to end point @@ -257,17 +264,17 @@ ViewProviderMeshNonManifoldPoints::~ViewProviderMeshNonManifoldPoints() pcPoints->unref(); } -void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcPointRoot = new SoGroup(); + auto pcPointRoot = new SoGroup(); pcDrawStyle->pointSize = 3; pcPointRoot->addChild(pcDrawStyle); // Draw points - SoSeparator* pointsep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto pointsep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); pointsep->addChild(basecol); pointsep->addChild(pcCoords); @@ -275,14 +282,9 @@ void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* pcFeat) pcPointRoot->addChild(pointsep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); pointsep->addChild(markcol); pointsep->addChild(marker); @@ -291,10 +293,9 @@ void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* pcFeat) void ViewProviderMeshNonManifoldPoints::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(inds.size()); + pcCoords->point.setNum(int(inds.size())); MeshCore::MeshPointIterator cP(rMesh); int i = 0; for (Mesh::ElementIndex ind : inds) { @@ -320,24 +321,24 @@ ViewProviderMeshDuplicatedFaces::~ViewProviderMeshDuplicatedFaces() pcFaces->unref(); } -void ViewProviderMeshDuplicatedFaces::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshDuplicatedFaces::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcFaceRoot = new SoGroup(); + auto pcFaceRoot = new SoGroup(); - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcFaceRoot->addChild(pcFlatStyle); - SoShapeHints* flathints = new SoShapeHints; + auto flathints = new SoShapeHints; flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; pcFaceRoot->addChild(flathints); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.0F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -345,14 +346,9 @@ void ViewProviderMeshDuplicatedFaces::attach(App::DocumentObject* pcFeat) pcFaceRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -361,11 +357,10 @@ void ViewProviderMeshDuplicatedFaces::attach(App::DocumentObject* pcFeat) void ViewProviderMeshDuplicatedFaces::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(3 * inds.size()); + pcCoords->point.setNum(int(3 * inds.size())); MeshCore::MeshFacetIterator cF(rMesh); int i = 0; int j = 0; @@ -397,17 +392,17 @@ ViewProviderMeshDuplicatedPoints::~ViewProviderMeshDuplicatedPoints() pcPoints->unref(); } -void ViewProviderMeshDuplicatedPoints::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshDuplicatedPoints::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcPointRoot = new SoGroup(); + auto pcPointRoot = new SoGroup(); pcDrawStyle->pointSize = 3; pcPointRoot->addChild(pcDrawStyle); // Draw points - SoSeparator* pointsep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto pointsep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); pointsep->addChild(basecol); pointsep->addChild(pcCoords); @@ -415,14 +410,9 @@ void ViewProviderMeshDuplicatedPoints::attach(App::DocumentObject* pcFeat) pcPointRoot->addChild(pointsep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); pointsep->addChild(markcol); pointsep->addChild(marker); @@ -431,10 +421,9 @@ void ViewProviderMeshDuplicatedPoints::attach(App::DocumentObject* pcFeat) void ViewProviderMeshDuplicatedPoints::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(inds.size()); + pcCoords->point.setNum(int(inds.size())); MeshCore::MeshPointIterator cP(rMesh); int i = 0; for (Mesh::ElementIndex ind : inds) { @@ -460,17 +449,17 @@ ViewProviderMeshDegenerations::~ViewProviderMeshDegenerations() pcLines->unref(); } -void ViewProviderMeshDegenerations::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshDegenerations::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcLineRoot = new SoGroup(); + auto pcLineRoot = new SoGroup(); pcDrawStyle->lineWidth = 3; pcLineRoot->addChild(pcDrawStyle); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -478,14 +467,9 @@ void ViewProviderMeshDegenerations::attach(App::DocumentObject* pcFeat) pcLineRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -494,11 +478,10 @@ void ViewProviderMeshDegenerations::attach(App::DocumentObject* pcFeat) void ViewProviderMeshDegenerations::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(2 * inds.size()); + pcCoords->point.setNum(int(2 * inds.size())); MeshCore::MeshFacetIterator cF(rMesh); int i = 0; int j = 0; @@ -512,7 +495,8 @@ void ViewProviderMeshDegenerations::showDefects(const std::vectorpoint.set1Value(i++, cP1.x, cP1.y, cP1.z); @@ -571,24 +555,24 @@ ViewProviderMeshIndices::~ViewProviderMeshIndices() pcFaces->unref(); } -void ViewProviderMeshIndices::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshIndices::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcFaceRoot = new SoGroup(); + auto pcFaceRoot = new SoGroup(); - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcFaceRoot->addChild(pcFlatStyle); - SoShapeHints* flathints = new SoShapeHints; + auto flathints = new SoShapeHints; flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; pcFaceRoot->addChild(flathints); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -596,14 +580,9 @@ void ViewProviderMeshIndices::attach(App::DocumentObject* pcFeat) pcFaceRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -612,12 +591,11 @@ void ViewProviderMeshIndices::attach(App::DocumentObject* pcFeat) void ViewProviderMeshIndices::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); if (!inds.empty()) { pcCoords->point.deleteValues(0); - pcCoords->point.setNum(3 * inds.size()); + pcCoords->point.setNum(int(3 * inds.size())); MeshCore::MeshFacetIterator cF(rMesh); int i = 0; int j = 0; @@ -650,17 +628,17 @@ ViewProviderMeshSelfIntersections::~ViewProviderMeshSelfIntersections() pcLines->unref(); } -void ViewProviderMeshSelfIntersections::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshSelfIntersections::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcLineRoot = new SoGroup(); + auto pcLineRoot = new SoGroup(); pcDrawStyle->lineWidth = 3; pcLineRoot->addChild(pcDrawStyle); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.5F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -668,32 +646,26 @@ void ViewProviderMeshSelfIntersections::attach(App::DocumentObject* pcFeat) pcLineRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); addDisplayMaskMode(pcLineRoot, "Line"); } -void ViewProviderMeshSelfIntersections::showDefects(const std::vector& indices) +void ViewProviderMeshSelfIntersections::showDefects(const std::vector& inds) { - if (indices.size() % 2 != 0) { + if (inds.size() % 2 != 0) { return; } - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + + const MeshCore::MeshKernel& rMesh = getMeshKernel(); MeshCore::MeshEvalSelfIntersection eval(rMesh); std::vector> intersection; - std::vector::const_iterator it; - for (it = indices.begin(); it != indices.end();) { + for (auto it = inds.begin(); it != inds.end();) { Mesh::ElementIndex id1 = *it; ++it; Mesh::ElementIndex id2 = *it; @@ -705,7 +677,7 @@ void ViewProviderMeshSelfIntersections::showDefects(const std::vectorpoint.deleteValues(0); - pcCoords->point.setNum(2 * lines.size()); + pcCoords->point.setNum(int(2 * lines.size())); int i = 0; int j = 0; for (const auto& line : lines) { @@ -732,24 +704,24 @@ ViewProviderMeshFolds::~ViewProviderMeshFolds() pcFaces->unref(); } -void ViewProviderMeshFolds::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshFolds::attach(App::DocumentObject* obj) { - ViewProviderDocumentObject::attach(pcFeat); + ViewProviderDocumentObject::attach(obj); // NOLINT - SoGroup* pcFaceRoot = new SoGroup(); + auto pcFaceRoot = new SoGroup(); - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcFaceRoot->addChild(pcFlatStyle); - SoShapeHints* flathints = new SoShapeHints; + auto flathints = new SoShapeHints; flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; pcFaceRoot->addChild(flathints); // Draw lines - SoSeparator* linesep = new SoSeparator; - SoBaseColor* basecol = new SoBaseColor; + auto linesep = new SoSeparator; + auto basecol = new SoBaseColor; basecol->rgb.setValue(1.0F, 0.0F, 0.0F); linesep->addChild(basecol); linesep->addChild(pcCoords); @@ -757,14 +729,9 @@ void ViewProviderMeshFolds::attach(App::DocumentObject* pcFeat) pcFaceRoot->addChild(linesep); // Draw markers - SoBaseColor* markcol = new SoBaseColor; + auto markcol = new SoBaseColor; markcol->rgb.setValue(1.0F, 1.0F, 0.0F); - SoMarkerSet* marker = new SoMarkerSet; - marker->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( - "PLUS", - App::GetApplication() - .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") - ->GetInt("MarkerSize", 7)); + SoMarkerSet* marker = makeMarkerSet(); linesep->addChild(markcol); linesep->addChild(marker); @@ -773,11 +740,10 @@ void ViewProviderMeshFolds::attach(App::DocumentObject* pcFeat) void ViewProviderMeshFolds::showDefects(const std::vector& inds) { - Mesh::Feature* f = static_cast(pcObject); - const MeshCore::MeshKernel& rMesh = f->Mesh.getValue().getKernel(); + const MeshCore::MeshKernel& rMesh = getMeshKernel(); pcCoords->point.deleteValues(0); - pcCoords->point.setNum(3 * inds.size()); + pcCoords->point.setNum(int(3 * inds.size())); MeshCore::MeshFacetIterator cF(rMesh); int i = 0; int j = 0; @@ -793,3 +759,4 @@ void ViewProviderMeshFolds::showDefects(const std::vector& i setDisplayMaskMode("Face"); } +// NOLINTEND(readability-magic-numbers,cppcoreguidelines-pro-bounds*) diff --git a/src/Mod/Mesh/Gui/ViewProviderDefects.h b/src/Mod/Mesh/Gui/ViewProviderDefects.h index 69fd2cf1bac3..d5b91c809d82 100644 --- a/src/Mod/Mesh/Gui/ViewProviderDefects.h +++ b/src/Mod/Mesh/Gui/ViewProviderDefects.h @@ -29,6 +29,7 @@ class SoCoordinate3; class SoPointSet; class SoLineSet; class SoFaceSet; +class SoMarkerSet; namespace MeshGui { @@ -52,13 +53,15 @@ class MeshGuiExport ViewProviderMeshDefects: public Gui::ViewProviderDocumentObj // NOLINTEND // Build up the initial Inventor node - void attach(App::DocumentObject* pcFeature) override = 0; + void attach(App::DocumentObject* obj) override = 0; /// Fill up the Inventor node with data virtual void showDefects(const std::vector&) = 0; protected: /// get called by the container whenever a property has been changed void onChanged(const App::Property* prop) override; + SoMarkerSet* makeMarkerSet() const; + const MeshCore::MeshKernel& getMeshKernel() const; protected: // NOLINTBEGIN @@ -82,8 +85,8 @@ class MeshGuiExport ViewProviderMeshOrientation: public ViewProviderMeshDefects ViewProviderMeshOrientation(); ~ViewProviderMeshOrientation() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoFaceSet* pcFaces; @@ -101,8 +104,8 @@ class MeshGuiExport ViewProviderMeshNonManifolds: public ViewProviderMeshDefects ViewProviderMeshNonManifolds(); ~ViewProviderMeshNonManifolds() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoLineSet* pcLines; @@ -120,8 +123,8 @@ class MeshGuiExport ViewProviderMeshNonManifoldPoints: public ViewProviderMeshDe ViewProviderMeshNonManifoldPoints(); ~ViewProviderMeshNonManifoldPoints() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoPointSet* pcPoints; @@ -139,8 +142,8 @@ class MeshGuiExport ViewProviderMeshDuplicatedFaces: public ViewProviderMeshDefe ViewProviderMeshDuplicatedFaces(); ~ViewProviderMeshDuplicatedFaces() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoFaceSet* pcFaces; @@ -159,8 +162,8 @@ class MeshGuiExport ViewProviderMeshDegenerations: public ViewProviderMeshDefect ViewProviderMeshDegenerations(); ~ViewProviderMeshDegenerations() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoLineSet* pcLines; @@ -175,8 +178,8 @@ class MeshGuiExport ViewProviderMeshDuplicatedPoints: public ViewProviderMeshDef ViewProviderMeshDuplicatedPoints(); ~ViewProviderMeshDuplicatedPoints() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoPointSet* pcPoints; @@ -191,8 +194,8 @@ class MeshGuiExport ViewProviderMeshIndices: public ViewProviderMeshDefects ViewProviderMeshIndices(); ~ViewProviderMeshIndices() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoFaceSet* pcFaces; @@ -210,8 +213,8 @@ class MeshGuiExport ViewProviderMeshSelfIntersections: public ViewProviderMeshDe ViewProviderMeshSelfIntersections(); ~ViewProviderMeshSelfIntersections() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoLineSet* pcLines; @@ -226,8 +229,8 @@ class MeshGuiExport ViewProviderMeshFolds: public ViewProviderMeshDefects ViewProviderMeshFolds(); ~ViewProviderMeshFolds() override; - void attach(App::DocumentObject* pcFeature) override; - void showDefects(const std::vector&) override; + void attach(App::DocumentObject* obj) override; + void showDefects(const std::vector& inds) override; private: SoFaceSet* pcFaces; diff --git a/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.cpp b/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.cpp index e503fea2ec0b..61c6efd4a567 100644 --- a/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.cpp @@ -79,9 +79,9 @@ ViewProviderMeshFaceSet::~ViewProviderMeshFaceSet() pcMeshFaces->unref(); } -void ViewProviderMeshFaceSet::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshFaceSet::attach(App::DocumentObject* obj) { - ViewProviderMesh::attach(pcFeat); + ViewProviderMesh::attach(obj); pcShapeGroup->addChild(pcMeshCoord); pcShapeGroup->addChild(pcMeshFaces); @@ -89,20 +89,19 @@ void ViewProviderMeshFaceSet::attach(App::DocumentObject* pcFeat) // read the threshold from the preferences Base::Reference hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("Mod/Mesh"); - int size = hGrp->GetInt("RenderTriangleLimit", -1); + long size = hGrp->GetInt("RenderTriangleLimit", -1); if (size > 0) { - pcMeshShape->renderTriangleLimit = (unsigned int)(pow(10.0F, size)); - static_cast(pcMeshFaces)->renderTriangleLimit = - (unsigned int)(pow(10.0F, size)); + unsigned int limit = (unsigned int)(pow(10.0F, size)); // NOLINT + pcMeshShape->renderTriangleLimit = limit; + static_cast(pcMeshFaces)->renderTriangleLimit = limit; } } void ViewProviderMeshFaceSet::updateData(const App::Property* prop) { ViewProviderMesh::updateData(prop); - if (prop->is()) { - const Mesh::MeshObject* mesh = - static_cast(prop)->getValuePtr(); + if (const auto* meshProp = dynamic_cast(prop)) { + const Mesh::MeshObject* mesh = meshProp->getValuePtr(); bool direct = MeshRenderer::shouldRenderDirectly(mesh->countFacets() > this->triangleCount); if (direct) { @@ -163,21 +162,23 @@ void ViewProviderMeshFaceSet::showOpenEdges(bool show) } else { pcOpenEdge->addChild(pcMeshCoord); - SoIndexedLineSet* lines = new SoIndexedLineSet; + auto lines = new SoIndexedLineSet; pcOpenEdge->addChild(lines); // Build up the lines with indices to the list of vertices 'pcMeshCoord' int index = 0; - const MeshCore::MeshKernel& rMesh = - static_cast(pcObject)->Mesh.getValue().getKernel(); - const MeshCore::MeshFacetArray& rFaces = rMesh.GetFacets(); + const Mesh::MeshObject& mesh = getMeshObject(); + const MeshCore::MeshKernel& kernel = mesh.getKernel(); + const MeshCore::MeshFacetArray& rFaces = kernel.GetFacets(); for (const auto& rFace : rFaces) { for (int i = 0; i < 3; i++) { + // NOLINTBEGIN if (rFace._aulNeighbours[i] == MeshCore::FACET_INDEX_MAX) { lines->coordIndex.set1Value(index++, rFace._aulPoints[i]); lines->coordIndex.set1Value(index++, rFace._aulPoints[(i + 1) % 3]); lines->coordIndex.set1Value(index++, SO_END_LINE_INDEX); } + // NOLINTEND } } } diff --git a/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h b/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h index 013fb24ecb19..20f532fe3585 100644 --- a/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h +++ b/src/Mod/Mesh/Gui/ViewProviderMeshFaceSet.h @@ -55,11 +55,11 @@ class MeshGuiExport ViewProviderMeshFaceSet: public ViewProviderMesh ViewProviderMeshFaceSet(); ~ViewProviderMeshFaceSet() override; - void attach(App::DocumentObject* pcFeat) override; - void updateData(const App::Property*) override; + void attach(App::DocumentObject* obj) override; + void updateData(const App::Property* prop) override; protected: - void showOpenEdges(bool) override; + void showOpenEdges(bool show) override; SoShape* getShapeNode() const override; SoNode* getCoordNode() const override; diff --git a/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp b/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp index 44f5efc0259c..371492c1f1f3 100644 --- a/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderMeshPyImp.cpp @@ -54,7 +54,7 @@ PyObject* ViewProviderMeshPy::setSelection(PyObject* args) selection.reserve(list.size()); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Py::Long index(*it); - Mesh::FacetIndex value = static_cast(index); + auto value = static_cast(index); selection.push_back(value); } @@ -75,7 +75,7 @@ PyObject* ViewProviderMeshPy::addSelection(PyObject* args) selection.reserve(list.size()); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Py::Long index(*it); - Mesh::FacetIndex value = static_cast(index); + auto value = static_cast(index); selection.push_back(value); } @@ -96,7 +96,7 @@ PyObject* ViewProviderMeshPy::removeSelection(PyObject* args) selection.reserve(list.size()); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Py::Long index(*it); - Mesh::FacetIndex value = static_cast(index); + auto value = static_cast(index); selection.push_back(value); } diff --git a/src/Mod/Mesh/Gui/ViewProviderTransform.cpp b/src/Mod/Mesh/Gui/ViewProviderTransform.cpp index a451c2a26d34..f174710b5677 100644 --- a/src/Mod/Mesh/Gui/ViewProviderTransform.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderTransform.cpp @@ -53,17 +53,17 @@ ViewProviderMeshTransform::~ViewProviderMeshTransform() pcTransformerDragger->unref(); } -void ViewProviderMeshTransform::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshTransform::attach(App::DocumentObject* obj) { // creates the standard viewing modes - ViewProviderMesh::attach(pcFeat); + ViewProviderMesh::attach(obj); - SoSeparator* pcEditRoot = new SoSeparator(); + auto pcEditRoot = new SoSeparator(); // flat shaded (Normal) ------------------------------------------ - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; - SoNormalBinding* pcBinding = new SoNormalBinding(); + auto pcBinding = new SoNormalBinding(); pcBinding->value = SoNormalBinding::PER_FACE; pcEditRoot->addChild(pcTransformerDragger); diff --git a/src/Mod/Mesh/Gui/ViewProviderTransform.h b/src/Mod/Mesh/Gui/ViewProviderTransform.h index d2ac7e6c4221..b53a131502f5 100644 --- a/src/Mod/Mesh/Gui/ViewProviderTransform.h +++ b/src/Mod/Mesh/Gui/ViewProviderTransform.h @@ -59,7 +59,7 @@ class ViewProviderMeshTransform: public ViewProviderMesh * Extracts the mesh data from the feature \a pcFeature and creates * an Inventor node \a SoNode with these data. */ - void attach(App::DocumentObject*) override; + void attach(App::DocumentObject* obj) override; /// set the viewing mode void setDisplayMode(const char* ModeName) override; diff --git a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp index 714fe832e1a9..611c266b4f3d 100644 --- a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp +++ b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.cpp @@ -67,26 +67,26 @@ ViewProviderMeshTransformDemolding::~ViewProviderMeshTransformDemolding() pcTrackballDragger->unref(); } -void ViewProviderMeshTransformDemolding::attach(App::DocumentObject* pcFeat) +void ViewProviderMeshTransformDemolding::attach(App::DocumentObject* obj) { // creates the standard viewing modes - ViewProviderMesh::attach(pcFeat); + ViewProviderMesh::attach(obj); - SoGroup* pcDemoldRoot = new SoGroup(); + auto pcDemoldRoot = new SoGroup(); - SoDrawStyle* pcFlatStyle = new SoDrawStyle(); + auto pcFlatStyle = new SoDrawStyle(); pcFlatStyle->style = SoDrawStyle::FILLED; pcDemoldRoot->addChild(pcFlatStyle); // dragger - SoSeparator* surroundsep = new SoSeparator; + auto surroundsep = new SoSeparator; - SoSurroundScale* ss = new SoSurroundScale; + auto ss = new SoSurroundScale; ss->numNodesUpToReset = 1; ss->numNodesUpToContainer = 2; surroundsep->addChild(ss); - SoAntiSquish* antisquish = new SoAntiSquish; + auto antisquish = new SoAntiSquish; antisquish->sizing = SoAntiSquish::AVERAGE_DIMENSION; surroundsep->addChild(antisquish); @@ -97,7 +97,7 @@ void ViewProviderMeshTransformDemolding::attach(App::DocumentObject* pcFeat) pcTransformDrag = new SoTransform(); - SoMaterialBinding* pcMatBinding = new SoMaterialBinding; + auto pcMatBinding = new SoMaterialBinding; pcMatBinding->value = SoMaterialBinding::PER_FACE_INDEXED; pcColorMat = new SoMaterial; @@ -116,15 +116,24 @@ void ViewProviderMeshTransformDemolding::attach(App::DocumentObject* pcFeat) calcNormalVector(); calcMaterialIndex(SbRotation()); + setCenterPoint(); +} + +void ViewProviderMeshTransformDemolding::setCenterPoint() +{ // getting center point - center = static_cast(pcObject)->Mesh.getValue().getKernel().GetBoundBox().GetCenter(); + const Mesh::MeshObject& mesh = getMeshObject(); + const MeshCore::MeshKernel& kernel = mesh.getKernel(); + Base::BoundBox3f bbox = kernel.GetBoundBox(); + center = bbox.GetCenter(); } void ViewProviderMeshTransformDemolding::calcNormalVector() { - const MeshKernel& cMesh = static_cast(pcObject)->Mesh.getValue().getKernel(); + const Mesh::MeshObject& mesh = getMeshObject(); + const MeshCore::MeshKernel& kernel = mesh.getKernel(); - MeshFacetIterator cFIt(cMesh); + MeshFacetIterator cFIt(kernel); for (cFIt.Init(); cFIt.More(); cFIt.Next()) { const MeshGeomFacet& rFace = *cFIt; @@ -144,12 +153,14 @@ void ViewProviderMeshTransformDemolding::calcMaterialIndex(const SbRotation& rot } } -void ViewProviderMeshTransformDemolding::sValueChangedCallback(void* This, SoDragger*) +void ViewProviderMeshTransformDemolding::sValueChangedCallback(void* This, + [[maybe_unused]] SoDragger* dragger) { static_cast(This)->valueChangedCallback(); } -void ViewProviderMeshTransformDemolding::sDragEndCallback(void* This, SoDragger*) +void ViewProviderMeshTransformDemolding::sDragEndCallback(void* This, + [[maybe_unused]] SoDragger* dragger) { static_cast(This)->DragEndCallback(); } diff --git a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.h b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.h index f051f89638fb..d538f0f7f29c 100644 --- a/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.h +++ b/src/Mod/Mesh/Gui/ViewProviderTransformDemolding.h @@ -63,7 +63,7 @@ class ViewProviderMeshTransformDemolding: public ViewProviderMesh * Extracts the mesh data from the feature \a pcFeature and creates * an Inventor node \a SoNode with these data. */ - void attach(App::DocumentObject*) override; + void attach(App::DocumentObject* obj) override; /// set the viewing mode void setDisplayMode(const char* ModeName) override; @@ -73,6 +73,7 @@ class ViewProviderMeshTransformDemolding: public ViewProviderMesh std::vector getDisplayModes() const override; protected: + void setCenterPoint(); void calcMaterialIndex(const SbRotation& rot); void calcNormalVector(); From fcea9343b31d8f33c788c721e259ad590e4c825c Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 21 Nov 2024 19:24:54 +0100 Subject: [PATCH 035/161] Mesh: Fix linter warnings --- src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp index 5b8fd7ce232c..f7bbc491ae08 100644 --- a/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp +++ b/src/Mod/Mesh/Gui/SoFCIndexedFaceSet.cpp @@ -133,11 +133,11 @@ void MeshRenderer::Private::generateGLArrays(SoGLRenderAction* action, indices.create(); vertices.bind(); - vertices.allocate(&(vertex[0]), vertex.size() * sizeof(float)); + vertices.allocate(vertex.data(), vertex.size() * sizeof(float)); vertices.release(); indices.bind(); - indices.allocate(&(index[0]), index.size() * sizeof(int32_t)); + indices.allocate(index.data(), index.size() * sizeof(int32_t)); indices.release(); this->matbinding = matbind; } @@ -630,7 +630,7 @@ void SoFCIndexedFaceSet::drawCoords(const SoGLCoordinateElement* const vertexlis coords3d = vertexlist->getArrayPtr3(); int mod = numindices / (4 * this->renderTriangleLimit) + 1; - float size = std::min((float)mod, 3.0f); + float size = std::min((float)mod, 3.0F); glPointSize(size); SbBool per_face = false; From 5771c94523d9ee101976916fbc916cd2d9b67d35 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 21 Nov 2024 12:27:35 +0100 Subject: [PATCH 036/161] App: Apply clang format (part 2) --- src/App/Color.cpp | 19 +- src/App/Color.h | 8 +- src/App/ColorModel.cpp | 272 +- src/App/ColorModel.h | 446 +-- src/App/ComplexGeoData.cpp | 26 +- src/App/ComplexGeoData.h | 213 +- src/App/Document.cpp | 2181 ++++++++------ src/App/Document.h | 334 ++- src/App/DocumentObject.cpp | 814 +++--- src/App/DocumentObject.h | 340 ++- src/App/ExpressionParser.h | 534 ++-- src/App/ExpressionTokenizer.cpp | 53 +- src/App/ExpressionTokenizer.h | 10 +- src/App/ExpressionVisitors.h | 106 +- src/App/FeatureTest.cpp | 211 +- src/App/FeatureTest.h | 213 +- src/App/GeoFeature.cpp | 105 +- src/App/GeoFeature.h | 78 +- src/App/Link.cpp | 2149 ++++++++------ src/App/Link.h | 714 +++-- src/App/LinkBaseExtensionPyImp.cpp | 247 +- src/App/LinkParams.py | 24 +- src/App/Metadata.h | 14 +- src/App/ObjectIdentifier.cpp | 1600 ++++++----- src/App/ObjectIdentifier.h | 480 ++-- src/App/Property.cpp | 168 +- src/App/Property.h | 317 ++- src/App/PropertyContainerPy.xml | 120 +- src/App/PropertyContainerPyImp.cpp | 342 ++- src/App/PropertyExpressionEngine.cpp | 663 +++-- src/App/PropertyExpressionEngine.h | 164 +- src/App/PropertyFile.cpp | 137 +- src/App/PropertyFile.h | 88 +- src/App/PropertyGeo.cpp | 540 ++-- src/App/PropertyGeo.h | 226 +- src/App/PropertyLinks.cpp | 3940 +++++++++++++++----------- src/App/PropertyLinks.h | 984 ++++--- src/App/PropertyPythonObject.cpp | 189 +- src/App/PropertyPythonObject.h | 35 +- src/App/PropertyStandard.cpp | 1127 ++++---- src/App/PropertyStandard.h | 502 ++-- src/App/PropertyUnits.cpp | 78 +- src/App/PropertyUnits.h | 67 +- src/App/private/DocumentP.h | 4 +- 44 files changed, 12135 insertions(+), 8747 deletions(-) diff --git a/src/App/Color.cpp b/src/App/Color.cpp index cfc5c59bfd10..0d2d93e16595 100644 --- a/src/App/Color.cpp +++ b/src/App/Color.cpp @@ -35,15 +35,14 @@ using namespace App; // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) Color::Color(float red, float green, float blue, float alpha) - : r(red) - , g(green) - , b(blue) - , a(alpha) -{ -} + : r(red) + , g(green) + , b(blue) + , a(alpha) +{} Color::Color(uint32_t rgba) - : Color{} + : Color {} { setPackedValue(rgba); } @@ -159,7 +158,7 @@ bool Color::fromHexString(const std::string& hex) if (hex.size() == 7) { std::stringstream ss(hex); unsigned int rgb; - char ch{}; + char ch {}; ss >> ch >> std::hex >> rgb; int rc = (rgb >> 16) & 0xff; @@ -176,13 +175,13 @@ bool Color::fromHexString(const std::string& hex) if (hex.size() == 9) { std::stringstream ss(hex); unsigned int rgba; - char ch{}; + char ch {}; ss >> ch >> std::hex >> rgba; int rc = (rgba >> 24) & 0xff; int gc = (rgba >> 16) & 0xff; int bc = (rgba >> 8) & 0xff; - int ac = rgba & 0xff; + int ac = rgba & 0xff; r = rc / 255.0F; g = gc / 255.0F; diff --git a/src/App/Color.h b/src/App/Color.h index 3697c437d730..c03a4fc11f00 100644 --- a/src/App/Color.h +++ b/src/App/Color.h @@ -72,7 +72,7 @@ struct color_traits } static color_type makeColor(int red, int green, int blue, int alpha = 255) { - return color_type{red, green, blue, alpha}; + return color_type {red, green, blue, alpha}; } private: @@ -146,7 +146,7 @@ class AppExport Color template static uint32_t asPackedRGBA(const T& color) { - color_traits ct{color}; + color_traits ct {color}; return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8) | ct.alpha(); } @@ -162,7 +162,7 @@ class AppExport Color template static uint32_t asPackedRGB(const T& color) { - color_traits ct{color}; + color_traits ct {color}; return (ct.red() << 24) | (ct.green() << 16) | (ct.blue() << 8); } @@ -179,7 +179,7 @@ class AppExport Color template void setValue(const T& q) { - color_traits ct{q}; + color_traits ct {q}; set(ct.redF(), ct.greenF(), ct.blueF()); } /** diff --git a/src/App/ColorModel.cpp b/src/App/ColorModel.cpp index 2bd3a306e81f..80e778c24424 100644 --- a/src/App/ColorModel.cpp +++ b/src/App/ColorModel.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -36,66 +36,66 @@ using namespace App; ColorModelPack ColorModelPack::createRedGreenBlue() { - ColorModelPack pack{ColorModelBlueGreenRed(), - ColorModelGreenYellowRed(), - ColorModelBlueCyanGreen(), - "Red-Yellow-Green-Cyan-Blue"}; + ColorModelPack pack {ColorModelBlueGreenRed(), + ColorModelGreenYellowRed(), + ColorModelBlueCyanGreen(), + "Red-Yellow-Green-Cyan-Blue"}; return pack; } ColorModelPack ColorModelPack::createBlueGreenRed() { - ColorModelPack pack{ColorModelRedGreenBlue(), - ColorModelGreenCyanBlue(), - ColorModelRedYellowGreen(), - "Blue-Cyan-Green-Yellow-Red"}; + ColorModelPack pack {ColorModelRedGreenBlue(), + ColorModelGreenCyanBlue(), + ColorModelRedYellowGreen(), + "Blue-Cyan-Green-Yellow-Red"}; return pack; } ColorModelPack ColorModelPack::createWhiteBlack() { - ColorModelPack pack{ColorModelBlackWhite(), - ColorModelGrayWhite(), - ColorModelBlackGray(), - "White-Black"}; + ColorModelPack pack {ColorModelBlackWhite(), + ColorModelGrayWhite(), + ColorModelBlackGray(), + "White-Black"}; return pack; } ColorModelPack ColorModelPack::createBlackWhite() { - ColorModelPack pack{ColorModelWhiteBlack(), - ColorModelGrayBlack(), - ColorModelWhiteGray(), - "Black-White"}; + ColorModelPack pack {ColorModelWhiteBlack(), + ColorModelGrayBlack(), + ColorModelWhiteGray(), + "Black-White"}; return pack; } ColorModelPack ColorModelPack::createRedWhiteBlue() { - ColorModelPack pack{ColorModelBlueWhiteRed(), - ColorModelWhiteRed(), - ColorModelBlueWhite(), - "Red-White-Blue"}; + ColorModelPack pack {ColorModelBlueWhiteRed(), + ColorModelWhiteRed(), + ColorModelBlueWhite(), + "Red-White-Blue"}; return pack; } -ColorField::ColorField () +ColorField::ColorField() { set(ColorModelBlueGreenRed(), -1.0f, 1.0f, 13); } -ColorField::ColorField (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt) +ColorField::ColorField(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt) { set(rclModel, fMin, fMax, usCt); } -ColorField& ColorField::operator = (const ColorField &rclCF) +ColorField& ColorField::operator=(const ColorField& rclCF) { colorField = rclCF.colorField; return *this; } -void ColorField::set (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt) +void ColorField::set(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt) { auto bounds = std::minmax(fMin, fMax); if (bounds.second <= bounds.first) { @@ -109,34 +109,37 @@ void ColorField::set (const ColorModel &rclModel, float fMin, float fMax, std::s rebuild(); } -void ColorField::setColorModel (const ColorModel &rclModel) +void ColorField::setColorModel(const ColorModel& rclModel) { colorModel = rclModel; rebuild(); } -void ColorField::rebuild () +void ColorField::rebuild() { colorField.resize(ctColors); - std::size_t usStep = std::min(ctColors / (colorModel.getCountColors() - 1), ctColors - 1); + std::size_t usStep = + std::min(ctColors / (colorModel.getCountColors() - 1), ctColors - 1); std::size_t usInd1 = 0; std::size_t usInd2 = usStep; for (std::size_t i = 0; i < (colorModel.getCountColors() - 1); i++) { - interpolate(colorModel.colors[i], usInd1, colorModel.colors[i+1], usInd2); + interpolate(colorModel.colors[i], usInd1, colorModel.colors[i + 1], usInd2); usInd1 = usInd2; - if ((i + 1) == (colorModel.getCountColors() - 2)) + if ((i + 1) == (colorModel.getCountColors() - 2)) { usInd2 = ctColors - 1; - else + } + else { usInd2 += usStep; + } } - fAscent = float(ctColors) / (fMax - fMin); + fAscent = float(ctColors) / (fMax - fMin); fConstant = -fAscent * fMin; } // fuellt das Array von Farbe 1, Index 1 bis Farbe 2, Index 2 -void ColorField::interpolate (Color clCol1, std::size_t usInd1, Color clCol2, std::size_t usInd2) +void ColorField::interpolate(Color clCol1, std::size_t usInd1, Color clCol2, std::size_t usInd2) { float fStep = 1.0f, fLen = float(usInd2 - usInd1); @@ -161,28 +164,37 @@ ColorGradientProfile::ColorGradientProfile() = default; bool ColorGradientProfile::isEqual(const ColorGradientProfile& cg) const { - if (tStyle != cg.tStyle) + if (tStyle != cg.tStyle) { return false; - if (fMin != cg.fMin) + } + if (fMin != cg.fMin) { return false; - if (fMax != cg.fMax) + } + if (fMax != cg.fMax) { return false; - if (!visibility.isEqual(cg.visibility)) + } + if (!visibility.isEqual(cg.visibility)) { return false; - if (tColorModel != cg.tColorModel) + } + if (tColorModel != cg.tColorModel) { return false; + } return true; } -ColorGradient::ColorGradient () +ColorGradient::ColorGradient() { createStandardPacks(); setColorModel(); set(-1.0f, 1.0f, 13, ColorBarStyle::ZERO_BASED, Visibility::Default); } -ColorGradient::ColorGradient (float fMin, float fMax, std::size_t usCtColors, ColorBarStyle tS, VisibilityFlags flags) +ColorGradient::ColorGradient(float fMin, + float fMax, + std::size_t usCtColors, + ColorBarStyle tS, + VisibilityFlags flags) { createStandardPacks(); setColorModel(); @@ -202,8 +214,9 @@ std::vector ColorGradient::getColorModelNames() const { std::vector names; names.reserve(modelPacks.size()); - for (const auto& it : modelPacks) + for (const auto& it : modelPacks) { names.push_back(it.description); + } return names; } @@ -214,7 +227,11 @@ void ColorGradient::setProfile(const ColorGradientProfile& pro) rebuild(); } -void ColorGradient::set (float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags flags) +void ColorGradient::set(float fMin, + float fMax, + std::size_t usCt, + ColorBarStyle tS, + VisibilityFlags flags) { auto bounds = std::minmax(fMin, fMax); if (bounds.second <= bounds.first) { @@ -229,74 +246,79 @@ void ColorGradient::set (float fMin, float fMax, std::size_t usCt, ColorBarStyle rebuild(); } -void ColorGradient::rebuild () +void ColorGradient::rebuild() { - switch (profile.tStyle) - { - case ColorBarStyle::FLOW: - { - colorField1.set(currentModelPack.totalModel, profile.fMin, profile.fMax, profile.ctColors); + switch (profile.tStyle) { + case ColorBarStyle::FLOW: { + colorField1.set(currentModelPack.totalModel, + profile.fMin, + profile.fMax, + profile.ctColors); break; } - case ColorBarStyle::ZERO_BASED: - { - if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) - { - colorField1.set(currentModelPack.bottomModel, profile.fMin, 0.0f, profile.ctColors / 2); - colorField2.set(currentModelPack.topModel, 0.0f, profile.fMax, profile.ctColors / 2); + case ColorBarStyle::ZERO_BASED: { + if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) { + colorField1.set(currentModelPack.bottomModel, + profile.fMin, + 0.0f, + profile.ctColors / 2); + colorField2.set(currentModelPack.topModel, + 0.0f, + profile.fMax, + profile.ctColors / 2); } - else if (profile.fMin >= 0.0f) + else if (profile.fMin >= 0.0f) { colorField1.set(currentModelPack.topModel, 0.0f, profile.fMax, profile.ctColors); - else + } + else { colorField1.set(currentModelPack.bottomModel, profile.fMin, 0.0f, profile.ctColors); + } break; } } } -std::size_t ColorGradient::getMinColors () const +std::size_t ColorGradient::getMinColors() const { - switch (profile.tStyle) - { - case ColorBarStyle::FLOW: - return colorField1.getMinColors(); - case ColorBarStyle::ZERO_BASED: - { - if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) + switch (profile.tStyle) { + case ColorBarStyle::FLOW: + return colorField1.getMinColors(); + case ColorBarStyle::ZERO_BASED: { + if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) { return colorField1.getMinColors() + colorField2.getMinColors(); - else + } + else { return colorField1.getMinColors(); + } } } return 2; } -void ColorGradient::setColorModel (std::size_t tModel) +void ColorGradient::setColorModel(std::size_t tModel) { profile.tColorModel = tModel; setColorModel(); rebuild(); } -void ColorGradient::setColorModel () +void ColorGradient::setColorModel() { - if (profile.tColorModel < modelPacks.size()) + if (profile.tColorModel < modelPacks.size()) { currentModelPack = modelPacks[profile.tColorModel]; - - switch (profile.tStyle) - { - case ColorBarStyle::FLOW: - { - colorField1.setColorModel(currentModelPack.totalModel); - colorField2.setColorModel(currentModelPack.bottomModel); - break; - } - case ColorBarStyle::ZERO_BASED: - { - colorField1.setColorModel(currentModelPack.topModel); - colorField2.setColorModel(currentModelPack.bottomModel); - break; } + + switch (profile.tStyle) { + case ColorBarStyle::FLOW: { + colorField1.setColorModel(currentModelPack.totalModel); + colorField2.setColorModel(currentModelPack.bottomModel); + break; + } + case ColorBarStyle::ZERO_BASED: { + colorField1.setColorModel(currentModelPack.topModel); + colorField2.setColorModel(currentModelPack.bottomModel); + break; + } } } @@ -317,60 +339,65 @@ ColorLegend::ColorLegend() values.push_back(1.0f); } -bool ColorLegend::operator == (const ColorLegend &rclCL) const +bool ColorLegend::operator==(const ColorLegend& rclCL) const { - return (colorFields.size() == rclCL.colorFields.size()) && - (names.size() == rclCL.names.size()) && - (values.size() == rclCL.values.size()) && - std::equal(colorFields.begin(), colorFields.end(), rclCL.colorFields.begin()) && - std::equal(names.begin(), names.end(), rclCL.names.begin()) && - std::equal(values.begin(), values.end(), rclCL.values.begin()) && - outsideGrayed == rclCL.outsideGrayed; + return (colorFields.size() == rclCL.colorFields.size()) && (names.size() == rclCL.names.size()) + && (values.size() == rclCL.values.size()) + && std::equal(colorFields.begin(), colorFields.end(), rclCL.colorFields.begin()) + && std::equal(names.begin(), names.end(), rclCL.names.begin()) + && std::equal(values.begin(), values.end(), rclCL.values.begin()) + && outsideGrayed == rclCL.outsideGrayed; } -float ColorLegend::getValue (std::size_t ulPos) const +float ColorLegend::getValue(std::size_t ulPos) const { - if (ulPos < values.size()) + if (ulPos < values.size()) { return values[ulPos]; - else + } + else { return 0.0f; + } } -bool ColorLegend::setValue (std::size_t ulPos, float fVal) +bool ColorLegend::setValue(std::size_t ulPos, float fVal) { - if (ulPos < values.size()) - { + if (ulPos < values.size()) { values[ulPos] = fVal; return true; } - else + else { return false; + } } -Color ColorLegend::getColor (std::size_t ulPos) const +Color ColorLegend::getColor(std::size_t ulPos) const { - if (ulPos < colorFields.size()) + if (ulPos < colorFields.size()) { return colorFields[ulPos]; - else + } + else { return Color(); + } } // color as: 0x00rrggbb -uint32_t ColorLegend::getPackedColor (std::size_t ulPos) const +uint32_t ColorLegend::getPackedColor(std::size_t ulPos) const { Color clRGB = getColor(ulPos); return clRGB.getPackedValue(); } -std::string ColorLegend::getText (std::size_t ulPos) const +std::string ColorLegend::getText(std::size_t ulPos) const { - if (ulPos < names.size()) + if (ulPos < names.size()) { return names[ulPos]; - else + } + else { return ""; + } } -std::size_t ColorLegend::addMin (const std::string &rclName) +std::size_t ColorLegend::addMin(const std::string& rclName) { names.push_front(rclName); values.push_front(values.front() - 1.0f); @@ -385,7 +412,7 @@ std::size_t ColorLegend::addMin (const std::string &rclName) return colorFields.size() - 1; } -std::size_t ColorLegend::addMax (const std::string &rclName) +std::size_t ColorLegend::addMax(const std::string& rclName) { names.push_back(rclName); values.push_back(values.back() + 1.0f); @@ -400,7 +427,7 @@ std::size_t ColorLegend::addMax (const std::string &rclName) return colorFields.size() - 1; } -bool ColorLegend::remove (std::size_t ulPos) +bool ColorLegend::remove(std::size_t ulPos) { if (ulPos < colorFields.size()) { colorFields.erase(colorFields.begin() + ulPos); @@ -413,7 +440,7 @@ bool ColorLegend::remove (std::size_t ulPos) return false; } -void ColorLegend::removeFirst () +void ColorLegend::removeFirst() { if (!colorFields.empty()) { colorFields.erase(colorFields.begin()); @@ -422,33 +449,36 @@ void ColorLegend::removeFirst () } } -void ColorLegend::removeLast () +void ColorLegend::removeLast() { if (!colorFields.empty()) { - colorFields.erase(colorFields.end()-1); - names.erase(names.end()-1); - values.erase(values.end()-1); + colorFields.erase(colorFields.end() - 1); + names.erase(names.end() - 1); + values.erase(values.end() - 1); } } -void ColorLegend::resize (std::size_t ulCt) +void ColorLegend::resize(std::size_t ulCt) { - if ((ulCt < 2) || (ulCt == colorFields.size())) + if ((ulCt < 2) || (ulCt == colorFields.size())) { return; + } if (ulCt > colorFields.size()) { int k = ulCt - colorFields.size(); - for (int i = 0; i < k; i++) + for (int i = 0; i < k; i++) { addMin("new"); + } } else { int k = colorFields.size() - ulCt; - for (int i = 0; i < k; i++) + for (int i = 0; i < k; i++) { removeLast(); + } } } -bool ColorLegend::setColor (std::size_t ulPos, float ucRed, float ucGreen, float ucBlue) +bool ColorLegend::setColor(std::size_t ulPos, float ucRed, float ucGreen, float ucBlue) { if (ulPos < names.size()) { colorFields[ulPos] = Color(ucRed, ucGreen, ucBlue); @@ -459,15 +489,15 @@ bool ColorLegend::setColor (std::size_t ulPos, float ucRed, float ucGreen, float } // color as 0x00rrggbb -bool ColorLegend::setColor (std::size_t ulPos, unsigned long ulColor) +bool ColorLegend::setColor(std::size_t ulPos, unsigned long ulColor) { - unsigned char ucRed = (unsigned char)((ulColor & 0x00ff0000) >> 16); + unsigned char ucRed = (unsigned char)((ulColor & 0x00ff0000) >> 16); unsigned char ucGreen = (unsigned char)((ulColor & 0x0000ff00) >> 8); - unsigned char ucBlue = (unsigned char)(ulColor & 0x000000ff); + unsigned char ucBlue = (unsigned char)(ulColor & 0x000000ff); return setColor(ulPos, ucRed, ucGreen, ucBlue); } -bool ColorLegend::setText (std::size_t ulPos, const std::string &rclName) +bool ColorLegend::setText(std::size_t ulPos, const std::string& rclName) { if (ulPos < names.size()) { names[ulPos] = rclName; diff --git a/src/App/ColorModel.h b/src/App/ColorModel.h index 5ca292642a07..8a5a897b3fb6 100644 --- a/src/App/ColorModel.h +++ b/src/App/ColorModel.h @@ -36,7 +36,8 @@ namespace App { -enum class Visibility { +enum class Visibility +{ Default, Grayed, Invisible @@ -44,12 +45,13 @@ enum class Visibility { using VisibilityFlags = Base::Flags; -enum class ColorBarStyle { +enum class ColorBarStyle +{ FLOW, ZERO_BASED }; -} +} // namespace App ENABLE_BITMASK_OPERATORS(App::Visibility) @@ -65,8 +67,8 @@ class AppExport ValueFloatToRGB virtual Color getColor(float fVal) const = 0; protected: - ValueFloatToRGB () = default; - virtual ~ValueFloatToRGB () = default; + ValueFloatToRGB() = default; + virtual ~ValueFloatToRGB() = default; }; @@ -74,22 +76,26 @@ class AppExport ColorModel { public: ColorModel() = default; - explicit ColorModel (std::size_t usCt) { + explicit ColorModel(std::size_t usCt) + { colors.resize(usCt); } ColorModel(const ColorModel&) = default; - virtual ~ColorModel () = default; - ColorModel& operator = (const ColorModel&) = default; - std::size_t getCountColors() const { + virtual ~ColorModel() = default; + ColorModel& operator=(const ColorModel&) = default; + std::size_t getCountColors() const + { return colors.size(); } std::vector colors; }; -class AppExport ColorModelBlueGreenRed : public ColorModel +class AppExport ColorModelBlueGreenRed: public ColorModel { public: - ColorModelBlueGreenRed () : ColorModel(5) { + ColorModelBlueGreenRed() + : ColorModel(5) + { colors[0] = Color(0, 0, 1); colors[1] = Color(0, 1, 1); colors[2] = Color(0, 1, 0); @@ -98,30 +104,36 @@ class AppExport ColorModelBlueGreenRed : public ColorModel } }; -class AppExport ColorModelBlueCyanGreen : public ColorModel +class AppExport ColorModelBlueCyanGreen: public ColorModel { public: - ColorModelBlueCyanGreen () : ColorModel(3) { + ColorModelBlueCyanGreen() + : ColorModel(3) + { colors[0] = Color(0, 0, 1); colors[1] = Color(0, 1, 1); colors[2] = Color(0, 1, 0); } }; -class AppExport ColorModelGreenYellowRed : public ColorModel +class AppExport ColorModelGreenYellowRed: public ColorModel { public: - ColorModelGreenYellowRed () : ColorModel(3) { + ColorModelGreenYellowRed() + : ColorModel(3) + { colors[0] = Color(0, 1, 0); colors[1] = Color(1, 1, 0); colors[2] = Color(1, 0, 0); } }; -class AppExport ColorModelRedGreenBlue : public ColorModel +class AppExport ColorModelRedGreenBlue: public ColorModel { public: - ColorModelRedGreenBlue () : ColorModel(5) { + ColorModelRedGreenBlue() + : ColorModel(5) + { colors[0] = Color(1, 0, 0); colors[1] = Color(1, 1, 0); colors[2] = Color(0, 1, 0); @@ -130,30 +142,36 @@ class AppExport ColorModelRedGreenBlue : public ColorModel } }; -class AppExport ColorModelGreenCyanBlue : public ColorModel +class AppExport ColorModelGreenCyanBlue: public ColorModel { public: - ColorModelGreenCyanBlue () : ColorModel(3) { + ColorModelGreenCyanBlue() + : ColorModel(3) + { colors[0] = Color(0, 1, 0); colors[1] = Color(0, 1, 1); colors[2] = Color(0, 0, 1); } }; -class AppExport ColorModelRedYellowGreen : public ColorModel +class AppExport ColorModelRedYellowGreen: public ColorModel { public: - ColorModelRedYellowGreen () : ColorModel(3) { + ColorModelRedYellowGreen() + : ColorModel(3) + { colors[0] = Color(1, 0, 0); colors[1] = Color(1, 1, 0); colors[2] = Color(0, 1, 0); } }; -class AppExport ColorModelBlueWhiteRed : public ColorModel +class AppExport ColorModelBlueWhiteRed: public ColorModel { public: - ColorModelBlueWhiteRed () : ColorModel(5) { + ColorModelBlueWhiteRed() + : ColorModel(5) + { colors[0] = Color(0, 0, 1); colors[1] = Color(float(85.0 / 255), float(170.0 / 255), 1); colors[2] = Color(1, 1, 1); @@ -162,75 +180,91 @@ class AppExport ColorModelBlueWhiteRed : public ColorModel } }; -class AppExport ColorModelBlueWhite : public ColorModel +class AppExport ColorModelBlueWhite: public ColorModel { public: - ColorModelBlueWhite () : ColorModel(3) { + ColorModelBlueWhite() + : ColorModel(3) + { colors[0] = Color(0, 0, 1); colors[1] = Color(float(85.0 / 255), float(170.0 / 255), 1); colors[2] = Color(1, 1, 1); } }; -class AppExport ColorModelWhiteRed : public ColorModel +class AppExport ColorModelWhiteRed: public ColorModel { public: - ColorModelWhiteRed () : ColorModel(3) { + ColorModelWhiteRed() + : ColorModel(3) + { colors[0] = Color(1, 1, 1); colors[1] = Color(1, float(85.0 / 255), 0); colors[2] = Color(1, 0, 0); } }; -class AppExport ColorModelBlackWhite : public ColorModel +class AppExport ColorModelBlackWhite: public ColorModel { public: - ColorModelBlackWhite () : ColorModel(2) { + ColorModelBlackWhite() + : ColorModel(2) + { colors[0] = Color(0, 0, 0); colors[1] = Color(1, 1, 1); } }; -class AppExport ColorModelBlackGray : public ColorModel +class AppExport ColorModelBlackGray: public ColorModel { public: - ColorModelBlackGray () : ColorModel(2) { + ColorModelBlackGray() + : ColorModel(2) + { colors[0] = Color(0.0f, 0.0f, 0.0f); colors[1] = Color(0.5f, 0.5f, 0.5f); } }; -class AppExport ColorModelGrayWhite : public ColorModel +class AppExport ColorModelGrayWhite: public ColorModel { public: - ColorModelGrayWhite () : ColorModel(2) { + ColorModelGrayWhite() + : ColorModel(2) + { colors[0] = Color(0.5f, 0.5f, 0.5f); colors[1] = Color(1.0f, 1.0f, 1.0f); } }; -class AppExport ColorModelWhiteBlack : public ColorModel +class AppExport ColorModelWhiteBlack: public ColorModel { public: - ColorModelWhiteBlack () : ColorModel(2) { + ColorModelWhiteBlack() + : ColorModel(2) + { colors[0] = Color(1, 1, 1); colors[1] = Color(0, 0, 0); } }; -class AppExport ColorModelWhiteGray : public ColorModel +class AppExport ColorModelWhiteGray: public ColorModel { public: - ColorModelWhiteGray () : ColorModel(2) { + ColorModelWhiteGray() + : ColorModel(2) + { colors[0] = Color(1.0f, 1.0f, 1.0f); colors[1] = Color(0.5f, 0.5f, 0.5f); } }; -class AppExport ColorModelGrayBlack : public ColorModel +class AppExport ColorModelGrayBlack: public ColorModel { public: - ColorModelGrayBlack () : ColorModel(2) { + ColorModelGrayBlack() + : ColorModel(2) + { colors[0] = Color(0.5f, 0.5f, 0.5f); colors[1] = Color(0.0f, 0.0f, 0.0f); } @@ -252,48 +286,59 @@ struct AppExport ColorModelPack class AppExport ColorField { public: - ColorField (); - ColorField (const ColorField &rclCF) = default; - ColorField (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt); - virtual ~ColorField () = default; + ColorField(); + ColorField(const ColorField& rclCF) = default; + ColorField(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt); + virtual ~ColorField() = default; - ColorField& operator = (const ColorField &rclCF); + ColorField& operator=(const ColorField& rclCF); - std::size_t getCountColors () const { + std::size_t getCountColors() const + { return ctColors; } - void set (const ColorModel &rclModel, float fMin, float fMax, std::size_t usCt); - void setCountColors (std::size_t usCt) { + void set(const ColorModel& rclModel, float fMin, float fMax, std::size_t usCt); + void setCountColors(std::size_t usCt) + { set(colorModel, fMin, fMax, usCt); } - void setRange (float fMin, float fMax) { + void setRange(float fMin, float fMax) + { set(colorModel, fMin, fMax, ctColors); } - void getRange (float &rfMin, float &rfMax) { - rfMin = fMin; rfMax = fMax; + void getRange(float& rfMin, float& rfMax) + { + rfMin = fMin; + rfMax = fMax; } - std::size_t getMinColors () const { + std::size_t getMinColors() const + { return colorModel.getCountColors(); } - void setColorModel (const ColorModel &rclModel); - const ColorModel& getColorModel () const { + void setColorModel(const ColorModel& rclModel); + const ColorModel& getColorModel() const + { return colorModel; } - void setDirect (std::size_t usInd, Color clCol) { + void setDirect(std::size_t usInd, Color clCol) + { colorField[usInd] = clCol; } - float getMinValue () const { + float getMinValue() const + { return fMin; } - float getMaxValue () const { + float getMaxValue() const + { return fMax; } - Color getColor (std::size_t usIndex) const { + Color getColor(std::size_t usIndex) const + { return colorField[usIndex]; } - inline Color getColor (float fVal) const; - inline std::size_t getColorIndex (float fVal) const; + inline Color getColor(float fVal) const; + inline std::size_t getColorIndex(float fVal) const; protected: ColorModel colorModel; @@ -302,32 +347,34 @@ class AppExport ColorField std::size_t ctColors; std::vector colorField; - void rebuild (); - void interpolate (Color clCol1, std::size_t usPos1, Color clCol2, std::size_t usPos2); + void rebuild(); + void interpolate(Color clCol1, std::size_t usPos1, Color clCol2, std::size_t usPos2); }; -inline Color ColorField::getColor (float fVal) const +inline Color ColorField::getColor(float fVal) const { // if the value is outside or at the border of the range std::size_t ct = colorModel.getCountColors() - 1; - if ( fVal <= fMin ) + if (fVal <= fMin) { return colorModel.colors[0]; - else if ( fVal >= fMax ) + } + else if (fVal >= fMax) { return colorModel.colors[ct]; + } // get the color field position (with 0 < t < 1) float t = (fVal - fMin) / (fMax - fMin); - Color col(1.0f, 1.0f, 1.0f); // white as default - for (std::size_t i=0; i(std::max(int(fConstant + fAscent * fVal), 0), int(ctColors - 1))); + return std::size_t( + std::min(std::max(int(fConstant + fAscent * fVal), 0), int(ctColors - 1))); } struct AppExport ColorGradientProfile { - ColorBarStyle tStyle{ColorBarStyle::FLOW}; - float fMin{}; - float fMax{}; - std::size_t ctColors{}; - std::size_t tColorModel{}; - VisibilityFlags visibility{Visibility::Default}; + ColorBarStyle tStyle {ColorBarStyle::FLOW}; + float fMin {}; + float fMax {}; + std::size_t ctColors {}; + std::size_t tColorModel {}; + VisibilityFlags visibility {Visibility::Default}; ColorGradientProfile(); - ColorGradientProfile (const ColorGradientProfile &) = default; - ColorGradientProfile& operator = (const ColorGradientProfile &) = default; + ColorGradientProfile(const ColorGradientProfile&) = default; + ColorGradientProfile& operator=(const ColorGradientProfile&) = default; bool isEqual(const ColorGradientProfile&) const; }; @@ -359,184 +407,217 @@ struct AppExport ColorGradientProfile class AppExport ColorGradient { public: - ColorGradient (); - ColorGradient (float fMin, float fMax, std::size_t usCtColors, ColorBarStyle tS, VisibilityFlags fl = Visibility::Default); - ColorGradient (const ColorGradient &) = default; - ColorGradient& operator = (const ColorGradient &) = default; - const ColorGradientProfile& getProfile() const { + ColorGradient(); + ColorGradient(float fMin, + float fMax, + std::size_t usCtColors, + ColorBarStyle tS, + VisibilityFlags fl = Visibility::Default); + ColorGradient(const ColorGradient&) = default; + ColorGradient& operator=(const ColorGradient&) = default; + const ColorGradientProfile& getProfile() const + { return profile; } void setProfile(const ColorGradientProfile& pro); - void set (float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags fl); - void setRange (float fMin, float fMax) { + void set(float fMin, float fMax, std::size_t usCt, ColorBarStyle tS, VisibilityFlags fl); + void setRange(float fMin, float fMax) + { set(fMin, fMax, profile.ctColors, profile.tStyle, profile.visibility); } - void getRange (float &rfMin, float &rfMax) const { + void getRange(float& rfMin, float& rfMax) const + { rfMin = profile.fMin; rfMax = profile.fMax; } - bool isOutOfRange(float fVal) const { + bool isOutOfRange(float fVal) const + { return ((fVal < profile.fMin) || (fVal > profile.fMax)); } - std::size_t getCountColors () const { + std::size_t getCountColors() const + { return profile.ctColors; } - void setCountColors (std::size_t usCt) { + void setCountColors(std::size_t usCt) + { set(profile.fMin, profile.fMax, usCt, profile.tStyle, profile.visibility); } - void setStyle (ColorBarStyle tS) { + void setStyle(ColorBarStyle tS) + { set(profile.fMin, profile.fMax, profile.ctColors, tS, profile.visibility); } - std::size_t getMinColors () const; - ColorBarStyle getStyle () const { + std::size_t getMinColors() const; + ColorBarStyle getStyle() const + { return profile.tStyle; } - void setOutsideGrayed (bool value) { + void setOutsideGrayed(bool value) + { profile.visibility.setFlag(Visibility::Grayed, value); } - bool isOutsideGrayed () const { + bool isOutsideGrayed() const + { return profile.visibility.testFlag(Visibility::Grayed); } - void setOutsideInvisible (bool value) { + void setOutsideInvisible(bool value) + { profile.visibility.setFlag(Visibility::Invisible, value); } - bool isOutsideInvisible () const { + bool isOutsideInvisible() const + { return profile.visibility.testFlag(Visibility::Invisible); } - void setColorModel (std::size_t tModel); - std::size_t getColorModelType () const { + void setColorModel(std::size_t tModel); + std::size_t getColorModelType() const + { return profile.tColorModel; } - inline const ColorModel& getColorModel () const; + inline const ColorModel& getColorModel() const; std::vector getColorModelNames() const; - float getMinValue () const { + float getMinValue() const + { return profile.fMin; } - float getMaxValue () const { + float getMaxValue() const + { return profile.fMax; } - inline Color getColor (float fVal) const; - inline std::size_t getColorIndex (float fVal) const; + inline Color getColor(float fVal) const; + inline std::size_t getColorIndex(float fVal) const; private: - inline Color _getColor (float fVal) const; + inline Color _getColor(float fVal) const; protected: void createStandardPacks(); protected: ColorGradientProfile profile; - ColorField colorField1, colorField2; + ColorField colorField1, colorField2; ColorModelPack currentModelPack; std::vector modelPacks; - void rebuild (); - void setColorModel (); + void rebuild(); + void setColorModel(); }; class AppExport ColorLegend { public: - ColorLegend (); - ColorLegend (const ColorLegend &rclCL) = default; - virtual ~ColorLegend () = default; - - ColorLegend& operator = (const ColorLegend &rclCL) = default; - bool operator == (const ColorLegend &rclCL) const; - bool operator != (const ColorLegend &rclCL) const { + ColorLegend(); + ColorLegend(const ColorLegend& rclCL) = default; + virtual ~ColorLegend() = default; + + ColorLegend& operator=(const ColorLegend& rclCL) = default; + bool operator==(const ColorLegend& rclCL) const; + bool operator!=(const ColorLegend& rclCL) const + { return !(*this == rclCL); } - void resize (std::size_t ulN); - std::size_t addMin (const std::string &rclName); - std::size_t addMax (const std::string &rclName); - bool remove (std::size_t ulPos); - void removeFirst (); - void removeLast (); - - Color getColor (std::size_t ulPos) const; - uint32_t getPackedColor (std::size_t ulPos) const; - bool setColor (std::size_t ulPos, float ucRed, float ucGreen, float ucBlue); - bool setColor (std::size_t ulPos, unsigned long ulColor); - float getValue (std::size_t ulPos) const; - bool setValue (std::size_t ulPos, float fVal); - std::string getText (std::size_t ulPos) const; - bool setText (std::size_t ulPos, const std::string &rclName); - std::size_t hasNumberOfFields () const { + void resize(std::size_t ulN); + std::size_t addMin(const std::string& rclName); + std::size_t addMax(const std::string& rclName); + bool remove(std::size_t ulPos); + void removeFirst(); + void removeLast(); + + Color getColor(std::size_t ulPos) const; + uint32_t getPackedColor(std::size_t ulPos) const; + bool setColor(std::size_t ulPos, float ucRed, float ucGreen, float ucBlue); + bool setColor(std::size_t ulPos, unsigned long ulColor); + float getValue(std::size_t ulPos) const; + bool setValue(std::size_t ulPos, float fVal); + std::string getText(std::size_t ulPos) const; + bool setText(std::size_t ulPos, const std::string& rclName); + std::size_t hasNumberOfFields() const + { return colorFields.size(); } - void setOutsideGrayed (bool bOS) { + void setOutsideGrayed(bool bOS) + { outsideGrayed = bOS; } - bool isOutsideGrayed () const { + bool isOutsideGrayed() const + { return outsideGrayed; } - inline float getMinValue () const; - inline float getMaxValue () const; + inline float getMinValue() const; + inline float getMaxValue() const; - inline Color getColor (float fVal) const; - inline std::size_t getColorIndex (float fVal) const; + inline Color getColor(float fVal) const; + inline std::size_t getColorIndex(float fVal) const; protected: std::deque colorFields; std::deque names; std::deque values; - bool outsideGrayed{false}; + bool outsideGrayed {false}; }; -inline Color ColorLegend::getColor (float fVal) const +inline Color ColorLegend::getColor(float fVal) const { std::deque::const_iterator pI; for (pI = values.begin(); pI != values.end(); ++pI) { - if (fVal < *pI) + if (fVal < *pI) { break; + } } if (outsideGrayed) { - if ((pI == values.begin()) || (pI == values.end())) + if ((pI == values.begin()) || (pI == values.end())) { return Color(0.5f, 0.5f, 0.5f); - else + } + else { return colorFields[pI - values.begin() - 1]; + } } - if (pI == values.begin()) + if (pI == values.begin()) { return *colorFields.begin(); - else if (pI == values.end()) - return *(colorFields.end()-1); - else + } + else if (pI == values.end()) { + return *(colorFields.end() - 1); + } + else { return colorFields[pI - values.begin() - 1]; + } } -inline std::size_t ColorLegend::getColorIndex (float fVal) const +inline std::size_t ColorLegend::getColorIndex(float fVal) const { std::deque::const_iterator pI; for (pI = values.begin(); pI != values.end(); ++pI) { - if (fVal < *pI) + if (fVal < *pI) { break; + } } - if (pI == values.begin()) + if (pI == values.begin()) { return 0; - else if (pI == values.end()) + } + else if (pI == values.end()) { return (std::size_t)(colorFields.size() - 1); - else + } + else { return pI - values.begin() - 1; + } } -inline float ColorLegend::getMinValue () const +inline float ColorLegend::getMinValue() const { return values.front(); } -inline float ColorLegend::getMaxValue () const +inline float ColorLegend::getMaxValue() const { return values.back(); } -inline Color ColorGradient::getColor (float fVal) const +inline Color ColorGradient::getColor(float fVal) const { Color color = _getColor(fVal); if (isOutsideInvisible()) { @@ -548,73 +629,78 @@ inline Color ColorGradient::getColor (float fVal) const return color; } -inline Color ColorGradient::_getColor (float fVal) const +inline Color ColorGradient::_getColor(float fVal) const { if (isOutsideGrayed()) { - if (isOutOfRange(fVal)) + if (isOutOfRange(fVal)) { return Color(0.5f, 0.5f, 0.5f); + } } switch (profile.tStyle) { - case ColorBarStyle::ZERO_BASED: - { + case ColorBarStyle::ZERO_BASED: { if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) { - if (fVal < 0.0f) + if (fVal < 0.0f) { return colorField1.getColor(fVal); - else + } + else { return colorField2.getColor(fVal); + } } else { return colorField1.getColor(fVal); } } - default: - case ColorBarStyle::FLOW: - { + default: + case ColorBarStyle::FLOW: { return colorField1.getColor(fVal); } } } -inline std::size_t ColorGradient::getColorIndex (float fVal) const +inline std::size_t ColorGradient::getColorIndex(float fVal) const { switch (profile.tStyle) { - case ColorBarStyle::ZERO_BASED: - { + case ColorBarStyle::ZERO_BASED: { if ((profile.fMin < 0.0f) && (profile.fMax > 0.0f)) { - if (fVal < 0.0f) + if (fVal < 0.0f) { return colorField1.getColorIndex(fVal); - else - return std::size_t(colorField1.getCountColors() + colorField2.getColorIndex(fVal)); + } + else { + return std::size_t(colorField1.getCountColors() + + colorField2.getColorIndex(fVal)); + } } else { return colorField1.getColorIndex(fVal); } } - default: - case ColorBarStyle::FLOW: - { + default: + case ColorBarStyle::FLOW: { return colorField1.getColorIndex(fVal); } } } -inline const ColorModel& ColorGradient::getColorModel () const +inline const ColorModel& ColorGradient::getColorModel() const { if (profile.tStyle == ColorBarStyle::ZERO_BASED) { - if (profile.fMax <= 0.0f) + if (profile.fMax <= 0.0f) { return currentModelPack.bottomModel; - else if ( profile.fMin >= 0.0f ) + } + else if (profile.fMin >= 0.0f) { return currentModelPack.topModel; - else + } + else { return currentModelPack.totalModel; + } } return currentModelPack.totalModel; } -} // namespace App +} // namespace App -#endif // APP_COLORMODEL_H +#endif // APP_COLORMODEL_H diff --git a/src/App/ComplexGeoData.cpp b/src/App/ComplexGeoData.cpp index 3e11b6f050f8..e8d50030a49d 100644 --- a/src/App/ComplexGeoData.cpp +++ b/src/App/ComplexGeoData.cpp @@ -184,20 +184,20 @@ bool ComplexGeoData::getCenterOfGravity(Base::Vector3d& unused) const return false; } -const std::string &ComplexGeoData::elementMapPrefix() { +const std::string& ComplexGeoData::elementMapPrefix() +{ static std::string prefix(ELEMENT_MAP_PREFIX); return prefix; } -std::string ComplexGeoData::getElementMapVersion() const { +std::string ComplexGeoData::getElementMapVersion() const +{ return "4"; } -bool ComplexGeoData::checkElementMapVersion(const char * ver) const +bool ComplexGeoData::checkElementMapVersion(const char* ver) const { - return !boost::equals(ver, "3") - && !boost::equals(ver, "4") - && !boost::starts_with(ver, "3."); + return !boost::equals(ver, "3") && !boost::equals(ver, "4") && !boost::starts_with(ver, "3."); } size_t ComplexGeoData::getElementMapSize(bool flush) const @@ -301,8 +301,9 @@ ElementMapPtr ComplexGeoData::resetElementMap(ElementMapPtr elementMap) _elementMap.swap(elementMap); // We expect that if the ComplexGeoData ( TopoShape ) has a hasher, then its elementMap will // have the same one. Make sure that happens. - if ( _elementMap && ! _elementMap->hasher ) + if (_elementMap && !_elementMap->hasher) { _elementMap->hasher = Hasher; + } return elementMap; } @@ -329,7 +330,6 @@ ElementMapPtr ComplexGeoData::ensureElementMap(bool flush) resetElementMap(std::make_shared()); } return elementMap(flush); - } void ComplexGeoData::flushElementMap() const @@ -656,12 +656,13 @@ unsigned int ComplexGeoData::getMemSize() const return 0; } -std::vector ComplexGeoData::getHigherElements(const char *, bool) const +std::vector ComplexGeoData::getHigherElements(const char*, bool) const { return {}; } -void ComplexGeoData::setMappedChildElements(const std::vector & children) +void ComplexGeoData::setMappedChildElements( + const std::vector& children) { // DO NOT reset element map if there is one. Because we allow mixing child // mapping and normal mapping @@ -690,8 +691,9 @@ void ComplexGeoData::beforeSave() const void ComplexGeoData::hashChildMaps() { flushElementMap(); - if (_elementMap) + if (_elementMap) { _elementMap->hashChildMaps(Tag); + } } bool ComplexGeoData::hasChildElementMap() const @@ -704,7 +706,7 @@ void ComplexGeoData::dumpElementMap(std::ostream& stream) const { auto map = getElementMap(); std::sort(map.begin(), map.end()); - for ( auto& element : map ) { + for (auto& element : map) { stream << element.index << " : " << element.name << std::endl; } } diff --git a/src/App/ComplexGeoData.h b/src/App/ComplexGeoData.h index 07d3a65587c7..995b79794464 100644 --- a/src/App/ComplexGeoData.h +++ b/src/App/ComplexGeoData.h @@ -37,7 +37,7 @@ #include "StringHasher.h" #ifdef __GNUC__ -# include +#include #endif @@ -45,16 +45,18 @@ namespace Base { class Placement; class Rotation; -template class BoundBox3;// NOLINT +template +class BoundBox3; // NOLINT using BoundBox3d = BoundBox3; -} +} // namespace Base namespace Data { -//struct MappedChildElements; +// struct MappedChildElements; /// Option for App::GeoFeature::searchElementCache() -enum class SearchOption { +enum class SearchOption +{ /// Whether to compare shape geometry CheckGeometry = 1, SingleResult = 2, @@ -67,11 +69,11 @@ typedef Base::Flags SearchOptions; */ class AppExport Segment: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT + TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT public: ~Segment() override = default; - virtual std::string getName() const=0; + virtual std::string getName() const = 0; }; enum ElementMapResetPolicy @@ -84,12 +86,22 @@ enum ElementMapResetPolicy */ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled { - TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT + TYPESYSTEM_HEADER_WITH_OVERRIDE(); // NOLINT public: - struct Line {uint32_t I1; uint32_t I2;}; - struct Facet {uint32_t I1; uint32_t I2; uint32_t I3;}; - struct Domain { + struct Line + { + uint32_t I1; + uint32_t I2; + }; + struct Facet + { + uint32_t I1; + uint32_t I2; + uint32_t I3; + }; + struct Domain + { std::vector points; std::vector facets; }; @@ -105,26 +117,24 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * List of different sub-element types * its NOT a list of the sub-elements itself */ - virtual std::vector getElementTypes() const=0; - virtual unsigned long countSubElements(const char* Type) const=0; + virtual std::vector getElementTypes() const = 0; + virtual unsigned long countSubElements(const char* Type) const = 0; /// Returns a generic element type and index. The determined element type isn't /// necessarily supported by this geometry. static std::pair getTypeAndIndex(const char* Name); /// get the sub-element by type and number - virtual Segment* getSubElement(const char* Type, unsigned long) const=0; + virtual Segment* getSubElement(const char* Type, unsigned long) const = 0; /// get sub-element by combined name virtual Segment* getSubElementByName(const char* Name) const; /** Get lines from segment */ - virtual void getLinesFromSubElement( - const Segment*, - std::vector &Points, - std::vector &lines) const; + virtual void getLinesFromSubElement(const Segment*, + std::vector& Points, + std::vector& lines) const; /** Get faces from segment */ - virtual void getFacesFromSubElement( - const Segment*, - std::vector &Points, - std::vector &PointNormals, - std::vector &faces) const; + virtual void getFacesFromSubElement(const Segment*, + std::vector& Points, + std::vector& PointNormals, + std::vector& faces) const; //@} /** @name Placement control */ @@ -147,7 +157,7 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * This method has to be handled by the child classes. * the actual placement and matrix is not part of this class. */ - virtual void setTransform(const Base::Matrix4D& rclTrf)=0; + virtual void setTransform(const Base::Matrix4D& rclTrf) = 0; /** Return the current matrix * This method has to be handled by the child classes. * the actual placement and matrix is not part of this class. @@ -158,7 +168,7 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled /** @name Modification */ //@{ /// Applies a transformation on the real geometric data type - virtual void transformGeometry(const Base::Matrix4D &rclMat) = 0; + virtual void transformGeometry(const Base::Matrix4D& rclMat) = 0; //@} /** @name Getting basic geometric entities */ @@ -166,21 +176,25 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled /// Get the standard accuracy to be used with getPoints, getLines or getFaces virtual double getAccuracy() const; /// Get the bound box - virtual Base::BoundBox3d getBoundBox() const=0; + virtual Base::BoundBox3d getBoundBox() const = 0; /** Get point from line object intersection */ - virtual Base::Vector3d getPointFromLineIntersection( - const Base::Vector3f& base, - const Base::Vector3f& dir) const; + virtual Base::Vector3d getPointFromLineIntersection(const Base::Vector3f& base, + const Base::Vector3f& dir) const; /** Get points from object with given accuracy */ - virtual void getPoints(std::vector &Points, - std::vector &Normals, - double Accuracy, uint16_t flags=0) const; + virtual void getPoints(std::vector& Points, + std::vector& Normals, + double Accuracy, + uint16_t flags = 0) const; /** Get lines from object with given accuracy */ - virtual void getLines(std::vector &Points,std::vector &lines, - double Accuracy, uint16_t flags=0) const; + virtual void getLines(std::vector& Points, + std::vector& lines, + double Accuracy, + uint16_t flags = 0) const; /** Get faces from object with given accuracy */ - virtual void getFaces(std::vector &Points,std::vector &faces, - double Accuracy, uint16_t flags=0) const; + virtual void getFaces(std::vector& Points, + std::vector& faces, + double Accuracy, + uint16_t flags = 0) const; /** Get the center of gravity * If this method is implemented then true is returned and the center of gravity. * The default implementation only returns false. @@ -188,7 +202,7 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled virtual bool getCenterOfGravity(Base::Vector3d& center) const; //@} - static const std::string &elementMapPrefix(); + static const std::string& elementMapPrefix(); /** @name Element name mapping */ //@{ @@ -200,8 +214,7 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * * @return Returns an indexed name. */ - IndexedName getIndexedName(const MappedName & name, - ElementIDRefs *sid = nullptr) const; + IndexedName getIndexedName(const MappedName& name, ElementIDRefs* sid = nullptr) const; /** Get element mapped name * @@ -212,9 +225,9 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * @param sid: optional output of and App::StringID involved forming this mapped name * @return Returns the mapped name. */ - MappedName getMappedName(const IndexedName & element, + MappedName getMappedName(const IndexedName& element, bool allowUnmapped = false, - ElementIDRefs *sid = nullptr) const; + ElementIDRefs* sid = nullptr) const; /** Return a pair of indexed name and mapped name * @@ -233,9 +246,8 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * it will be treated as indexed name. Or else, it will be treated as * mapped name. */ - MappedElement getElementName(const char * name, - ElementIDRefs *sid = nullptr, - bool copy = false) const; + MappedElement + getElementName(const char* name, ElementIDRefs* sid = nullptr, bool copy = false) const; /** Add a sub-element name mapping. * @@ -259,11 +271,13 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled const MappedName& name, long masterTag, const ElementIDRefs* sid = nullptr, - bool overwrite = false) { - return _elementMap -> setElementName(element, name, masterTag, sid, overwrite); + bool overwrite = false) + { + return _elementMap->setElementName(element, name, masterTag, sid, overwrite); } - bool hasElementMap() { + bool hasElementMap() + { return _elementMap != nullptr; } @@ -276,8 +290,8 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled * @return a list of mapped names of the give element along with their * associated string ID references */ - std::vector > - getElementMappedNames(const IndexedName & element, bool needUnmapped=false) const; + std::vector> + getElementMappedNames(const IndexedName& element, bool needUnmapped = false) const; /// Hash the child element map postfixes to shorten element name from hierarchical maps void hashChildMaps(); @@ -286,29 +300,31 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled bool hasChildElementMap() const; /// Append the Tag (if and only if it is non zero) into the element map - virtual void reTagElementMap(long tag, - App::StringHasherRef hasher, - const char *postfix=nullptr) { + virtual void + reTagElementMap(long tag, App::StringHasherRef hasher, const char* postfix = nullptr) + { (void)tag; (void)hasher; (void)postfix; } // NOTE: getElementHistory is now in ElementMap - long getElementHistory(const MappedName & name, - MappedName *original=nullptr, std::vector *history=nullptr) const { - if ( _elementMap != nullptr ) { + long getElementHistory(const MappedName& name, + MappedName* original = nullptr, + std::vector* history = nullptr) const + { + if (_elementMap != nullptr) { return _elementMap->getElementHistory(name, Tag, original, history); } return 0; }; - void setMappedChildElements(const std::vector & children); + void setMappedChildElements(const std::vector& children); std::vector getMappedChildElements() const; - char elementType(const Data::MappedName &) const; - char elementType(const Data::IndexedName &) const; - char elementType(const char *name) const; + char elementType(const Data::MappedName&) const; + char elementType(const Data::IndexedName&) const; + char elementType(const char* name) const; /** Reset/swap the element map * @@ -322,19 +338,19 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled std::vector getElementMap() const; /// Set the entire element map - void setElementMap(const std::vector &elements); + void setElementMap(const std::vector& elements); /// Get the current element map size - size_t getElementMapSize(bool flush=true) const; + size_t getElementMapSize(bool flush = true) const; /// Return the higher level element names of the given element - virtual std::vector getHigherElements(const char *name, bool silent=false) const; + virtual std::vector getHigherElements(const char* name, bool silent = false) const; /// Return the current element map version virtual std::string getElementMapVersion() const; /// Return true to signal element map version change - virtual bool checkElementMapVersion(const char * ver) const; + virtual bool checkElementMapVersion(const char* ver) const; /// Check if the given sub-name only contains an element name static bool isElementName(const char* subName) @@ -359,15 +375,21 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled /** @name Save/restore */ //@{ - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - void SaveDocFile(Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; - unsigned int getMemSize () const override; - void setPersistenceFileName(const char *name) const; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; + unsigned int getMemSize() const override; + void setPersistenceFileName(const char* name) const; virtual void beforeSave() const; - bool isRestoreFailed() const { return _restoreFailed; } - void resetRestoreFailure() const { _restoreFailed = true; } + bool isRestoreFailed() const + { + return _restoreFailed; + } + void resetRestoreFailure() const + { + _restoreFailed = true; + } //@} /** @@ -382,51 +404,60 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled const std::string dumpElementMap() const; protected: - /// from local to outside inline Base::Vector3d transformPointToOutside(const Base::Vector3f& vec) const { + // clang-format off return getTransform() * Base::Vector3d(static_cast(vec.x), static_cast(vec.y), static_cast(vec.z)); + // clang-format on } /// from local to outside template inline std::vector transformPointsToOutside(const std::vector& input) const { + // clang-format off std::vector output; output.reserve(input.size()); Base::Matrix4D mat(getTransform()); - std::transform(input.cbegin(), input.cend(), std::back_inserter(output), [&mat](const Vec& vec) { - return mat * Base::Vector3d(static_cast(vec.x), - static_cast(vec.y), - static_cast(vec.z)); - }); + std::transform(input.cbegin(), input.cend(), std::back_inserter(output), + [&mat](const Vec& vec) { + return mat * Base::Vector3d(static_cast(vec.x), + static_cast(vec.y), + static_cast(vec.z)); + }); return output; + // clang-format on } inline Base::Vector3d transformVectorToOutside(const Base::Vector3f& vec) const { + // clang-format off Base::Matrix4D mat(getTransform()); mat.setCol(3, Base::Vector3d()); return mat * Base::Vector3d(static_cast(vec.x), - static_cast(vec.y), - static_cast(vec.z)); + static_cast(vec.y), + static_cast(vec.z)); + // clang-format on } template std::vector transformVectorsToOutside(const std::vector& input) const { + // clang-format off std::vector output; output.reserve(input.size()); Base::Matrix4D mat(getTransform()); mat.setCol(3, Base::Vector3d()); - std::transform(input.cbegin(), input.cend(), std::back_inserter(output), [&mat](const Vec& vec) { - return mat * Base::Vector3d(static_cast(vec.x), - static_cast(vec.y), - static_cast(vec.z)); - }); + std::transform(input.cbegin(), input.cend(), std::back_inserter(output), + [&mat](const Vec& vec) { + return mat * Base::Vector3d(static_cast(vec.x), + static_cast(vec.y), + static_cast(vec.z)); + }); return output; + // clang-format on } /// from local to inside inline Base::Vector3f transformPointToInside(const Base::Vector3d& vec) const @@ -438,23 +469,25 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled static_cast(tmp.y), static_cast(tmp.z)); } + public: - mutable long Tag{0}; + mutable long Tag {0}; /// String hasher for element name shortening mutable App::StringHasherRef Hasher; protected: - - void restoreStream(std::istream & stream, std::size_t count); + void restoreStream(std::istream& stream, std::size_t count); void readElements(Base::XMLReader& reader, size_t count); /// from local to outside inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const { + // clang-format off return getTransform() * Base::Vector3d(static_cast(vec.x), static_cast(vec.y), static_cast(vec.z)); + // clang-format on } /// from local to inside inline Base::Vector3f transformToInside(const Base::Vector3d& vec) const @@ -468,8 +501,8 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled } protected: - ElementMapPtr elementMap(bool flush=true) const; - ElementMapPtr ensureElementMap(bool flush=true); + ElementMapPtr elementMap(bool flush = true) const; + ElementMapPtr ensureElementMap(bool flush = true); private: ElementMapPtr _elementMap; @@ -479,7 +512,7 @@ class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled mutable bool _restoreFailed = false; }; -} //namespace App +} // namespace Data ENABLE_BITMASK_OPERATORS(Data::SearchOption) #endif diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 11ee02c52277..aef283502bfb 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -58,9 +58,9 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -72,7 +72,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include #include -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG #include #include @@ -128,12 +128,13 @@ using namespace boost; using namespace zipios; #if FC_DEBUG -# define FC_LOGFEATUREUPDATE +#define FC_LOGFEATUREUPDATE #endif namespace fs = boost::filesystem; -namespace App { +namespace App +{ static bool globalIsRestoring; static bool globalIsRelabeling; @@ -163,7 +164,7 @@ DocumentP::DocumentP() UndoMaxStackSize = 20; } -} // namespace App +} // namespace App PROPERTY_SOURCE(App::Document, App::PropertyContainer) @@ -177,19 +178,19 @@ void Document::setStatus(Status pos, bool on) d->StatusBits.set((size_t)pos, on); } -//bool _has_cycle_dfs(const DependencyList & g, vertex_t u, default_color_type * color) +// bool _has_cycle_dfs(const DependencyList & g, vertex_t u, default_color_type * color) //{ -// color[u] = gray_color; -// graph_traits < DependencyList >::adjacency_iterator vi, vi_end; -// for (tie(vi, vi_end) = adjacent_vertices(u, g); vi != vi_end; ++vi) -// if (color[*vi] == white_color) -// if (has_cycle_dfs(g, *vi, color)) -// return true; // cycle detected, return immediately -// else if (color[*vi] == gray_color) // *vi is an ancestor! -// return true; -// color[u] = black_color; -// return false; -//} +// color[u] = gray_color; +// graph_traits < DependencyList >::adjacency_iterator vi, vi_end; +// for (tie(vi, vi_end) = adjacent_vertices(u, g); vi != vi_end; ++vi) +// if (color[*vi] == white_color) +// if (has_cycle_dfs(g, *vi, color)) +// return true; // cycle detected, return immediately +// else if (color[*vi] == gray_color) // *vi is an ancestor! +// return true; +// color[u] = black_color; +// return false; +// } bool Document::checkOnCycle() { @@ -207,48 +208,51 @@ bool Document::checkOnCycle() bool Document::undo(int id) { if (d->iUndoMode) { - if(id) { + if (id) { auto it = mUndoMap.find(id); - if(it == mUndoMap.end()) + if (it == mUndoMap.end()) { return false; - if(it->second != d->activeUndoTransaction) { - while(!mUndoTransactions.empty() && mUndoTransactions.back()!=it->second) + } + if (it->second != d->activeUndoTransaction) { + while (!mUndoTransactions.empty() && mUndoTransactions.back() != it->second) { undo(0); + } } } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); - if (mUndoTransactions.empty()) + } + if (mUndoTransactions.empty()) { return false; + } // redo d->activeUndoTransaction = new Transaction(mUndoTransactions.back()->getID()); d->activeUndoTransaction->Name = mUndoTransactions.back()->Name; { - Base::FlagToggler flag(d->undoing); - // applying the undo - mUndoTransactions.back()->apply(*this,false); - - // save the redo - mRedoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; - mRedoTransactions.push_back(d->activeUndoTransaction); - d->activeUndoTransaction = nullptr; - - mUndoMap.erase(mUndoTransactions.back()->getID()); - delete mUndoTransactions.back(); - mUndoTransactions.pop_back(); - + Base::FlagToggler flag(d->undoing); + // applying the undo + mUndoTransactions.back()->apply(*this, false); + + // save the redo + mRedoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; + mRedoTransactions.push_back(d->activeUndoTransaction); + d->activeUndoTransaction = nullptr; + + mUndoMap.erase(mUndoTransactions.back()->getID()); + delete mUndoTransactions.back(); + mUndoTransactions.pop_back(); } - for(auto & obj : d->objectArray) { - if(obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { + for (auto& obj : d->objectArray) { + if (obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { obj->onUndoRedoFinished(); - obj->setStatus(ObjectStatus::PendingTransactionUpdate,false); + obj->setStatus(ObjectStatus::PendingTransactionUpdate, false); } } - signalUndo(*this); // now signal the undo + signalUndo(*this); // now signal the undo return true; } @@ -259,18 +263,21 @@ bool Document::undo(int id) bool Document::redo(int id) { if (d->iUndoMode) { - if(id) { + if (id) { auto it = mRedoMap.find(id); - if(it == mRedoMap.end()) + if (it == mRedoMap.end()) { return false; - while(!mRedoTransactions.empty() && mRedoTransactions.back()!=it->second) + } + while (!mRedoTransactions.empty() && mRedoTransactions.back() != it->second) { redo(0); + } } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); + } - assert(mRedoTransactions.size()!=0); + assert(mRedoTransactions.size() != 0); // undo d->activeUndoTransaction = new Transaction(mRedoTransactions.back()->getID()); @@ -278,22 +285,22 @@ bool Document::redo(int id) // do the redo { - Base::FlagToggler flag(d->undoing); - mRedoTransactions.back()->apply(*this,true); + Base::FlagToggler flag(d->undoing); + mRedoTransactions.back()->apply(*this, true); - mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; - mUndoTransactions.push_back(d->activeUndoTransaction); - d->activeUndoTransaction = nullptr; + mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; + mUndoTransactions.push_back(d->activeUndoTransaction); + d->activeUndoTransaction = nullptr; - mRedoMap.erase(mRedoTransactions.back()->getID()); - delete mRedoTransactions.back(); - mRedoTransactions.pop_back(); + mRedoMap.erase(mRedoTransactions.back()->getID()); + delete mRedoTransactions.back(); + mRedoTransactions.pop_back(); } - for(auto & obj : d->objectArray) { - if(obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { + for (auto& obj : d->objectArray) { + if (obj->testStatus(ObjectStatus::PendingTransactionUpdate)) { obj->onUndoRedoFinished(); - obj->setStatus(ObjectStatus::PendingTransactionUpdate,false); + obj->setStatus(ObjectStatus::PendingTransactionUpdate, false); } } @@ -304,20 +311,23 @@ bool Document::redo(int id) return false; } -void Document::addOrRemovePropertyOfObject(TransactionalObject* obj, Property *prop, bool add) +void Document::addOrRemovePropertyOfObject(TransactionalObject* obj, Property* prop, bool add) { - if (!prop || !obj || !obj->isAttachedToDocument()) + if (!prop || !obj || !obj->isAttachedToDocument()) { return; - if(d->iUndoMode && !isPerformingTransaction() && !d->activeUndoTransaction) { - if(!testStatus(Restoring) || testStatus(Importing)) { - int tid=0; - const char *name = GetApplication().getActiveTransaction(&tid); - if(name && tid>0) - _openTransaction(name,tid); + } + if (d->iUndoMode && !isPerformingTransaction() && !d->activeUndoTransaction) { + if (!testStatus(Restoring) || testStatus(Importing)) { + int tid = 0; + const char* name = GetApplication().getActiveTransaction(&tid); + if (name && tid > 0) { + _openTransaction(name, tid); + } } } - if (d->activeUndoTransaction && !d->rollback) + if (d->activeUndoTransaction && !d->rollback) { d->activeUndoTransaction->addOrRemoveProperty(obj, prop, add); + } } bool Document::isPerformingTransaction() const @@ -328,36 +338,46 @@ bool Document::isPerformingTransaction() const std::vector Document::getAvailableUndoNames() const { std::vector vList; - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { vList.push_back(d->activeUndoTransaction->Name); - for (std::list::const_reverse_iterator It=mUndoTransactions.rbegin();It!=mUndoTransactions.rend();++It) + } + for (std::list::const_reverse_iterator It = mUndoTransactions.rbegin(); + It != mUndoTransactions.rend(); + ++It) { vList.push_back((**It).Name); + } return vList; } std::vector Document::getAvailableRedoNames() const { std::vector vList; - for (std::list::const_reverse_iterator It=mRedoTransactions.rbegin();It!=mRedoTransactions.rend();++It) + for (std::list::const_reverse_iterator It = mRedoTransactions.rbegin(); + It != mRedoTransactions.rend(); + ++It) { vList.push_back((**It).Name); + } return vList; } -void Document::openTransaction(const char* name) { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::openTransaction(const char* name) +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot open transaction while transacting"); + } return; } - GetApplication().setActiveTransaction(name?name:""); + GetApplication().setActiveTransaction(name ? name : ""); } int Document::_openTransaction(const char* name, int id) { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot open transaction while transacting"); + } return 0; } @@ -366,80 +386,89 @@ int Document::_openTransaction(const char* name, int id) // clearing the redo transactions and will cause // a double deletion of some transaction and thus // a segmentation fault - if (d->opentransaction) + if (d->opentransaction) { return 0; + } Base::FlagToggler<> flag(d->opentransaction); - if(id && mUndoMap.find(id)!=mUndoMap.end()) + if (id && mUndoMap.find(id) != mUndoMap.end()) { throw Base::RuntimeError("invalid transaction id"); - if (d->activeUndoTransaction) + } + if (d->activeUndoTransaction) { _commitTransaction(true); + } _clearRedos(); d->activeUndoTransaction = new Transaction(id); - if (!name) + if (!name) { name = ""; + } d->activeUndoTransaction->Name = name; mUndoMap[d->activeUndoTransaction->getID()] = d->activeUndoTransaction; id = d->activeUndoTransaction->getID(); signalOpenTransaction(*this, name); - auto &app = GetApplication(); + auto& app = GetApplication(); auto activeDoc = app.getActiveDocument(); - if(activeDoc && - activeDoc!=this && - !activeDoc->hasPendingTransaction()) - { + if (activeDoc && activeDoc != this && !activeDoc->hasPendingTransaction()) { std::string aname("-> "); aname += d->activeUndoTransaction->Name; FC_LOG("auto transaction " << getName() << " -> " << activeDoc->getName()); - activeDoc->_openTransaction(aname.c_str(),id); + activeDoc->_openTransaction(aname.c_str(), id); } return id; } return 0; } -void Document::renameTransaction(const char *name, int id) { - if(name && d->activeUndoTransaction && d->activeUndoTransaction->getID()==id) { - if(boost::starts_with(d->activeUndoTransaction->Name, "-> ")) +void Document::renameTransaction(const char* name, int id) +{ + if (name && d->activeUndoTransaction && d->activeUndoTransaction->getID() == id) { + if (boost::starts_with(d->activeUndoTransaction->Name, "-> ")) { d->activeUndoTransaction->Name.resize(3); - else + } + else { d->activeUndoTransaction->Name.clear(); + } d->activeUndoTransaction->Name += name; } } -void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What, int line) +void Document::_checkTransaction(DocumentObject* pcDelObj, const Property* What, int line) { // if the undo is active but no transaction open, open one! if (d->iUndoMode && !isPerformingTransaction()) { if (!d->activeUndoTransaction) { - if(!testStatus(Restoring) || testStatus(Importing)) { - int tid=0; - const char *name = GetApplication().getActiveTransaction(&tid); - if(name && tid>0) { + if (!testStatus(Restoring) || testStatus(Importing)) { + int tid = 0; + const char* name = GetApplication().getActiveTransaction(&tid); + if (name && tid > 0) { bool ignore = false; - if(What && What->testStatus(Property::NoModify)) + if (What && What->testStatus(Property::NoModify)) { ignore = true; - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - if(What) - FC_LOG((ignore?"ignore":"auto") << " transaction (" - << line << ") '" << What->getFullName()); - else - FC_LOG((ignore?"ignore":"auto") <<" transaction (" - << line << ") '" << name << "' in " << getName()); } - if(!ignore) - _openTransaction(name,tid); + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + if (What) { + FC_LOG((ignore ? "ignore" : "auto") + << " transaction (" << line << ") '" << What->getFullName()); + } + else { + FC_LOG((ignore ? "ignore" : "auto") << " transaction (" << line << ") '" + << name << "' in " << getName()); + } + } + if (!ignore) { + _openTransaction(name, tid); + } return; } } - if(!pcDelObj) + if (!pcDelObj) { return; - // When the object is going to be deleted we have to check if it has already been added to - // the undo transactions + } + // When the object is going to be deleted we have to check if it has already been added + // to the undo transactions std::list::iterator it; for (it = mUndoTransactions.begin(); it != mUndoTransactions.end(); ++it) { if ((*it)->hasObject(pcDelObj)) { @@ -453,7 +482,7 @@ void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What, void Document::_clearRedos() { - if(isPerformingTransaction() || d->committing) { + if (isPerformingTransaction() || d->committing) { FC_ERR("Cannot clear redo while transacting"); return; } @@ -465,22 +494,26 @@ void Document::_clearRedos() } } -void Document::commitTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::commitTransaction() +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot commit transaction while transacting"); + } return; } - if (d->activeUndoTransaction) - GetApplication().closeActiveTransaction(false,d->activeUndoTransaction->getID()); + if (d->activeUndoTransaction) { + GetApplication().closeActiveTransaction(false, d->activeUndoTransaction->getID()); + } } void Document::_commitTransaction(bool notify) { if (isPerformingTransaction()) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot commit transaction while transacting"); + } return; } else if (d->committing) { @@ -490,12 +523,12 @@ void Document::_commitTransaction(bool notify) if (d->activeUndoTransaction) { Base::FlagToggler<> flag(d->committing); - Application::TransactionSignaller signaller(false,true); + Application::TransactionSignaller signaller(false, true); int id = d->activeUndoTransaction->getID(); mUndoTransactions.push_back(d->activeUndoTransaction); d->activeUndoTransaction = nullptr; // check the stack for the limits - if(mUndoTransactions.size() > d->UndoMaxStackSize){ + if (mUndoTransactions.size() > d->UndoMaxStackSize) { mUndoMap.erase(mUndoTransactions.front()->getID()); delete mUndoTransactions.front(); mUndoTransactions.pop_front(); @@ -503,34 +536,39 @@ void Document::_commitTransaction(bool notify) signalCommitTransaction(*this); // closeActiveTransaction() may call again _commitTransaction() - if (notify) - GetApplication().closeActiveTransaction(false,id); + if (notify) { + GetApplication().closeActiveTransaction(false, id); + } } } -void Document::abortTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) +void Document::abortTransaction() +{ + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot abort transaction while transacting"); + } return; } - if (d->activeUndoTransaction) - GetApplication().closeActiveTransaction(true,d->activeUndoTransaction->getID()); + if (d->activeUndoTransaction) { + GetApplication().closeActiveTransaction(true, d->activeUndoTransaction->getID()); + } } void Document::_abortTransaction() { - if(isPerformingTransaction() || d->committing) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (isPerformingTransaction() || d->committing) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Cannot abort transaction while transacting"); + } } if (d->activeUndoTransaction) { Base::FlagToggler flag(d->rollback); - Application::TransactionSignaller signaller(true,true); + Application::TransactionSignaller signaller(true, true); // applying the so far made changes - d->activeUndoTransaction->apply(*this,false); + d->activeUndoTransaction->apply(*this, false); // destroy the undo mUndoMap.erase(d->activeUndoTransaction->getID()); @@ -542,30 +580,37 @@ void Document::_abortTransaction() bool Document::hasPendingTransaction() const { - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { return true; - else + } + else { return false; + } } -int Document::getTransactionID(bool undo, unsigned pos) const { - if(undo) { - if(d->activeUndoTransaction) { - if(pos == 0) +int Document::getTransactionID(bool undo, unsigned pos) const +{ + if (undo) { + if (d->activeUndoTransaction) { + if (pos == 0) { return d->activeUndoTransaction->getID(); + } --pos; } - if(pos>=mUndoTransactions.size()) + if (pos >= mUndoTransactions.size()) { return 0; + } auto rit = mUndoTransactions.rbegin(); - for(;pos;++rit,--pos) + for (; pos; ++rit, --pos) { continue; + } return (*rit)->getID(); } - if(pos>=mRedoTransactions.size()) + if (pos >= mRedoTransactions.size()) { return 0; + } auto rit = mRedoTransactions.rbegin(); - for(;pos;++rit,--pos){} + for (; pos; ++rit, --pos) {} return (*rit)->getID(); } @@ -592,12 +637,12 @@ void Document::clearDocument() if (!d->objectArray.empty()) { GetApplication().signalDeleteDocument(*this); d->clearDocument(); - GetApplication().signalNewDocument(*this,false); + GetApplication().signalNewDocument(*this, false); } Base::FlagToggler<> flag(globalIsRestoring, false); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); d->clearRecomputeLog(); d->objectArray.clear(); @@ -609,13 +654,14 @@ void Document::clearDocument() void Document::clearUndos() { - if(isPerformingTransaction() || d->committing) { + if (isPerformingTransaction() || d->committing) { FC_ERR("Cannot clear undos while transacting"); return; } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { _commitTransaction(true); + } mUndoMap.clear(); @@ -629,57 +675,65 @@ void Document::clearUndos() delete mUndoTransactions.front(); mUndoTransactions.pop_front(); } - //while (!mUndoTransactions.empty()) { - // delete mUndoTransactions.back(); - // mUndoTransactions.pop_back(); - //} + // while (!mUndoTransactions.empty()) { + // delete mUndoTransactions.back(); + // mUndoTransactions.pop_back(); + // } _clearRedos(); } int Document::getAvailableUndos(int id) const { - if(id) { + if (id) { auto it = mUndoMap.find(id); - if(it == mUndoMap.end()) + if (it == mUndoMap.end()) { return 0; + } int i = 0; - if(d->activeUndoTransaction) { + if (d->activeUndoTransaction) { ++i; - if(d->activeUndoTransaction->getID()==id) + if (d->activeUndoTransaction->getID() == id) { return i; + } } auto rit = mUndoTransactions.rbegin(); - for(;rit!=mUndoTransactions.rend()&&*rit!=it->second;++rit) + for (; rit != mUndoTransactions.rend() && *rit != it->second; ++rit) { ++i; - assert(rit!=mUndoTransactions.rend()); - return i+1; + } + assert(rit != mUndoTransactions.rend()); + return i + 1; } - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { return static_cast(mUndoTransactions.size() + 1); - else + } + else { return static_cast(mUndoTransactions.size()); + } } int Document::getAvailableRedos(int id) const { - if(id) { + if (id) { auto it = mRedoMap.find(id); - if(it == mRedoMap.end()) + if (it == mRedoMap.end()) { return 0; + } int i = 0; - for(auto rit=mRedoTransactions.rbegin();*rit!=it->second;++rit) + for (auto rit = mRedoTransactions.rbegin(); *rit != it->second; ++rit) { ++i; - assert(i<(int)mRedoTransactions.size()); - return i+1; + } + assert(i < (int)mRedoTransactions.size()); + return i + 1; } return static_cast(mRedoTransactions.size()); } void Document::setUndoMode(int iMode) { - if (d->iUndoMode && !iMode) + if (d->iUndoMode && !iMode) { clearUndos(); + } d->iUndoMode = iMode; } @@ -689,7 +743,7 @@ int Document::getUndoMode() const return d->iUndoMode; } -unsigned int Document::getUndoMemSize () const +unsigned int Document::getUndoMemSize() const { return d->UndoMemSize; } @@ -701,18 +755,19 @@ void Document::setUndoLimit(unsigned int UndoMemSize) void Document::setMaxUndoStackSize(unsigned int UndoMaxStackSize) { - d->UndoMaxStackSize = UndoMaxStackSize; + d->UndoMaxStackSize = UndoMaxStackSize; } -unsigned int Document::getMaxUndoStackSize()const +unsigned int Document::getMaxUndoStackSize() const { return d->UndoMaxStackSize; } void Document::onBeforeChange(const Property* prop) { - if(prop == &Label) + if (prop == &Label) { oldLabel = Label.getValue(); + } signalBeforeChange(*this, *prop); } @@ -724,26 +779,35 @@ void Document::onChanged(const Property* prop) if (prop == &Label) { Base::FlagToggler<> flag(globalIsRelabeling); App::GetApplication().signalRelabelDocument(*this); - } else if(prop == &ShowHidden) { + } + else if (prop == &ShowHidden) { App::GetApplication().signalShowHidden(*this); - } else if (prop == &Uid) { - std::string new_dir = getTransientDirectoryName(this->Uid.getValueStr(),this->FileName.getStrValue()); + } + else if (prop == &Uid) { + std::string new_dir = + getTransientDirectoryName(this->Uid.getValueStr(), this->FileName.getStrValue()); std::string old_dir = this->TransientDir.getStrValue(); Base::FileInfo TransDirNew(new_dir); Base::FileInfo TransDirOld(old_dir); // this directory should not exist if (!TransDirNew.exists()) { if (TransDirOld.exists()) { - if (!TransDirOld.renameFile(new_dir.c_str())) - Base::Console().Warning("Failed to rename '%s' to '%s'\n", old_dir.c_str(), new_dir.c_str()); - else + if (!TransDirOld.renameFile(new_dir.c_str())) { + Base::Console().Warning("Failed to rename '%s' to '%s'\n", + old_dir.c_str(), + new_dir.c_str()); + } + else { this->TransientDir.setValue(new_dir); + } } else { - if (!TransDirNew.createDirectories()) + if (!TransDirNew.createDirectories()) { Base::Console().Warning("Failed to create '%s'\n", new_dir.c_str()); - else + } + else { this->TransientDir.setValue(new_dir); + } } } // when reloading an existing document the transient directory doesn't change @@ -753,31 +817,36 @@ void Document::onChanged(const Property* prop) std::string uuid = this->Uid.getValueStr(); Base::Uuid id; Base::Console().Warning("Document with the UUID '%s' already exists, change to '%s'\n", - uuid.c_str(), id.getValue().c_str()); + uuid.c_str(), + id.getValue().c_str()); // recursive call of onChanged() this->Uid.setValue(id); } - } else if(prop == &UseHasher) { - for(auto obj : d->objectArray) { + } + else if (prop == &UseHasher) { + for (auto obj : d->objectArray) { auto geofeature = dynamic_cast(obj); - if(geofeature && geofeature->getPropertyOfGeometry()) + if (geofeature && geofeature->getPropertyOfGeometry()) { geofeature->enforceRecompute(); + } } } } -void Document::onBeforeChangeProperty(const TransactionalObject *Who, const Property *What) +void Document::onBeforeChangeProperty(const TransactionalObject* Who, const Property* What) { - if(Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) + if (Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) { signalBeforeChangeObject(*static_cast(Who), *What); - if(!d->rollback && !globalIsRelabeling) { + } + if (!d->rollback && !globalIsRelabeling) { _checkTransaction(nullptr, What, __LINE__); - if (d->activeUndoTransaction) + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectChange(Who, What); + } } } -void Document::onChangedProperty(const DocumentObject *Who, const Property *What) +void Document::onChangedProperty(const DocumentObject* Who, const Property* What) { signalChangedObject(*Who, *What); } @@ -821,8 +890,11 @@ Document::Document(const char* documentName) PropertyType(Prop_Transient | Prop_ReadOnly), "The path to the file where the document is saved to"); ADD_PROPERTY_TYPE(CreatedBy, (Author.c_str()), 0, Prop_None, "The creator of the document"); - ADD_PROPERTY_TYPE( - CreationDate, (CreationDateString.c_str()), 0, Prop_ReadOnly, "Date of creation"); + ADD_PROPERTY_TYPE(CreationDate, + (CreationDateString.c_str()), + 0, + Prop_ReadOnly, + "Date of creation"); ADD_PROPERTY_TYPE(LastModifiedBy, (""), 0, Prop_None, 0); ADD_PROPERTY_TYPE(LastModifiedDate, ("Unknown"), 0, Prop_ReadOnly, "Date of last modification"); ADD_PROPERTY_TYPE(Company, @@ -840,7 +912,8 @@ Document::Document(const char* documentName) } UnitSystem.setEnums(enumValsAsVector); // Get the preferences/General unit system as the default for a new document - ParameterGrp::handle hGrpu = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); + ParameterGrp::handle hGrpu = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); UnitSystem.setValue(hGrpu->GetInt("UserSchema", 0)); ADD_PROPERTY_TYPE(Comment, (""), 0, Prop_None, "Additional tag to save a comment"); ADD_PROPERTY_TYPE(Meta, (), 0, Prop_None, "Map with additional meta information"); @@ -863,15 +936,21 @@ Document::Document(const char* documentName) licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); } ADD_PROPERTY_TYPE(License, (name), 0, Prop_None, "License string of the Item"); - ADD_PROPERTY_TYPE( - LicenseURL, (licenseUrl.c_str()), 0, Prop_None, "URL to the license text/contract"); + ADD_PROPERTY_TYPE(LicenseURL, + (licenseUrl.c_str()), + 0, + Prop_None, + "URL to the license text/contract"); ADD_PROPERTY_TYPE(ShowHidden, (false), 0, PropertyType(Prop_None), "Whether to show hidden object items in the tree view"); - ADD_PROPERTY_TYPE(UseHasher,(true), 0,PropertyType(Prop_Hidden), - "Whether to use hasher on topological naming"); + ADD_PROPERTY_TYPE(UseHasher, + (true), + 0, + PropertyType(Prop_Hidden), + "Whether to use hasher on topological naming"); // this creates and sets 'TransientDir' in onChanged() ADD_PROPERTY_TYPE(TransientDir, @@ -879,8 +958,11 @@ Document::Document(const char* documentName) 0, PropertyType(Prop_Transient | Prop_ReadOnly), "Transient directory, where the files live while the document is open"); - ADD_PROPERTY_TYPE( - Tip, (nullptr), 0, PropertyType(Prop_Transient), "Link of the tip object of the document"); + ADD_PROPERTY_TYPE(Tip, + (nullptr), + 0, + PropertyType(Prop_Transient), + "Link of the tip object of the document"); ADD_PROPERTY_TYPE(TipName, (""), 0, @@ -892,7 +974,7 @@ Document::Document(const char* documentName) Document::~Document() { #ifdef FC_LOGUPDATECHAIN - Console().Log("-App::Document: %s %p\n",getName(), this); + Console().Log("-App::Document: %s %p\n", getName(), this); #endif try { @@ -902,7 +984,7 @@ Document::~Document() } #ifdef FC_LOGUPDATECHAIN - Console().Log("-Delete Features of %s \n",getName()); + Console().Log("-Delete Features of %s \n", getName()); #endif d->clearDocument(); @@ -928,22 +1010,19 @@ Document::~Document() delete d; } -std::string Document::getTransientDirectoryName(const std::string& uuid, const std::string& filename) const +std::string Document::getTransientDirectoryName(const std::string& uuid, + const std::string& filename) const { // Create a directory name of the form: {ExeName}_Doc_{UUID}_{HASH}_{PID} std::stringstream out; QCryptographicHash hash(QCryptographicHash::Sha1); -#if QT_VERSION < QT_VERSION_CHECK(6,3,0) +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) hash.addData(filename.c_str(), filename.size()); #else hash.addData(QByteArrayView(filename.c_str(), filename.size())); #endif - out << App::Application::getUserCachePath() << App::Application::getExecutableName() - << "_Doc_" - << uuid - << "_" - << hash.result().toHex().left(6).constData() - << "_" + out << App::Application::getUserCachePath() << App::Application::getExecutableName() << "_Doc_" + << uuid << "_" << hash.result().toHex().left(6).constData() << "_" << App::Application::applicationPid(); return out.str(); } @@ -952,7 +1031,7 @@ std::string Document::getTransientDirectoryName(const std::string& uuid, const s // Exported functions //-------------------------------------------------------------------------- -void Document::Save (Base::Writer &writer) const +void Document::Save(Base::Writer& writer) const { d->hashers.clear(); addStringHasher(d->Hasher); @@ -960,9 +1039,8 @@ void Document::Save (Base::Writer &writer) const writer.Stream() << R"(\n"; + << App::Application::Config()["BuildRevision"] << "\" FileVersion=\"" + << writer.getFileVersion() << "\" StringHasher=\"1\">\n"; writer.incInd(); @@ -983,25 +1061,27 @@ void Document::Save (Base::Writer &writer) const writer.Stream() << "" << endl; } -void Document::Restore(Base::XMLReader &reader) +void Document::Restore(Base::XMLReader& reader) { - int i,Cnt; + int i, Cnt; d->hashers.clear(); d->touchedObjs.clear(); addStringHasher(d->Hasher); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); reader.readElement("Document"); long scheme = reader.getAttributeAsInteger("SchemaVersion"); reader.DocumentSchema = scheme; if (reader.hasAttribute("ProgramVersion")) { reader.ProgramVersion = reader.getAttribute("ProgramVersion"); - } else { + } + else { reader.ProgramVersion = "pre-0.14"; } if (reader.hasAttribute("FileVersion")) { reader.FileVersion = reader.getAttributeAsUnsigned("FileVersion"); - } else { + } + else { reader.FileVersion = 0; } @@ -1022,7 +1102,8 @@ void Document::Restore(Base::XMLReader &reader) std::string FilePath = FileName.getValue(); std::string DocLabel = Label.getValue(); - // read the Document Properties, when reading in Uid the transient directory gets renamed automatically + // read the Document Properties, when reading in Uid the transient directory gets renamed + // automatically PropertyContainer::Restore(reader); // We must restore the correct 'FileName' property again because the stored @@ -1031,18 +1112,18 @@ void Document::Restore(Base::XMLReader &reader) Label.setValue(DocLabel.c_str()); // SchemeVersion "2" - if ( scheme == 2 ) { + if (scheme == 2) { // read the feature types reader.readElement("Features"); Cnt = reader.getAttributeAsInteger("Count"); - for (i=0 ;isetStatus(ObjectStatus::Restore, true); pObj->Restore(reader); pObj->setStatus(ObjectStatus::Restore, false); @@ -1063,8 +1144,8 @@ void Document::Restore(Base::XMLReader &reader) reader.readEndElement("Feature"); } reader.readEndElement("FeatureData"); - } // SchemeVersion "3" or higher - else if ( scheme >= 3 ) { + } // SchemeVersion "3" or higher + else if (scheme >= 3) { // read the feature types readObjects(reader); @@ -1087,33 +1168,41 @@ void DocumentP::checkStringHasher(const Base::XMLReader& reader) } } -std::pair Document::addStringHasher(const StringHasherRef & hasher) const { - if (!hasher) +std::pair Document::addStringHasher(const StringHasherRef& hasher) const +{ + if (!hasher) { return std::make_pair(false, 0); - auto ret = d->hashers.left.insert(HasherMap::left_map::value_type(hasher,(int)d->hashers.size())); - if (ret.second) + } + auto ret = + d->hashers.left.insert(HasherMap::left_map::value_type(hasher, (int)d->hashers.size())); + if (ret.second) { hasher->clearMarks(); - return std::make_pair(ret.second,ret.first->second); + } + return std::make_pair(ret.second, ret.first->second); } -StringHasherRef Document::getStringHasher(int idx) const { +StringHasherRef Document::getStringHasher(int idx) const +{ StringHasherRef hasher; - if(idx<0) { - if(UseHasher.getValue()) { + if (idx < 0) { + if (UseHasher.getValue()) { return d->Hasher; } return hasher; } auto it = d->hashers.right.find(idx); - if(it == d->hashers.right.end()) { + if (it == d->hashers.right.end()) { hasher = new StringHasher; - d->hashers.right.insert(HasherMap::right_map::value_type(idx,hasher)); - }else + d->hashers.right.insert(HasherMap::right_map::value_type(idx, hasher)); + } + else { hasher = it->second; + } return hasher; } -struct DocExportStatus { +struct DocExportStatus +{ Document::ExportStatus status; std::set objs; }; @@ -1121,14 +1210,17 @@ struct DocExportStatus { static DocExportStatus _ExportStatus; // Exception-safe exporting status setter -class DocumentExporting { +class DocumentExporting +{ public: - explicit DocumentExporting(const std::vector &objs) { + explicit DocumentExporting(const std::vector& objs) + { _ExportStatus.status = Document::Exporting; - _ExportStatus.objs.insert(objs.begin(),objs.end()); + _ExportStatus.objs.insert(objs.begin(), objs.end()); } - ~DocumentExporting() { + ~DocumentExporting() + { _ExportStatus.status = Document::NotExporting; _ExportStatus.objs.clear(); } @@ -1139,26 +1231,32 @@ class DocumentExporting { // at the same time. I see no benefits in distinguish which documents are // exporting, so just use a static variable for global status. But the // implementation can easily be changed here if necessary. -Document::ExportStatus Document::isExporting(const App::DocumentObject *obj) const { - if(_ExportStatus.status!=Document::NotExporting && - (!obj || _ExportStatus.objs.find(obj)!=_ExportStatus.objs.end())) +Document::ExportStatus Document::isExporting(const App::DocumentObject* obj) const +{ + if (_ExportStatus.status != Document::NotExporting + && (!obj || _ExportStatus.objs.find(obj) != _ExportStatus.objs.end())) { return _ExportStatus.status; + } return Document::NotExporting; } -void Document::exportObjects(const std::vector& obj, std::ostream& out) { +void Document::exportObjects(const std::vector& obj, std::ostream& out) +{ DocumentExporting exporting(obj); d->hashers.clear(); - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - for(auto o : obj) { - if(o && o->isAttachedToDocument()) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + for (auto o : obj) { + if (o && o->isAttachedToDocument()) { FC_LOG("exporting " << o->getFullName()); if (!o->getPropertyByName("_ObjectUUID")) { - auto prop = static_cast(o->addDynamicProperty( - "App::PropertyUUID", "_ObjectUUID", nullptr, nullptr, - Prop_Output | Prop_Hidden)); + auto prop = static_cast( + o->addDynamicProperty("App::PropertyUUID", + "_ObjectUUID", + nullptr, + nullptr, + Prop_Output | Prop_Hidden)); prop->setValue(Base::Uuid::createUuid()); } } @@ -1171,8 +1269,8 @@ void Document::exportObjects(const std::vector& obj, std:: writer.Stream() << R"()" << endl; + << App::Application::Config()["BuildRevision"] << R"(" FileVersion="1">)" + << endl; // Add this block to have the same layout as for normal documents writer.Stream() << "" << endl; writer.Stream() << "" << endl; @@ -1197,37 +1295,41 @@ void Document::exportObjects(const std::vector& obj, std:: #define FC_ELEMENT_OBJECT_DEP "Dep" void Document::writeObjects(const std::vector& obj, - Base::Writer &writer) const + Base::Writer& writer) const { // writing the features types - writer.incInd(); // indentation for 'Objects count' + writer.incInd(); // indentation for 'Objects count' writer.Stream() << writer.ind() << "" << endl; - writer.incInd(); // indentation for 'Object type' + writer.incInd(); // indentation for 'Object type' - if(!isExporting(nullptr)) { - for(auto o : obj) { - const auto &outList = o->getOutList(DocumentObject::OutListNoHidden - | DocumentObject::OutListNoXLinked); + if (!isExporting(nullptr)) { + for (auto o : obj) { + const auto& outList = + o->getOutList(DocumentObject::OutListNoHidden | DocumentObject::OutListNoXLinked); writer.Stream() << writer.ind() - << "<" FC_ELEMENT_OBJECT_DEPS " " FC_ATTR_DEP_OBJ_NAME "=\"" - << o->getNameInDocument() << "\" " FC_ATTR_DEP_COUNT "=\"" << outList.size(); - if(outList.empty()) { + << "<" FC_ELEMENT_OBJECT_DEPS " " FC_ATTR_DEP_OBJ_NAME "=\"" + << o->getNameInDocument() << "\" " FC_ATTR_DEP_COUNT "=\"" + << outList.size(); + if (outList.empty()) { writer.Stream() << "\"/>" << endl; continue; } int partial = o->canLoadPartial(); - if(partial>0) + if (partial > 0) { writer.Stream() << "\" " FC_ATTR_DEP_ALLOW_PARTIAL << "=\"" << partial; + } writer.Stream() << "\">" << endl; writer.incInd(); - for(auto dep : outList) { - auto name = dep?dep->getNameInDocument():""; - writer.Stream() << writer.ind() << "<" FC_ELEMENT_OBJECT_DEP " " - FC_ATTR_DEP_OBJ_NAME "=\"" << (name?name:"") << "\"/>" << endl; + for (auto dep : outList) { + auto name = dep ? dep->getNameInDocument() : ""; + writer.Stream() << writer.ind() + << "<" FC_ELEMENT_OBJECT_DEP " " FC_ATTR_DEP_OBJ_NAME "=\"" + << (name ? name : "") << "\"/>" << endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; @@ -1237,23 +1339,26 @@ void Document::writeObjects(const std::vector& obj, std::vector::const_iterator it; for (it = obj.begin(); it != obj.end(); ++it) { writer.Stream() << writer.ind() << "getTypeId().getName() << "\" " - << "name=\"" << (*it)->getExportName() << "\" " - << "id=\"" << (*it)->getID() << "\" "; + << "type=\"" << (*it)->getTypeId().getName() << "\" " + << "name=\"" << (*it)->getExportName() << "\" " + << "id=\"" << (*it)->getID() << "\" "; // Only write out custom view provider types std::string viewType = (*it)->getViewProviderNameStored(); - if (viewType != (*it)->getViewProviderName()) + if (viewType != (*it)->getViewProviderName()) { writer.Stream() << "ViewType=\"" << viewType << "\" "; + } // See DocumentObjectPy::getState - if ((*it)->testStatus(ObjectStatus::Touch)) + if ((*it)->testStatus(ObjectStatus::Touch)) { writer.Stream() << "Touched=\"1\" "; + } if ((*it)->testStatus(ObjectStatus::Error)) { writer.Stream() << "Invalid=\"1\" "; auto desc = getErrorDescription(*it); - if(desc) + if (desc) { writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" "; + } } writer.Stream() << "/>" << endl; } @@ -1262,62 +1367,67 @@ void Document::writeObjects(const std::vector& obj, writer.Stream() << writer.ind() << "" << endl; // writing the features itself - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; - writer.incInd(); // indentation for 'Object name' + writer.incInd(); // indentation for 'Object name' for (it = obj.begin(); it != obj.end(); ++it) { writer.Stream() << writer.ind() << "getExportName() << "\""; - if((*it)->hasExtensions()) + if ((*it)->hasExtensions()) { writer.Stream() << " Extensions=\"True\""; + } writer.Stream() << ">" << endl; (*it)->Save(writer); writer.Stream() << writer.ind() << "" << endl; } - writer.decInd(); // indentation for 'Object name' + writer.decInd(); // indentation for 'Object name' writer.Stream() << writer.ind() << "" << endl; writer.decInd(); // indentation for 'Objects count' } -struct DepInfo { +struct DepInfo +{ std::unordered_set deps; int canLoadPartial = 0; }; -static void _loadDeps(const std::string &name, - std::unordered_map &objs, - const std::unordered_map &deps) +static void _loadDeps(const std::string& name, + std::unordered_map& objs, + const std::unordered_map& deps) { auto it = deps.find(name); - if(it == deps.end()) { - objs.emplace(name,true); + if (it == deps.end()) { + objs.emplace(name, true); return; } - if(it->second.canLoadPartial) { - if(it->second.canLoadPartial == 1) { + if (it->second.canLoadPartial) { + if (it->second.canLoadPartial == 1) { // canLoadPartial==1 means all its children will be created but not // restored, i.e. exists as if newly created object, and therefore no // need to load dependency of the children - for(auto &dep : it->second.deps) - objs.emplace(dep,false); - objs.emplace(name,true); - }else - objs.emplace(name,false); + for (auto& dep : it->second.deps) { + objs.emplace(dep, false); + } + objs.emplace(name, true); + } + else { + objs.emplace(name, false); + } return; } objs[name] = true; // If cannot load partial, then recurse to load all children dependency - for(auto &dep : it->second.deps) { + for (auto& dep : it->second.deps) { auto it = objs.find(dep); - if(it!=objs.end() && it->second) + if (it != objs.end() && it->second) { continue; - _loadDeps(dep,objs,deps); + } + _loadDeps(dep, objs, deps); } } -std::vector -Document::readObjects(Base::XMLReader& reader) +std::vector Document::readObjects(Base::XMLReader& reader) { d->touchedObjs.clear(); bool keepDigits = testStatus(Document::KeepTrailingDigits); @@ -1329,65 +1439,75 @@ Document::readObjects(Base::XMLReader& reader) reader.readElement("Objects"); int Cnt = reader.getAttributeAsInteger("Count"); - if(!reader.hasAttribute(FC_ATTR_DEPENDENCIES)) + if (!reader.hasAttribute(FC_ATTR_DEPENDENCIES)) { d->partialLoadObjects.clear(); - else if(!d->partialLoadObjects.empty()) { - std::unordered_map deps; - for (int i=0 ;ipartialLoadObjects.empty()) { + std::unordered_map deps; + for (int i = 0; i < Cnt; i++) { reader.readElement(FC_ELEMENT_OBJECT_DEPS); int dcount = reader.getAttributeAsInteger(FC_ATTR_DEP_COUNT); - if(!dcount) + if (!dcount) { continue; - auto &info = deps[reader.getAttribute(FC_ATTR_DEP_OBJ_NAME)]; - if(reader.hasAttribute(FC_ATTR_DEP_ALLOW_PARTIAL)) + } + auto& info = deps[reader.getAttribute(FC_ATTR_DEP_OBJ_NAME)]; + if (reader.hasAttribute(FC_ATTR_DEP_ALLOW_PARTIAL)) { info.canLoadPartial = reader.getAttributeAsInteger(FC_ATTR_DEP_ALLOW_PARTIAL); - for(int j=0;j objs; objs.reserve(d->partialLoadObjects.size()); - for(auto &v : d->partialLoadObjects) + for (auto& v : d->partialLoadObjects) { objs.emplace_back(v.first.c_str()); - for(auto &name : objs) - _loadDeps(name,d->partialLoadObjects,deps); - if(Cnt > (int)d->partialLoadObjects.size()) - setStatus(Document::PartialDoc,true); + } + for (auto& name : objs) { + _loadDeps(name, d->partialLoadObjects, deps); + } + if (Cnt > (int)d->partialLoadObjects.size()) { + setStatus(Document::PartialDoc, true); + } else { - for(auto &v : d->partialLoadObjects) { - if(!v.second) { - setStatus(Document::PartialDoc,true); + for (auto& v : d->partialLoadObjects) { + if (!v.second) { + setStatus(Document::PartialDoc, true); break; } } - if(!testStatus(Document::PartialDoc)) + if (!testStatus(Document::PartialDoc)) { d->partialLoadObjects.clear(); + } } } long lastId = 0; - for (int i=0 ;ipartialLoadObjects.empty()) { + if (!d->partialLoadObjects.empty()) { auto it = d->partialLoadObjects.find(name); - if(it == d->partialLoadObjects.end()) + if (it == d->partialLoadObjects.end()) { continue; + } partial = !it->second; } - if(!testStatus(Status::Importing) && reader.hasAttribute("id")) { + if (!testStatus(Status::Importing) && reader.hasAttribute("id")) { // if not importing, then temporary reset lastObjectId and make the // following addObject() generate the correct id for this object. - d->lastObjectId = reader.getAttributeAsInteger("id")-1; + d->lastObjectId = reader.getAttributeAsInteger("id") - 1; } // To prevent duplicate name when export/import of objects from @@ -1399,22 +1519,26 @@ Document::readObjects(Base::XMLReader& reader) // correctly unmap the names. auto pos = name.find('@'); std::string _obj_name; - const char *obj_name; - if(pos!=std::string::npos) { - _obj_name = name.substr(0,pos); + const char* obj_name; + if (pos != std::string::npos) { + _obj_name = name.substr(0, pos); obj_name = _obj_name.c_str(); - }else + } + else { obj_name = name.c_str(); + } try { // Use name from XML as is and do NOT remove trailing digits because // otherwise we may cause a dependency to itself // Example: Object 'Cut001' references object 'Cut' and removing the // digits we make an object 'Cut' referencing itself. - App::DocumentObject* obj = addObject(type.c_str(), obj_name, /*isNew=*/ false, viewType.c_str(), partial); + App::DocumentObject* obj = + addObject(type.c_str(), obj_name, /*isNew=*/false, viewType.c_str(), partial); if (obj) { - if(lastId < obj->_Id) + if (lastId < obj->_Id) { lastId = obj->_Id; + } objs.push_back(obj); // use this name for the later access because an object with // the given name may already exist @@ -1422,13 +1546,16 @@ Document::readObjects(Base::XMLReader& reader) // restore touch/error status flags if (reader.hasAttribute("Touched")) { - if(reader.getAttributeAsInteger("Touched") != 0) + if (reader.getAttributeAsInteger("Touched") != 0) { d->touchedObjs.insert(obj); + } } if (reader.hasAttribute("Invalid")) { - obj->setStatus(ObjectStatus::Error, reader.getAttributeAsInteger("Invalid") != 0); - if(obj->isError() && reader.hasAttribute("Error")) - d->addRecomputeLog(reader.getAttribute("Error"),obj); + obj->setStatus(ObjectStatus::Error, + reader.getAttributeAsInteger("Invalid") != 0); + if (obj->isError() && reader.hasAttribute("Error")) { + d->addRecomputeLog(reader.getAttribute("Error"), obj); + } } } } @@ -1436,8 +1563,9 @@ Document::readObjects(Base::XMLReader& reader) Base::Console().Error("Cannot create object '%s': (%s)\n", name.c_str(), e.what()); } } - if(!testStatus(Status::Importing)) + if (!testStatus(Status::Importing)) { d->lastObjectId = lastId; + } reader.readEndElement("Objects"); setStatus(Document::KeepTrailingDigits, keepDigits); @@ -1446,11 +1574,13 @@ Document::readObjects(Base::XMLReader& reader) reader.clearPartialRestoreDocumentObject(); reader.readElement("ObjectData"); Cnt = reader.getAttributeAsInteger("Count"); - for (int i=0 ;itestStatus(App::PartialObject)) { // check if this feature has been registered + if (pObj + && !pObj->testStatus( + App::PartialObject)) { // check if this feature has been registered pObj->setStatus(ObjectStatus::Restore, true); try { FC_TRACE("restoring " << pObj->getFullName()); @@ -1458,26 +1588,28 @@ Document::readObjects(Base::XMLReader& reader) } // Try to continue only for certain exception types if not handled // by the feature type. For all other exception types abort the process. - catch (const Base::UnicodeError &e) { + catch (const Base::UnicodeError& e) { e.ReportException(); } - catch (const Base::ValueError &e) { + catch (const Base::ValueError& e) { e.ReportException(); } - catch (const Base::IndexError &e) { + catch (const Base::IndexError& e) { e.ReportException(); } - catch (const Base::RuntimeError &e) { + catch (const Base::RuntimeError& e) { e.ReportException(); } - catch (const Base::XMLAttributeError &e) { + catch (const Base::XMLAttributeError& e) { e.ReportException(); } pObj->setStatus(ObjectStatus::Restore, false); if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInDocumentObject)) { - Base::Console().Error("Object \"%s\" was subject to a partial restore. As a result geometry may have changed or be incomplete.\n",name.c_str()); + Base::Console().Error("Object \"%s\" was subject to a partial restore. As a result " + "geometry may have changed or be incomplete.\n", + name.c_str()); reader.clearPartialRestoreDocumentObject(); } } @@ -1488,16 +1620,16 @@ Document::readObjects(Base::XMLReader& reader) return objs; } -void Document::addRecomputeObject(DocumentObject *obj) { - if(testStatus(Status::Restoring) && obj) { +void Document::addRecomputeObject(DocumentObject* obj) +{ + if (testStatus(Status::Restoring) && obj) { setStatus(Status::RecomputeOnRestore, true); d->touchedObjs.insert(obj); obj->touch(); } } -std::vector -Document::importObjects(Base::XMLReader& reader) +std::vector Document::importObjects(Base::XMLReader& reader) { d->hashers.clear(); Base::FlagToggler<> flag(globalIsRestoring, false); @@ -1509,31 +1641,37 @@ Document::importObjects(Base::XMLReader& reader) reader.DocumentSchema = scheme; if (reader.hasAttribute("ProgramVersion")) { reader.ProgramVersion = reader.getAttribute("ProgramVersion"); - } else { + } + else { reader.ProgramVersion = "pre-0.14"; } if (reader.hasAttribute("FileVersion")) { reader.FileVersion = reader.getAttributeAsUnsigned("FileVersion"); - } else { + } + else { reader.FileVersion = 0; } std::vector objs = readObjects(reader); - for(auto o : objs) { - if(o && o->isAttachedToDocument()) { - o->setStatus(App::ObjImporting,true); + for (auto o : objs) { + if (o && o->isAttachedToDocument()) { + o->setStatus(App::ObjImporting, true); FC_LOG("importing " << o->getFullName()); - if (auto propUUID = Base::freecad_dynamic_cast( - o->getPropertyByName("_ObjectUUID"))) - { - auto propSource = Base::freecad_dynamic_cast( - o->getPropertyByName("_SourceUUID")); - if (!propSource) - propSource = static_cast(o->addDynamicProperty( - "App::PropertyUUID", "_SourceUUID", nullptr, nullptr, - Prop_Output | Prop_Hidden)); - if (propSource) + if (auto propUUID = + Base::freecad_dynamic_cast(o->getPropertyByName("_ObjectUUID"))) { + auto propSource = + Base::freecad_dynamic_cast(o->getPropertyByName("_SourceUUID")); + if (!propSource) { + propSource = static_cast( + o->addDynamicProperty("App::PropertyUUID", + "_SourceUUID", + nullptr, + nullptr, + Prop_Output | Prop_Hidden)); + } + if (propSource) { propSource->setValue(propUUID->getValue()); + } propUUID->setValue(Base::Uuid::createUuid()); } } @@ -1542,27 +1680,29 @@ Document::importObjects(Base::XMLReader& reader) reader.readEndElement("Document"); signalImportObjects(objs, reader); - afterRestore(objs,true); + afterRestore(objs, true); signalFinishImportObjects(objs); - for(auto o : objs) { - if(o && o->isAttachedToDocument()) - o->setStatus(App::ObjImporting,false); + for (auto o : objs) { + if (o && o->isAttachedToDocument()) { + o->setStatus(App::ObjImporting, false); + } } d->hashers.clear(); return objs; } -unsigned int Document::getMemSize () const +unsigned int Document::getMemSize() const { unsigned int size = 0; // size of the DocObjects in the document std::vector::const_iterator it; - for (it = d->objectArray.begin(); it != d->objectArray.end(); ++it) + for (it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { size += (*it)->getMemSize(); + } size += d->Hasher->getMemSize(); @@ -1575,20 +1715,23 @@ unsigned int Document::getMemSize () const return size; } -static std::string checkFileName(const char *file) { +static std::string checkFileName(const char* file) +{ std::string fn(file); // Append extension if missing. This option is added for security reason, so // that the user won't accidentally overwrite other file that may be critical. - if(App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("CheckExtension",true)) - { - const char *ext = strrchr(file,'.'); - if(!ext || !boost::iequals(ext+1,"fcstd")) { - if(ext && ext[1] == 0) + if (App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("CheckExtension", true)) { + const char* ext = strrchr(file, '.'); + if (!ext || !boost::iequals(ext + 1, "fcstd")) { + if (ext && ext[1] == 0) { fn += "FCStd"; - else + } + else { fn += ".FCStd"; + } } } return fn; @@ -1601,7 +1744,7 @@ bool Document::saveAs(const char* _file) if (this->FileName.getStrValue() != file) { this->FileName.setValue(file); this->Label.setValue(fi.fileNamePure()); - this->Uid.touch(); // this forces a rename of the transient directory + this->Uid.touch(); // this forces a rename of the transient directory } return save(); @@ -1618,9 +1761,9 @@ bool Document::saveCopy(const char* _file) const } // Save the document under the name it has been opened -bool Document::save () +bool Document::save() { - if(testStatus(Document::PartialDoc)) { + if (testStatus(Document::PartialDoc)) { FC_ERR("Partial loaded document '" << Label.getValue() << "' cannot be saved"); // TODO We don't make this a fatal error and return 'true' to make it possible to // save other documents that depends on this partial opened document. We need better @@ -1637,11 +1780,15 @@ bool Document::save () std::string LastModifiedDateString = Base::Tools::currentDateTimeString(); LastModifiedDate.setValue(LastModifiedDateString.c_str()); // set author if needed - bool saveAuthor = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("prefSetAuthorOnSave",false); + bool saveAuthor = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("prefSetAuthorOnSave", false); if (saveAuthor) { - std::string Author = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("prefAuthor",""); + std::string Author = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("prefAuthor", ""); LastModifiedBy.setValue(Author.c_str()); } @@ -1651,46 +1798,56 @@ bool Document::save () return false; } -namespace App { +namespace App +{ // Helper class to handle different backup policies -class BackupPolicy { +class BackupPolicy +{ public: - enum Policy { + enum Policy + { Standard, TimeStamp }; - BackupPolicy() { + BackupPolicy() + { policy = Standard; numberOfFiles = 1; useFCBakExtension = true; saveBackupDateFormat = "%Y%m%d-%H%M%S"; } ~BackupPolicy() = default; - void setPolicy(Policy p) { + void setPolicy(Policy p) + { policy = p; } - void setNumberOfFiles(int count) { + void setNumberOfFiles(int count) + { numberOfFiles = count; } - void useBackupExtension(bool on) { + void useBackupExtension(bool on) + { useFCBakExtension = on; } - void setDateFormat(const std::string& fmt) { + void setDateFormat(const std::string& fmt) + { saveBackupDateFormat = fmt; } - void apply(const std::string& sourcename, const std::string& targetname) { + void apply(const std::string& sourcename, const std::string& targetname) + { switch (policy) { - case Standard: - applyStandard(sourcename, targetname); - break; - case TimeStamp: - applyTimeStamp(sourcename, targetname); - break; + case Standard: + applyStandard(sourcename, targetname); + break; + case TimeStamp: + applyTimeStamp(sourcename, targetname); + break; } } private: - void applyStandard(const std::string& sourcename, const std::string& targetname) { + void applyStandard(const std::string& sourcename, const std::string& targetname) + { // if saving the project data succeeded rename to the actual file name Base::FileInfo fi(targetname); if (fi.exists()) { @@ -1702,12 +1859,12 @@ class BackupPolicy { std::vector files = di.getDirectoryContent(); for (const Base::FileInfo& it : files) { std::string file = it.fileName(); - if (file.substr(0,fn.length()) == fn) { + if (file.substr(0, fn.length()) == fn) { // starts with the same file name std::string suf(file.substr(fn.length())); if (!suf.empty()) { std::string::size_type nPos = suf.find_first_not_of("0123456789"); - if (nPos==std::string::npos) { + if (nPos == std::string::npos) { // store all backup files backup.push_back(it); nSuff = std::max(nSuff, std::atol(suf.c_str())); @@ -1720,8 +1877,9 @@ class BackupPolicy { // delete the oldest backup file we found Base::FileInfo del = backup.front(); for (const Base::FileInfo& it : backup) { - if (it.lastModified() < del.lastModified()) + if (it.lastModified() < del.lastModified()) { del = it; + } } del.deleteFile(); @@ -1734,8 +1892,9 @@ class BackupPolicy { fn = str.str(); } - if (!fi.renameFile(fn.c_str())) + if (!fi.renameFile(fn.c_str())) { Base::Console().Warning("Cannot rename project file to backup file\n"); + } } else { fi.deleteFile(); @@ -1744,17 +1903,18 @@ class BackupPolicy { Base::FileInfo tmp(sourcename); if (!tmp.renameFile(targetname.c_str())) { - throw Base::FileException( - "Cannot rename tmp save file to project file", Base::FileInfo(targetname)); + throw Base::FileException("Cannot rename tmp save file to project file", + Base::FileInfo(targetname)); } } - void applyTimeStamp(const std::string& sourcename, const std::string& targetname) { + void applyTimeStamp(const std::string& sourcename, const std::string& targetname) + { Base::FileInfo fi(targetname); std::string fn = sourcename; std::string ext = fi.extension(); - std::string bn; // full path with no extension but with "." - std::string pbn; // base name of the project + "." + std::string bn; // full path with no extension but with "." + std::string pbn; // base name of the project + "." if (!ext.empty()) { bn = fi.filePath().substr(0, fi.filePath().length() - ext.length()); pbn = fi.fileName().substr(0, fi.fileName().length() - ext.length()); @@ -1764,7 +1924,7 @@ class BackupPolicy { pbn = fi.fileName() + "."; } - bool backupManagementError = false; // Note error and report at the end + bool backupManagementError = false; // Note error and report at the end if (fi.exists()) { if (numberOfFiles > 0) { // replace . by - in format to avoid . between base name and extension @@ -1780,25 +1940,30 @@ class BackupPolicy { std::string file = it.fileName(); std::string fext = it.extension(); std::string fextUp = fext; - std::transform(fextUp.begin(), fextUp.end(), fextUp.begin(),(int (*)(int))toupper); + std::transform(fextUp.begin(), + fextUp.end(), + fextUp.begin(), + (int (*)(int))toupper); // re-enforcing identification of the backup file - // old case : the name starts with the full name of the project and follows with numbers - if ((startsWith(file, fn) && - (file.length() > fn.length()) && - checkDigits(file.substr(fn.length()))) || - // .FCBak case : The bame starts with the base name of the project + "." - // + complement with no "." + ".FCBak" - ((fextUp == "FCBAK") && startsWith(file, pbn) && - (checkValidComplement(file, pbn, fext)))) { + // old case : the name starts with the full name of the project and + // follows with numbers + if ((startsWith(file, fn) && (file.length() > fn.length()) + && checkDigits(file.substr(fn.length()))) + || + // .FCBak case : The bame starts with the base name of the project + + // "." + // + complement with no "." + ".FCBak" + ((fextUp == "FCBAK") && startsWith(file, pbn) + && (checkValidComplement(file, pbn, fext)))) { backup.push_back(it); } } } if (!backup.empty() && (int)backup.size() >= numberOfFiles) { - std::sort (backup.begin(), backup.end(), fileComparisonByDate); + std::sort(backup.begin(), backup.end(), fileComparisonByDate); // delete the oldest backup file we found // Base::FileInfo del = backup.front(); int nb = 0; @@ -1808,18 +1973,19 @@ class BackupPolicy { try { if (!it.deleteFile()) { backupManagementError = true; - Base::Console().Warning("Cannot remove backup file : %s\n", it.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file : %s\n", + it.fileName().c_str()); } } catch (...) { backupManagementError = true; - Base::Console().Warning("Cannot remove backup file : %s\n", it.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file : %s\n", + it.fileName().c_str()); } } } - } - } //end remove backup + } // end remove backup // create a new backup file { @@ -1828,22 +1994,23 @@ class BackupPolicy { std::stringstream str; Base::TimeInfo ti = fi.lastModified(); time_t s = ti.getTime_t(); - struct tm * timeinfo = localtime(& s); + struct tm* timeinfo = localtime(&s); char buffer[100]; - strftime(buffer,sizeof(buffer),saveBackupDateFormat.c_str(),timeinfo); - str << bn << buffer ; + strftime(buffer, sizeof(buffer), saveBackupDateFormat.c_str(), timeinfo); + str << bn << buffer; fn = str.str(); bool done = false; - if ((fn.empty()) || (fn[fn.length()-1] == ' ') || (fn[fn.length()-1] == '-')) { - if (fn[fn.length()-1] == ' ') { - fn = fn.substr(0,fn.length()-1); + if ((fn.empty()) || (fn[fn.length() - 1] == ' ') + || (fn[fn.length() - 1] == '-')) { + if (fn[fn.length() - 1] == ' ') { + fn = fn.substr(0, fn.length() - 1); } } else { - if (!renameFileNoErase(fi, fn+".FCBak")) { + if (!renameFileNoErase(fi, fn + ".FCBak")) { fn = fn + "-"; } else { @@ -1853,25 +2020,31 @@ class BackupPolicy { if (!done) { while (ext < numberOfFiles + 10) { - if (renameFileNoErase(fi, fn+std::to_string(ext)+".FCBak")) + if (renameFileNoErase(fi, fn + std::to_string(ext) + ".FCBak")) { break; + } ext++; } } } else { - // changed but simpler and solves also the delay sometimes introduced by google drive + // changed but simpler and solves also the delay sometimes introduced by + // google drive while (ext < numberOfFiles + 10) { - // linux just replace the file if exists, and then the existence is to be tested before rename - if (renameFileNoErase(fi, fi.filePath()+std::to_string(ext))) + // linux just replace the file if exists, and then the existence is to + // be tested before rename + if (renameFileNoErase(fi, fi.filePath() + std::to_string(ext))) { break; + } ext++; } } if (ext >= numberOfFiles + 10) { - Base::Console().Error("File not saved: Cannot rename project file to backup file\n"); - //throw Base::FileException("File not saved: Cannot rename project file to backup file", fi); + Base::Console().Error( + "File not saved: Cannot rename project file to backup file\n"); + // throw Base::FileException("File not saved: Cannot rename project file to + // backup file", fi); } } } @@ -1880,7 +2053,8 @@ class BackupPolicy { fi.deleteFile(); } catch (...) { - Base::Console().Warning("Cannot remove backup file: %s\n", fi.fileName().c_str()); + Base::Console().Warning("Cannot remove backup file: %s\n", + fi.fileName().c_str()); backupManagementError = true; } } @@ -1889,36 +2063,46 @@ class BackupPolicy { Base::FileInfo tmp(sourcename); if (!tmp.renameFile(targetname.c_str())) { throw Base::FileException( - "Save interrupted: Cannot rename temporary file to project file", tmp); + "Save interrupted: Cannot rename temporary file to project file", + tmp); } if (backupManagementError) { - throw Base::FileException("Warning: Save complete, but error while managing backup history.", fi); + throw Base::FileException( + "Warning: Save complete, but error while managing backup history.", + fi); } } - static bool fileComparisonByDate(const Base::FileInfo& i, - const Base::FileInfo& j) { - return (i.lastModified()>j.lastModified()); + static bool fileComparisonByDate(const Base::FileInfo& i, const Base::FileInfo& j) + { + return (i.lastModified() > j.lastModified()); } - bool startsWith(const std::string& st1, - const std::string& st2) const { - return st1.substr(0,st2.length()) == st2; + bool startsWith(const std::string& st1, const std::string& st2) const + { + return st1.substr(0, st2.length()) == st2; } - bool checkValidString (const std::string& cmpl, const boost::regex& e) const { + bool checkValidString(const std::string& cmpl, const boost::regex& e) const + { boost::smatch what; - bool res = boost::regex_search (cmpl,what,e); + bool res = boost::regex_search(cmpl, what, e); return res; } - bool checkValidComplement(const std::string& file, const std::string& pbn, const std::string& ext) const { - std::string cmpl = file.substr(pbn.length(),file.length()- pbn.length() - ext.length()-1); - boost::regex e (R"(^[^.]*$)"); - return checkValidString(cmpl,e); + bool checkValidComplement(const std::string& file, + const std::string& pbn, + const std::string& ext) const + { + std::string cmpl = + file.substr(pbn.length(), file.length() - pbn.length() - ext.length() - 1); + boost::regex e(R"(^[^.]*$)"); + return checkValidString(cmpl, e); } - bool checkDigits (const std::string& cmpl) const { - boost::regex e (R"(^[0-9]*$)"); - return checkValidString(cmpl,e); + bool checkDigits(const std::string& cmpl) const + { + boost::regex e(R"(^[0-9]*$)"); + return checkValidString(cmpl, e); } - bool renameFileNoErase(Base::FileInfo fi, const std::string& newName) { + bool renameFileNoErase(Base::FileInfo fi, const std::string& newName) + { // linux just replaces the file if it exists, so the existence is to be tested before rename Base::FileInfo nf(newName); if (!nf.exists()) { @@ -1933,18 +2117,20 @@ class BackupPolicy { bool useFCBakExtension; std::string saveBackupDateFormat; }; -} +} // namespace App bool Document::saveToFile(const char* filename) const { signalStartSave(*this, filename); - auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); - int compression = hGrp->GetInt("CompressionLevel",7); + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Document"); + int compression = hGrp->GetInt("CompressionLevel", 7); compression = Base::clamp(compression, Z_NO_COMPRESSION, Z_BEST_COMPRESSION); - bool policy = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("BackupPolicy",true); + bool policy = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("BackupPolicy", true); auto canonical_path = [](const char* filename) { try { @@ -1975,7 +2161,7 @@ bool Document::saveToFile(const char* filename) const } }; - //realpath is canonical filename i.e. without symlink + // realpath is canonical filename i.e. without symlink std::string nativePath = canonical_path(filename); // make a tmp. file where to save the project data first and then rename to @@ -2002,12 +2188,14 @@ bool Document::saveToFile(const char* filename) const writer.setLevel(compression); writer.putNextEntry("Document.xml"); - if (hGrp->GetBool("SaveBinaryBrep", false)) + if (hGrp->GetBool("SaveBinaryBrep", false)) { writer.setMode("BinaryBrep"); + } writer.Stream() << "" << endl << "" << endl; Document::Save(writer); @@ -2026,17 +2214,23 @@ bool Document::saveToFile(const char* filename) const if (policy) { // if saving the project data succeeded rename to the actual file name - int count_bak = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetInt("CountBackupFiles",1); - bool backup = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("CreateBackupFiles",true); + int count_bak = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetInt("CountBackupFiles", 1); + bool backup = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("CreateBackupFiles", true); if (!backup) { count_bak = -1; } - bool useFCBakExtension = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetBool("UseFCBakExtension",true); - std::string saveBackupDateFormat = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Document")->GetASCII("SaveBackupDateFormat","%Y%m%d-%H%M%S"); + bool useFCBakExtension = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetBool("UseFCBakExtension", true); + std::string saveBackupDateFormat = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("SaveBackupDateFormat", "%Y%m%d-%H%M%S"); BackupPolicy policy; if (useFCBakExtension) { @@ -2056,19 +2250,21 @@ bool Document::saveToFile(const char* filename) const return true; } -bool Document::isAnyRestoring() { +bool Document::isAnyRestoring() +{ return globalIsRestoring; } // Open the document -void Document::restore (const char *filename, - bool delaySignal, const std::vector &objNames) +void Document::restore(const char* filename, + bool delaySignal, + const std::vector& objNames) { clearUndos(); d->activeObject = nullptr; bool signal = false; - Document *activeDoc = GetApplication().getActiveDocument(); + Document* activeDoc = GetApplication().getActiveDocument(); if (!d->objectArray.empty()) { signal = true; GetApplication().signalDeleteDocument(*this); @@ -2077,7 +2273,7 @@ void Document::restore (const char *filename, Base::FlagToggler<> flag(globalIsRestoring, false); - setStatus(Document::PartialDoc,false); + setStatus(Document::PartialDoc, false); d->clearRecomputeLog(); d->objectArray.clear(); @@ -2085,37 +2281,43 @@ void Document::restore (const char *filename, d->objectIdMap.clear(); d->lastObjectId = 0; - if(signal) { - GetApplication().signalNewDocument(*this,true); - if(activeDoc == this) + if (signal) { + GetApplication().signalNewDocument(*this, true); + if (activeDoc == this) { GetApplication().setActiveDocument(this); + } } - if(!filename) + if (!filename) { filename = FileName.getValue(); + } Base::FileInfo fi(filename); Base::ifstream file(fi, std::ios::in | std::ios::binary); std::streambuf* buf = file.rdbuf(); std::streamoff size = buf->pubseekoff(0, std::ios::end, std::ios::in); buf->pubseekoff(0, std::ios::beg, std::ios::in); - if (size < 22) // an empty zip archive has 22 bytes - throw Base::FileException("Invalid project file",filename); + if (size < 22) { // an empty zip archive has 22 bytes + throw Base::FileException("Invalid project file", filename); + } zipios::ZipInputStream zipstream(file); Base::XMLReader reader(filename, zipstream); - if (!reader.isValid()) - throw Base::FileException("Error reading compression file",filename); + if (!reader.isValid()) { + throw Base::FileException("Error reading compression file", filename); + } GetApplication().signalStartRestoreDocument(*this); setStatus(Document::Restoring, true); d->partialLoadObjects.clear(); - for(auto &name : objNames) - d->partialLoadObjects.emplace(name,true); + for (auto& name : objNames) { + d->partialLoadObjects.emplace(name, true); + } try { Document::Restore(reader); - } catch (const Base::Exception& e) { + } + catch (const Base::Exception& e) { Base::Console().Error("Invalid Document.xml: %s\n", e.what()); setStatus(Document::RestoreError, true); } @@ -2134,16 +2336,20 @@ void Document::restore (const char *filename, if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestore)) { setStatus(Document::PartialRestore, true); - Base::Console().Error("There were errors while loading the file. Some data might have been modified or not recovered at all. Look above for more specific information about the objects involved.\n"); + Base::Console().Error("There were errors while loading the file. Some data might have been " + "modified or not recovered at all. Look above for more specific " + "information about the objects involved.\n"); } - if(!delaySignal) + if (!delaySignal) { afterRestore(true); + } } -bool Document::afterRestore(bool checkPartial) { +bool Document::afterRestore(bool checkPartial) +{ Base::FlagToggler<> flag(globalIsRestoring, false); - if(!afterRestore(d->objectArray,checkPartial)) { + if (!afterRestore(d->objectArray, checkPartial)) { FC_WARN("Reload partial document " << getName()); GetApplication().signalPendingReloadDocument(*this); return false; @@ -2153,11 +2359,12 @@ bool Document::afterRestore(bool checkPartial) { return true; } -bool Document::afterRestore(const std::vector &objArray, bool checkPartial) +bool Document::afterRestore(const std::vector& objArray, bool checkPartial) { checkPartial = checkPartial && testStatus(Document::PartialDoc); - if(checkPartial && !d->touchedObjs.empty()) + if (checkPartial && !d->touchedObjs.empty()) { return false; + } // some link type property cannot restore link information until other // objects has been restored. For example, PropertyExpressionEngine and @@ -2165,86 +2372,95 @@ bool Document::afterRestore(const std::vector &objArray, bool // Property::afterRestore() interface to let them sort it out. Note, this // API is not called in object dedpenency order, because the order // information is not ready yet. - std::map > propMap; - for(auto obj : objArray) { - auto &props = propMap[obj]; + std::map> propMap; + for (auto obj : objArray) { + auto& props = propMap[obj]; obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { try { prop->afterRestore(); - } catch (const Base::Exception& e) { - FC_ERR("Failed to restore " << obj->getFullName() - << '.' << prop->getName() << ": " << e.what()); + } + catch (const Base::Exception& e) { + FC_ERR("Failed to restore " << obj->getFullName() << '.' << prop->getName() << ": " + << e.what()); } } } - if(checkPartial && !d->touchedObjs.empty()) { + if (checkPartial && !d->touchedObjs.empty()) { // partial document touched, signal full reload return false; } - std::set objSet(objArray.begin(),objArray.end()); - auto objs = getDependencyList(objArray.empty()?d->objectArray:objArray,DepSort); + std::set objSet(objArray.begin(), objArray.end()); + auto objs = getDependencyList(objArray.empty() ? d->objectArray : objArray, DepSort); for (auto obj : objs) { - if(objSet.find(obj)==objSet.end()) + if (objSet.find(obj) == objSet.end()) { continue; + } try { - for(auto prop : propMap[obj]) + for (auto prop : propMap[obj]) { prop->onContainerRestored(); + } bool touched = false; - auto returnCode = obj->ExpressionEngine.execute( - PropertyExpressionEngine::ExecuteOnRestore,&touched); - if(returnCode!=DocumentObject::StdReturn) { - FC_ERR("Expression engine failed to restore " << obj->getFullName() << ": " << returnCode->Why); + auto returnCode = + obj->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOnRestore, &touched); + if (returnCode != DocumentObject::StdReturn) { + FC_ERR("Expression engine failed to restore " << obj->getFullName() << ": " + << returnCode->Why); d->addRecomputeLog(returnCode); } obj->onDocumentRestored(); - if(touched) + if (touched) { d->touchedObjs.insert(obj); + } } catch (const Base::Exception& e) { - d->addRecomputeLog(e.what(),obj); + d->addRecomputeLog(e.what(), obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << e.what()); } - catch (std::exception &e) { - d->addRecomputeLog(e.what(),obj); + catch (std::exception& e) { + d->addRecomputeLog(e.what(), obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << e.what()); } catch (...) { - d->addRecomputeLog("Unknown exception on restore",obj); + d->addRecomputeLog("Unknown exception on restore", obj); FC_ERR("Failed to restore " << obj->getFullName() << ": " << "unknown exception"); } - if(obj->isValid()) { - auto &props = propMap[obj]; + if (obj->isValid()) { + auto& props = propMap[obj]; props.clear(); // refresh properties in case the object changes its property list obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto link = Base::freecad_dynamic_cast(prop); int res; std::string errMsg; - if(link && (res=link->checkRestore(&errMsg))) { + if (link && (res = link->checkRestore(&errMsg))) { d->touchedObjs.insert(obj); - if(res==1 || checkPartial) { + if (res == 1 || checkPartial) { FC_WARN(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); setStatus(Document::LinkStampChanged, true); - if(checkPartial) + if (checkPartial) { return false; - } else { + } + } + else { FC_ERR(obj->getFullName() << '.' << prop->getName() << ": " << errMsg); - d->addRecomputeLog(errMsg,obj); + d->addRecomputeLog(errMsg, obj); setStatus(Document::PartialRestore, true); } } } } - if(checkPartial && !d->touchedObjs.empty()) { + if (checkPartial && !d->touchedObjs.empty()) { // partial document touched, signal full reload return false; - } else if(!d->touchedObjs.count(obj)) + } + else if (!d->touchedObjs.count(obj)) { obj->purgeTouched(); + } signalFinishRestoreObject(*obj); } @@ -2263,14 +2479,14 @@ bool Document::isSaved() const * or in the tree view. The label almost (but not always e.g. if you manually change it) * matches with the file name where the document is stored to. * In contrast to Label the method getName() returns the internal name of the document that only - * matches with Label when loading or creating a document because then both are set to the same value. - * Since the internal name cannot be changed during runtime it must differ from the Label after saving - * the document the first time or saving it under a new file name. + * matches with Label when loading or creating a document because then both are set to the same + * value. Since the internal name cannot be changed during runtime it must differ from the Label + * after saving the document the first time or saving it under a new file name. * @ note More than one document can have the same label name. - * @ note The internal is always guaranteed to be unique because @ref Application::newDocument() checks - * for a document with the same name and makes it unique if needed. Hence you cannot rely on that the - * internal name matches with the name you passed to Application::newDoument(). You should use the - * method getName() instead. + * @ note The internal is always guaranteed to be unique because @ref Application::newDocument() + * checks for a document with the same name and makes it unique if needed. Hence you cannot rely on + * that the internal name matches with the name you passed to Application::newDoument(). You should + * use the method getName() instead. */ const char* Document::getName() const { @@ -2278,7 +2494,8 @@ const char* Document::getName() const return myName.c_str(); } -std::string Document::getFullName() const { +std::string Document::getFullName() const +{ return myName; } @@ -2289,15 +2506,15 @@ const char* Document::getProgramVersion() const const char* Document::getFileName() const { - return testStatus(TempDoc) ? TransientDir.getValue() - : FileName.getValue(); + return testStatus(TempDoc) ? TransientDir.getValue() : FileName.getValue(); } /// Remove all modifications. After this call The document becomes valid again. void Document::purgeTouched() { - for (auto It : d->objectArray) + for (auto It : d->objectArray) { It->purgeTouched(); + } } bool Document::isTouched() const @@ -2335,63 +2552,76 @@ bool Document::isClosable() const int Document::countObjects() const { - return static_cast(d->objectArray.size()); + return static_cast(d->objectArray.size()); } -void Document::getLinksTo(std::set &links, - const DocumentObject *obj, int options, int maxCount, - const std::vector &objs) const +void Document::getLinksTo(std::set& links, + const DocumentObject* obj, + int options, + int maxCount, + const std::vector& objs) const { - std::map > linkMap; + std::map> linkMap; - for(auto o : !objs.empty() ? objs : d->objectArray) { - if (o == obj) + for (auto o : !objs.empty() ? objs : d->objectArray) { + if (o == obj) { continue; + } auto linked = o; if (options & GetLinkArrayElement) { linked = o->getLinkedObject(false); } else { auto ext = o->getExtensionByType(true); - if(ext) - linked = ext->getTrueLinkedObject(false,nullptr,0,true); - else + if (ext) { + linked = ext->getTrueLinkedObject(false, nullptr, 0, true); + } + else { linked = o->getLinkedObject(false); + } } - if(linked && linked!=o) { - if(options & GetLinkRecursive) + if (linked && linked != o) { + if (options & GetLinkRecursive) { linkMap[linked].push_back(o); - else if(linked == obj || !obj) { - if((options & GetLinkExternal) - && linked->getDocument()==o->getDocument()) + } + else if (linked == obj || !obj) { + if ((options & GetLinkExternal) && linked->getDocument() == o->getDocument()) { continue; - else if(options & GetLinkedObject) + } + else if (options & GetLinkedObject) { links.insert(linked); - else + } + else { links.insert(o); - if(maxCount && maxCount<=(int)links.size()) + } + if (maxCount && maxCount <= (int)links.size()) { return; + } } } } - if(!(options & GetLinkRecursive)) + if (!(options & GetLinkRecursive)) { return; + } - std::vector current(1,obj); - for(int depth=0;!current.empty();++depth) { - if(!GetApplication().checkLinkDepth(depth, MessageOption::Error)) + std::vector current(1, obj); + for (int depth = 0; !current.empty(); ++depth) { + if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) { break; + } std::vector next; - for(const App::DocumentObject *o : current) { + for (const App::DocumentObject* o : current) { auto iter = linkMap.find(o); - if(iter==linkMap.end()) + if (iter == linkMap.end()) { continue; - for (App::DocumentObject *link : iter->second) { + } + for (App::DocumentObject* link : iter->second) { if (links.insert(link).second) { - if(maxCount && maxCount<=(int)links.size()) + if (maxCount && maxCount <= (int)links.size()) { return; + } next.push_back(link); } } @@ -2401,9 +2631,10 @@ void Document::getLinksTo(std::set &links, return; } -bool Document::hasLinksTo(const DocumentObject *obj) const { - std::set links; - getLinksTo(links,obj,0,1); +bool Document::hasLinksTo(const DocumentObject* obj) const +{ + std::set links; + getLinksTo(links, obj, 0, 1); return !links.empty(); } @@ -2412,13 +2643,14 @@ std::vector Document::getInList(const DocumentObject* me) // result list std::vector result; // go through all objects - for (const auto & It : d->objectMap) { + for (const auto& It : d->objectMap) { // get the outList and search if me is in that list std::vector OutList = It.second->getOutList(); for (auto obj : OutList) { - if (obj && obj == me) + if (obj && obj == me) { // add the parent object result.push_back(It.second); + } } } return result; @@ -2437,103 +2669,122 @@ std::vector Document::getInList(const DocumentObject* me) // assumption is broken by the introduction of PropertyXLink which can link to // external object. // -static void _buildDependencyList(const std::vector &objectArray, - int options, std::vector *depObjs, - DependencyList *depList, std::map *objectMap, - bool *touchCheck = nullptr) +static void _buildDependencyList(const std::vector& objectArray, + int options, + std::vector* depObjs, + DependencyList* depList, + std::map* objectMap, + bool* touchCheck = nullptr) { - std::map > outLists; + std::map> outLists; std::deque objs; - if(objectMap) objectMap->clear(); - if(depList) depList->clear(); + if (objectMap) { + objectMap->clear(); + } + if (depList) { + depList->clear(); + } - int op = (options & Document::DepNoXLinked)?DocumentObject::OutListNoXLinked:0; + int op = (options & Document::DepNoXLinked) ? DocumentObject::OutListNoXLinked : 0; for (auto obj : objectArray) { objs.push_back(obj); - while(!objs.empty()) { + while (!objs.empty()) { auto obj = objs.front(); objs.pop_front(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } auto it = outLists.find(obj); - if(it!=outLists.end()) + if (it != outLists.end()) { continue; + } - if(touchCheck) { - if(obj->isTouched() || obj->mustExecute()) { + if (touchCheck) { + if (obj->isTouched() || obj->mustExecute()) { // early termination on touch check *touchCheck = true; return; } } - if(depObjs) depObjs->push_back(obj); - if(objectMap && depList) + if (depObjs) { + depObjs->push_back(obj); + } + if (objectMap && depList) { (*objectMap)[obj] = add_vertex(*depList); + } - auto &outList = outLists[obj]; + auto& outList = outLists[obj]; outList = obj->getOutList(op); - objs.insert(objs.end(),outList.begin(),outList.end()); + objs.insert(objs.end(), outList.begin(), outList.end()); } } - if(objectMap && depList) { - for (const auto &v : outLists) { - for(auto obj : v.second) { - if(obj && obj->isAttachedToDocument()) - add_edge((*objectMap)[v.first],(*objectMap)[obj],*depList); + if (objectMap && depList) { + for (const auto& v : outLists) { + for (auto obj : v.second) { + if (obj && obj->isAttachedToDocument()) { + add_edge((*objectMap)[v.first], (*objectMap)[obj], *depList); + } } } } } -std::vector Document::getDependencyList( - const std::vector& objectArray, int options) +std::vector +Document::getDependencyList(const std::vector& objectArray, int options) { std::vector ret; - if(!(options & DepSort)) { - _buildDependencyList(objectArray,options,&ret,nullptr,nullptr); + if (!(options & DepSort)) { + _buildDependencyList(objectArray, options, &ret, nullptr, nullptr); return ret; } DependencyList depList; - std::map objectMap; - std::map vertexMap; + std::map objectMap; + std::map vertexMap; - _buildDependencyList(objectArray,options,nullptr,&depList,&objectMap); + _buildDependencyList(objectArray, options, nullptr, &depList, &objectMap); - for(auto &v : objectMap) + for (auto& v : objectMap) { vertexMap[v.second] = v.first; + } std::list make_order; try { boost::topological_sort(depList, std::front_inserter(make_order)); - } catch (const std::exception& e) { - if(options & DepNoCycle) { + } + catch (const std::exception& e) { + if (options & DepNoCycle) { // Use boost::strong_components to find cycles. It groups strongly // connected vertices as components, and therefore each component // forms a cycle. std::vector c(vertexMap.size()); - std::map > components; - boost::strong_components(depList,boost::make_iterator_property_map( - c.begin(),boost::get(boost::vertex_index,depList),c[0])); - for(size_t i=0;i> components; + boost::strong_components( + depList, + boost::make_iterator_property_map(c.begin(), + boost::get(boost::vertex_index, depList), + c[0])); + for (size_t i = 0; i < c.size(); ++i) { components[c[i]].push_back(i); + } FC_ERR("Dependency cycles: "); std::ostringstream ss; ss << std::endl; - for(auto &v : components) { - if(v.second.size()==1) { + for (auto& v : components) { + if (v.second.size() == 1) { // For components with only one member, we still need to // check if there it is self looping. auto it = vertexMap.find(v.second[0]); - if(it==vertexMap.end()) + if (it == vertexMap.end()) { continue; + } // Try search the object in its own out list - for(auto obj : it->second->getOutList()) { - if(obj == it->second) { + for (auto obj : it->second->getOutList()) { + if (obj == it->second) { ss << std::endl << it->second->getFullName() << std::endl; break; } @@ -2541,12 +2792,14 @@ std::vector Document::getDependencyList( continue; } // For components with more than one member, they form a loop together - for(size_t i=0;isecond->getFullName() << ", "; } ss << std::endl; @@ -2556,81 +2809,94 @@ std::vector Document::getDependencyList( } FC_ERR(e.what()); ret = DocumentP::partialTopologicalSort(objectArray); - std::reverse(ret.begin(),ret.end()); + std::reverse(ret.begin(), ret.end()); return ret; } - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { ret.push_back(vertexMap[*i]); + } return ret; } -std::vector Document::getDependentDocuments(bool sort) { - return getDependentDocuments({this},sort); +std::vector Document::getDependentDocuments(bool sort) +{ + return getDependentDocuments({this}, sort); } -std::vector Document::getDependentDocuments( - std::vector pending, bool sort) +std::vector Document::getDependentDocuments(std::vector pending, + bool sort) { DependencyList depList; - std::map docMap; - std::map vertexMap; + std::map docMap; + std::map vertexMap; std::vector ret; - if(pending.empty()) + if (pending.empty()) { return ret; + } auto outLists = PropertyXLink::getDocumentOutList(); std::set docs; - docs.insert(pending.begin(),pending.end()); - if(sort) { - for(auto doc : pending) + docs.insert(pending.begin(), pending.end()); + if (sort) { + for (auto doc : pending) { docMap[doc] = add_vertex(depList); + } } - while(!pending.empty()) { + while (!pending.empty()) { auto doc = pending.back(); pending.pop_back(); auto it = outLists.find(doc); - if(it == outLists.end()) + if (it == outLists.end()) { continue; + } - auto &vertex = docMap[doc]; - for(auto depDoc : it->second) { - if(docs.insert(depDoc).second) { + auto& vertex = docMap[doc]; + for (auto depDoc : it->second) { + if (docs.insert(depDoc).second) { pending.push_back(depDoc); - if(sort) + if (sort) { docMap[depDoc] = add_vertex(depList); + } } - add_edge(vertex,docMap[depDoc],depList); + add_edge(vertex, docMap[depDoc], depList); } } - if(!sort) { - ret.insert(ret.end(),docs.begin(),docs.end()); + if (!sort) { + ret.insert(ret.end(), docs.begin(), docs.end()); return ret; } std::list make_order; try { boost::topological_sort(depList, std::front_inserter(make_order)); - } catch (const std::exception& e) { + } + catch (const std::exception& e) { std::string msg("Document::getDependentDocuments: "); msg += e.what(); throw Base::RuntimeError(msg); } - for(auto &v : docMap) + for (auto& v : docMap) { vertexMap[v.second] = v.first; - for (auto rIt=make_order.rbegin(); rIt!=make_order.rend(); ++rIt) + } + for (auto rIt = make_order.rbegin(); rIt != make_order.rend(); ++rIt) { ret.push_back(vertexMap[*rIt]); + } return ret; } -void Document::_rebuildDependencyList(const std::vector &objs) +void Document::_rebuildDependencyList(const std::vector& objs) { #ifdef USE_OLD_DAG - _buildDependencyList(objs.empty()?d->objectArray:objs,false,0,&d->DepList,&d->VertexObjectList); + _buildDependencyList(objs.empty() ? d->objectArray : objs, + false, + 0, + &d->DepList, + &d->VertexObjectList); #else (void)objs; #endif @@ -2645,9 +2911,9 @@ void Document::_rebuildDependencyList(const std::vector &o * @param paths Map with current and new names */ -void Document::renameObjectIdentifiers(const std::map &paths, - const std::function & selector) +void Document::renameObjectIdentifiers( + const std::map& paths, + const std::function& selector) { std::map extendedPaths; @@ -2665,7 +2931,7 @@ void Document::renameObjectIdentifiers(const std::map &objs, bool force) +int Document::recompute(const std::vector& objs, bool force) { if (testStatus(Document::Recomputing)) { // this is clearly a bug in the calling instance @@ -2676,8 +2942,9 @@ int Document::recompute(const std::vector &objs, bool forc // The 'SkipRecompute' flag can be (tmp.) set to avoid too many // time expensive recomputes - if(!force && testStatus(Document::SkipRecompute)) + if (!force && testStatus(Document::SkipRecompute)) { return 0; + } Base::ObjectStatusLocker exe(Document::Recomputing, this); @@ -2700,8 +2967,11 @@ int Document::recompute(const std::vector &objs, bool forc } // caching vertex to DocObject - for (std::map::const_iterator It1= d->VertexObjectList.begin();It1 != d->VertexObjectList.end(); ++It1) + for (std::map::const_iterator It1 = d->VertexObjectList.begin(); + It1 != d->VertexObjectList.end(); + ++It1) { d->vertexMap[It1->second] = It1->first; + } #ifdef FC_LOGFEATUREUPDATE std::clog << "make ordering: " << std::endl; @@ -2709,7 +2979,7 @@ int Document::recompute(const std::vector &objs, bool forc std::set recomputeList; - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) { + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { DocumentObject* Cur = d->vertexMap[*i]; // Because of PropertyXLink, we should account for external objects // TODO: make sure it is safe to rely on getNameInDocument() to check if @@ -2717,9 +2987,11 @@ int Document::recompute(const std::vector &objs, bool forc // to properly nullify getNameInDocument(), rather than revert back to // the inefficient isIn() // if (!Cur || !isIn(Cur)) continue; - if (!Cur || !Cur->getNameInDocument()) continue; + if (!Cur || !Cur->getNameInDocument()) { + continue; + } #ifdef FC_LOGFEATUREUPDATE - std::clog << Cur->getNameInDocument() << " dep on:" ; + std::clog << Cur->getNameInDocument() << " dep on:"; #endif bool NeedUpdate = false; @@ -2730,12 +3002,14 @@ int Document::recompute(const std::vector &objs, bool forc #endif NeedUpdate = true; } - else {// if (Cur->mustExecute() == -1) + else { // if (Cur->mustExecute() == -1) // update if one of the dependencies is touched for (boost::tie(j, jend) = out_edges(*i, d->DepList); j != jend; ++j) { DocumentObject* Test = d->vertexMap[target(*j, d->DepList)]; - if (!Test) continue; + if (!Test) { + continue; + } #ifdef FC_LOGFEATUREUPDATE std::clog << " " << Test->getNameInDocument(); #endif @@ -2762,18 +3036,22 @@ int Document::recompute(const std::vector &objs, bool forc #ifdef FC_LOGFEATUREUPDATE std::clog << "Have to recompute the following document objects" << std::endl; - for (std::set::const_iterator it = recomputeList.begin(); it != recomputeList.end(); ++it) { + for (std::set::const_iterator it = recomputeList.begin(); + it != recomputeList.end(); + ++it) { std::clog << " " << (*it)->getNameInDocument() << std::endl; } #endif - for (std::list::reverse_iterator i = make_order.rbegin();i != make_order.rend(); ++i) { + for (std::list::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) { DocumentObject* Cur = d->vertexMap[*i]; - if (!Cur || !isIn(Cur)) continue; + if (!Cur || !isIn(Cur)) { + continue; + } - if (recomputeList.find(Cur) != recomputeList.end() || - Cur->ExpressionEngine.depsAreTouched()) { - if ( _recomputeFeature(Cur)) { + if (recomputeList.find(Cur) != recomputeList.end() + || Cur->ExpressionEngine.depsAreTouched()) { + if (_recomputeFeature(Cur)) { // if something happened break execution of recompute d->vertexMap.clear(); return -1; @@ -2784,11 +3062,14 @@ int Document::recompute(const std::vector &objs, bool forc } // reset all touched - for (std::map::iterator it = d->vertexMap.begin(); it != d->vertexMap.end(); ++it) { + for (std::map::iterator it = d->vertexMap.begin(); + it != d->vertexMap.end(); + ++it) { // TODO: check the TODO comments above for details // if ((it->second) && isIn(it->second)) - if ((it->second) && it->second->getNameInDocument()) + if ((it->second) && it->second->getNameInDocument()) { it->second->purgeTouched(); + } } d->vertexMap.clear(); @@ -2797,20 +3078,26 @@ int Document::recompute(const std::vector &objs, bool forc return objectCount; } -#else //ifdef USE_OLD_DAG +#else // ifdef USE_OLD_DAG -int Document::recompute(const std::vector &objs, bool force, bool *hasError, int options) +int Document::recompute(const std::vector& objs, + bool force, + bool* hasError, + int options) { if (d->undoing || d->rollback) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("Ignore document recompute on undo/redo"); + } return 0; } int objectCount = 0; if (testStatus(Document::PartialDoc)) { - if(mustExecute()) - FC_WARN("Please reload partial document '" << Label.getValue() << "' for recomputation."); + if (mustExecute()) { + FC_WARN("Please reload partial document '" << Label.getValue() + << "' for recomputation."); + } return 0; } if (testStatus(Document::Recomputing)) { @@ -2820,8 +3107,8 @@ int Document::recompute(const std::vector &objs, bool forc } // The 'SkipRecompute' flag can be (tmp.) set to avoid too many // time expensive recomputes - if(!force && testStatus(Document::SkipRecompute)) { - signalSkipRecompute(*this,objs); + if (!force && testStatus(Document::SkipRecompute)) { + signalSkipRecompute(*this, objs); return 0; } @@ -2852,96 +3139,106 @@ int Document::recompute(const std::vector &objs, bool forc } std::reverse(topoSortedObjects.begin(),topoSortedObjects.end()); #else - auto topoSortedObjects = getDependencyList(objs.empty()?d->objectArray:objs,DepSort|options); + auto topoSortedObjects = + getDependencyList(objs.empty() ? d->objectArray : objs, DepSort | options); #endif - for(auto obj : topoSortedObjects) - obj->setStatus(ObjectStatus::PendingRecompute,true); + for (auto obj : topoSortedObjects) { + obj->setStatus(ObjectStatus::PendingRecompute, true); + } - ParameterGrp::handle hGrp = GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Document"); - bool canAbort = hGrp->GetBool("CanAbortRecompute",true); + ParameterGrp::handle hGrp = + GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document"); + bool canAbort = hGrp->GetBool("CanAbortRecompute", true); - std::set filter; + std::set filter; size_t idx = 0; FC_TIME_INIT(t2); try { // maximum two passes to allow some form of dependency inversion - for(int passes=0; passes<2 && idx seq; - if(canAbort) { - seq = std::make_unique("Recompute...", topoSortedObjects.size()); + if (canAbort) { + seq = std::make_unique("Recompute...", + topoSortedObjects.size()); } FC_LOG("Recompute pass " << passes); for (; idx < topoSortedObjects.size(); ++idx) { auto obj = topoSortedObjects[idx]; - if(!obj->isAttachedToDocument() || filter.find(obj)!=filter.end()) + if (!obj->isAttachedToDocument() || filter.find(obj) != filter.end()) { continue; + } // ask the object if it should be recomputed bool doRecompute = false; if (obj->mustRecompute()) { doRecompute = true; ++objectCount; int res = _recomputeFeature(obj); - if(res) { - if(hasError) + if (res) { + if (hasError) { *hasError = true; - if(res < 0) { + } + if (res < 0) { passes = 2; break; } // if something happened filter all object in its // inListRecursive from the queue then proceed - obj->getInListEx(filter,true); + obj->getInListEx(filter, true); filter.insert(obj); continue; } } - if(obj->isTouched() || doRecompute) { + if (obj->isTouched() || doRecompute) { signalRecomputedObject(*obj); obj->purgeTouched(); // set all dependent object touched to force recompute - for (auto inObjIt : obj->getInList()) + for (auto inObjIt : obj->getInList()) { inObjIt->enforceRecompute(); + } } - if (seq) + if (seq) { seq->next(true); + } } // check if all objects are recomputed but still thouched - for (size_t i=0;isetStatus(ObjectStatus::Recompute2,false); - if(!filter.count(obj) && obj->isTouched()) { - if(passes>0) + obj->setStatus(ObjectStatus::Recompute2, false); + if (!filter.count(obj) && obj->isTouched()) { + if (passes > 0) { FC_ERR(obj->getFullName() << " still touched after recompute"); - else{ + } + else { FC_LOG(obj->getFullName() << " still touched after recompute"); - if(idx>=topoSortedObjects.size()) { + if (idx >= topoSortedObjects.size()) { // let's start the next pass on the first touched object idx = i; } - obj->setStatus(ObjectStatus::Recompute2,true); + obj->setStatus(ObjectStatus::Recompute2, true); } } } } - }catch(Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); } FC_TIME_LOG(t2, "Recompute"); - for(auto obj : topoSortedObjects) { - if(!obj->isAttachedToDocument()) + for (auto obj : topoSortedObjects) { + if (!obj->isAttachedToDocument()) { continue; - obj->setStatus(ObjectStatus::PendingRecompute,false); - obj->setStatus(ObjectStatus::Recompute2,false); + } + obj->setStatus(ObjectStatus::PendingRecompute, false); + obj->setStatus(ObjectStatus::Recompute2, false); } - signalRecomputed(*this,topoSortedObjects); + signalRecomputed(*this, topoSortedObjects); - FC_TIME_LOG(t,"Recompute total"); + FC_TIME_LOG(t, "Recompute total"); if (!d->_RecomputeLog.empty()) { if (!testStatus(Status::IgnoreErrorOnRecompute)) { @@ -2959,21 +3256,23 @@ int Document::recompute(const std::vector &objs, bool forc for (auto doc : GetApplication().getDocuments()) { decltype(doc->d->pendingRemove) objs; objs.swap(doc->d->pendingRemove); - for(auto &o : objs) { + for (auto& o : objs) { try { if (auto obj = o.getObject()) { obj->getDocument()->removeObject(obj->getNameInDocument()); } - } catch (Base::Exception & e) { + } + catch (Base::Exception& e) { e.ReportException(); - FC_ERR("error when removing object " << o.getDocumentName() << '#' << o.getObjectName()); + FC_ERR("error when removing object " << o.getDocumentName() << '#' + << o.getObjectName()); } } } return objectCount; } -#endif // USE_OLD_DAG +#endif // USE_OLD_DAG /*! Does almost the same as topologicalSort() until no object with an input degree of zero @@ -2983,21 +3282,21 @@ int Document::recompute(const std::vector &objs, bool forc An alternative to this method might be: https://en.wikipedia.org/wiki/Tarjan%E2%80%99s_strongly_connected_components_algorithm */ -std::vector DocumentP::partialTopologicalSort( - const std::vector& objects) +std::vector +DocumentP::partialTopologicalSort(const std::vector& objects) { - vector < App::DocumentObject* > ret; + vector ret; ret.reserve(objects.size()); // pairs of input and output degree - map < App::DocumentObject*, std::pair > countMap; + map> countMap; for (auto objectIt : objects) { - //we need inlist with unique entries + // we need inlist with unique entries auto in = objectIt->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); - //we need outlist with unique entries + // we need outlist with unique entries auto out = objectIt->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); @@ -3013,25 +3312,27 @@ std::vector DocumentP::partialTopologicalSort( removeVertex = false; // try input degree - auto degInIt = find_if(countMap.begin(), countMap.end(), - [](pair< App::DocumentObject*, pair > vertex)->bool { - return vertex.second.first == 0; - }); + auto degInIt = find_if(countMap.begin(), + countMap.end(), + [](pair> vertex) -> bool { + return vertex.second.first == 0; + }); if (degInIt != countMap.end()) { removeVertex = true; degIn.push_back(degInIt->first); degInIt->second.first = degInIt->second.first - 1; - //we need outlist with unique entries + // we need outlist with unique entries auto out = degInIt->first->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); for (auto outListIt : out) { auto outListMapIt = countMap.find(outListIt); - if (outListMapIt != countMap.end()) + if (outListMapIt != countMap.end()) { outListMapIt->second.first = outListMapIt->second.first - 1; + } } } } @@ -3048,25 +3349,27 @@ std::vector DocumentP::partialTopologicalSort( while (removeVertex) { removeVertex = false; - auto degOutIt = find_if(countMap.begin(), countMap.end(), - [](pair< App::DocumentObject*, pair > vertex)->bool { - return vertex.second.second == 0; - }); + auto degOutIt = find_if(countMap.begin(), + countMap.end(), + [](pair> vertex) -> bool { + return vertex.second.second == 0; + }); if (degOutIt != countMap.end()) { removeVertex = true; degOut.push_front(degOutIt->first); degOutIt->second.second = degOutIt->second.second - 1; - //we need inlist with unique entries + // we need inlist with unique entries auto in = degOutIt->first->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); for (auto inListIt : in) { auto inListMapIt = countMap.find(inListIt); - if (inListMapIt != countMap.end()) + if (inListMapIt != countMap.end()) { inListMapIt->second.second = inListMapIt->second.second - 1; + } } } } @@ -3084,20 +3387,22 @@ std::vector DocumentP::partialTopologicalSort( return ret; } -std::vector DocumentP::topologicalSort(const std::vector& objects) const +std::vector +DocumentP::topologicalSort(const std::vector& objects) const { // topological sort algorithm described here: // https://de.wikipedia.org/wiki/Topologische_Sortierung#Algorithmus_f.C3.BCr_das_Topologische_Sortieren - vector < App::DocumentObject* > ret; + vector ret; ret.reserve(objects.size()); - map < App::DocumentObject*,int > countMap; + map countMap; for (auto objectIt : objects) { // We now support externally linked objects // if(!obj->isAttachedToDocument() || obj->getDocument()!=this) - if(!objectIt->isAttachedToDocument()) + if (!objectIt->isAttachedToDocument()) { continue; - //we need inlist with unique entries + } + // we need inlist with unique entries auto in = objectIt->getInList(); std::sort(in.begin(), in.end()); in.erase(std::unique(in.begin(), in.end()), in.end()); @@ -3105,33 +3410,38 @@ std::vector DocumentP::topologicalSort(const std::vector count)->bool { - return count.second == 0; - }); + auto rootObjeIt = find_if(countMap.begin(), + countMap.end(), + [](pair count) -> bool { + return count.second == 0; + }); - if (rootObjeIt == countMap.end()){ + if (rootObjeIt == countMap.end()) { cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << endl; return ret; } - while (rootObjeIt != countMap.end()){ + while (rootObjeIt != countMap.end()) { rootObjeIt->second = rootObjeIt->second - 1; - //we need outlist with unique entries + // we need outlist with unique entries auto out = rootObjeIt->first->getOutList(); std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); for (auto outListIt : out) { auto outListMapIt = countMap.find(outListIt); - if (outListMapIt != countMap.end()) + if (outListMapIt != countMap.end()) { outListMapIt->second = outListMapIt->second - 1; + } } ret.push_back(rootObjeIt->first); - rootObjeIt = find_if(countMap.begin(), countMap.end(), [](pair < App::DocumentObject*, int > count)->bool { - return count.second == 0; - }); + rootObjeIt = find_if(countMap.begin(), + countMap.end(), + [](pair count) -> bool { + return count.second == 0; + }); } return ret; @@ -3142,7 +3452,7 @@ std::vector Document::topologicalSort() const return d->topologicalSort(d->objectArray); } -const char * Document::getErrorDescription(const App::DocumentObject*Obj) const +const char* Document::getErrorDescription(const App::DocumentObject* Obj) const { return d->findRecomputeLog(Obj); } @@ -3152,41 +3462,43 @@ int Document::_recomputeFeature(DocumentObject* Feat) { FC_LOG("Recomputing " << Feat->getFullName()); - DocumentObjectExecReturn *returnCode = nullptr; + DocumentObjectExecReturn* returnCode = nullptr; try { returnCode = Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteNonOutput); if (returnCode == DocumentObject::StdReturn) { returnCode = Feat->recompute(); - if(returnCode == DocumentObject::StdReturn) - returnCode = Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOutput); + if (returnCode == DocumentObject::StdReturn) { + returnCode = + Feat->ExpressionEngine.execute(PropertyExpressionEngine::ExecuteOutput); + } } } - catch(Base::AbortException &e){ + catch (Base::AbortException& e) { e.ReportException(); FC_LOG("Failed to recompute " << Feat->getFullName() << ": " << e.what()); - d->addRecomputeLog("User abort",Feat); + d->addRecomputeLog("User abort", Feat); return -1; } catch (const Base::MemoryException& e) { FC_ERR("Memory exception in " << Feat->getFullName() << " thrown: " << e.what()); - d->addRecomputeLog("Out of memory exception",Feat); + d->addRecomputeLog("Out of memory exception", Feat); return 1; } - catch (Base::Exception &e) { + catch (Base::Exception& e) { e.ReportException(); FC_LOG("Failed to recompute " << Feat->getFullName() << ": " << e.what()); - d->addRecomputeLog(e.what(),Feat); + d->addRecomputeLog(e.what(), Feat); return 1; } - catch (std::exception &e) { + catch (std::exception& e) { FC_ERR("exception in " << Feat->getFullName() << " thrown: " << e.what()); - d->addRecomputeLog(e.what(),Feat); + d->addRecomputeLog(e.what(), Feat); return 1; } #ifndef FC_DEBUG catch (...) { FC_ERR("Unknown exception in " << Feat->getFullName() << " thrown"); - d->addRecomputeLog("Unknown exception!",Feat); + d->addRecomputeLog("Unknown exception!", Feat); return 1; } #endif @@ -3210,23 +3522,30 @@ bool Document::recomputeFeature(DocumentObject* Feat, bool recursive) // verify that the feature is (active) part of the document if (Feat->isAttachedToDocument()) { - if(recursive) { + if (recursive) { bool hasError = false; - recompute({Feat},true,&hasError); + recompute({Feat}, true, &hasError); return !hasError; - } else { + } + else { _recomputeFeature(Feat); signalRecomputedObject(*Feat); return Feat->isValid(); } - }else + } + else { return false; + } } -DocumentObject * Document::addObject(const char* sType, const char* pObjectName, - bool isNew, const char* viewType, bool isPartial) +DocumentObject* Document::addObject(const char* sType, + const char* pObjectName, + bool isNew, + const char* viewType, + bool isPartial) { - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; @@ -3234,8 +3553,9 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, } void* typeInstance = type.createInstance(); - if (!typeInstance) + if (!typeInstance) { return nullptr; + } App::DocumentObject* pcObject = static_cast(typeInstance); @@ -3244,18 +3564,21 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } // get Unique name string ObjectName; - if (pObjectName && pObjectName[0] != '\0') + if (pObjectName && pObjectName[0] != '\0') { ObjectName = getUniqueObjectName(pObjectName); - else + } + else { ObjectName = getUniqueObjectName(sType); + } d->activeObject = pcObject; @@ -3265,19 +3588,21 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, // generate object id and add to id map; pcObject->_Id = ++d->lastObjectId; d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); - // If we are restoring, don't set the Label object now; it will be restored later. This is to avoid potential duplicate - // label conflicts later. - if (!d->StatusBits.test(Restoring)) - pcObject->Label.setValue( ObjectName ); + // If we are restoring, don't set the Label object now; it will be restored later. This is to + // avoid potential duplicate label conflicts later. + if (!d->StatusBits.test(Restoring)) { + pcObject->Label.setValue(ObjectName); + } // Call the object-specific initialization if (!d->undoing && !d->rollback && isNew) { - pcObject->setupObject (); + pcObject->setupObject(); } // mark the object as new (i.e. set status bit 2) and send the signal @@ -3285,11 +3610,13 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, pcObject->setStatus(ObjectStatus::PartialObject, isPartial); - if (!viewType || viewType[0] == '\0') + if (!viewType || viewType[0] == '\0') { viewType = pcObject->getViewProviderNameOverride(); + } - if (viewType && viewType[0] != '\0') + if (viewType && viewType[0] != '\0') { pcObject->_pcViewProviderName = viewType; + } signalNewObject(*pcObject); @@ -3304,19 +3631,22 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, return pcObject; } -std::vector Document::addObjects(const char* sType, const std::vector& objectNames, bool isNew) +std::vector +Document::addObjects(const char* sType, const std::vector& objectNames, bool isNew) { - Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + Base::Type type = + Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; throw Base::TypeError(str.str()); } - std::vector objects; + std::vector objects; objects.resize(objectNames.size()); - std::generate(objects.begin(), objects.end(), - [&]{ return static_cast(type.createInstance()); }); + std::generate(objects.begin(), objects.end(), [&] { + return static_cast(type.createInstance()); + }); // the type instance could be a null pointer, it is enough to check the first element if (!objects.empty() && !objects[0]) { objects.clear(); @@ -3326,7 +3656,7 @@ std::vector Document::addObjects(const char* sType, const std: // get all existing object names std::vector reservedNames; reservedNames.reserve(d->objectMap.size()); - for (const auto & pos : d->objectMap) { + for (const auto& pos : d->objectMap) { reservedNames.push_back(pos.first); } @@ -3338,7 +3668,7 @@ std::vector Document::addObjects(const char* sType, const std: // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); + _checkTransaction(nullptr, nullptr, __LINE__); if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); } @@ -3346,16 +3676,17 @@ std::vector Document::addObjects(const char* sType, const std: // get unique name std::string ObjectName = objectNames[index]; - if (ObjectName.empty()) + if (ObjectName.empty()) { ObjectName = sType; + } ObjectName = Base::Tools::getIdentifier(ObjectName); if (d->objectMap.find(ObjectName) != d->objectMap.end()) { // remove also trailing digits from clean name which is to avoid to create lengthy names // like 'Box001001' if (!testStatus(KeepTrailingDigits)) { std::string::size_type index = ObjectName.find_last_not_of("0123456789"); - if (index+1 < ObjectName.size()) { - ObjectName = ObjectName.substr(0,index+1); + if (index + 1 < ObjectName.size()) { + ObjectName = ObjectName.substr(0, index + 1); } } @@ -3369,7 +3700,8 @@ std::vector Document::addObjects(const char* sType, const std: // generate object id and add to id map; pcObject->_Id = ++d->lastObjectId; d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); @@ -3384,7 +3716,7 @@ std::vector Document::addObjects(const char* sType, const std: // mark the object as new (i.e. set status bit 2) and send the signal pcObject->setStatus(ObjectStatus::New, true); - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; signalNewObject(*pcObject); @@ -3414,36 +3746,42 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName) // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } // get unique name string ObjectName; - if (pObjectName && pObjectName[0] != '\0') + if (pObjectName && pObjectName[0] != '\0') { ObjectName = getUniqueObjectName(pObjectName); - else + } + else { ObjectName = getUniqueObjectName(pcObject->getTypeId().getName()); + } d->activeObject = pcObject; // insert in the name map d->objectMap[ObjectName] = pcObject; // generate object id and add to id map; - if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + if (!pcObject->_Id) { + pcObject->_Id = ++d->lastObjectId; + } d->objectIdMap[pcObject->_Id] = pcObject; - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector d->objectArray.push_back(pcObject); - pcObject->Label.setValue( ObjectName ); + pcObject->Label.setValue(ObjectName); // mark the object as new (i.e. set status bit 2) and send the signal pcObject->setStatus(ObjectStatus::New, true); - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; signalNewObject(*pcObject); @@ -3461,21 +3799,25 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName) std::string ObjectName = getUniqueObjectName(pObjectName); d->objectMap[ObjectName] = pcObject; // generate object id and add to id map; - if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + if (!pcObject->_Id) { + pcObject->_Id = ++d->lastObjectId; + } d->objectIdMap[pcObject->_Id] = pcObject; d->objectArray.push_back(pcObject); - // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) + // cache the pointer to the name string in the Object (for performance of + // DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // do no transactions if we do a rollback! if (!d->rollback) { // Undo stuff - _checkTransaction(nullptr,nullptr,__LINE__); - if (d->activeUndoTransaction) + _checkTransaction(nullptr, nullptr, __LINE__); + if (d->activeUndoTransaction) { d->activeUndoTransaction->addObjectDel(pcObject); + } } - const char *viewType = pcObject->getViewProviderNameOverride(); + const char* viewType = pcObject->getViewProviderNameOverride(); pcObject->_pcViewProviderName = viewType ? viewType : ""; // send the signal @@ -3496,8 +3838,9 @@ void Document::removeObject(const char* sName) auto pos = d->objectMap.find(sName); // name not found? - if (pos == d->objectMap.end()) + if (pos == d->objectMap.end()) { return; + } if (pos->second->testStatus(ObjectStatus::PendingRecompute)) { // TODO: shall we allow removal if there is active undo transaction? @@ -3508,10 +3851,11 @@ void Document::removeObject(const char* sName) TransactionLocker tlock; - _checkTransaction(pos->second,nullptr,__LINE__); + _checkTransaction(pos->second, nullptr, __LINE__); - if (d->activeObject == pos->second) + if (d->activeObject == pos->second) { d->activeObject = nullptr; + } // Mark the object as about to be deleted pos->second->setStatus(ObjectStatus::Remove, true); @@ -3534,20 +3878,22 @@ void Document::removeObject(const char* sName) #ifdef USE_OLD_DAG if (!d->vertexMap.empty()) { // recompute of document is running - for (std::map::iterator it = d->vertexMap.begin(); it != d->vertexMap.end(); ++it) { + for (std::map::iterator it = d->vertexMap.begin(); + it != d->vertexMap.end(); + ++it) { if (it->second == pos->second) { - it->second = 0; // just nullify the pointer + it->second = 0; // just nullify the pointer break; } } } -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG // Before deleting we must nullify all dependent objects breakDependency(pos->second, true); - //and remove the tip if needed - if (Tip.getValue() && strcmp(Tip.getValue()->getNameInDocument(), sName)==0) { + // and remove the tip if needed + if (Tip.getValue() && strcmp(Tip.getValue()->getNameInDocument(), sName) == 0) { Tip.setValue(nullptr); TipName.setValue(""); } @@ -3573,7 +3919,9 @@ void Document::removeObject(const char* sName) } } - for (std::vector::iterator obj = d->objectArray.begin(); obj != d->objectArray.end(); ++obj) { + for (std::vector::iterator obj = d->objectArray.begin(); + obj != d->objectArray.end(); + ++obj) { if (*obj == pos->second) { d->objectArray.erase(obj); break; @@ -3598,26 +3946,30 @@ void Document::_removeObject(DocumentObject* pcObject) TransactionLocker tlock; // TODO Refactoring: share code with Document::removeObject() (2015-09-01, Fat-Zer) - _checkTransaction(pcObject,nullptr,__LINE__); + _checkTransaction(pcObject, nullptr, __LINE__); auto pos = d->objectMap.find(pcObject->getNameInDocument()); - if(!d->rollback && d->activeUndoTransaction && pos->second->hasChildElement()) { + if (!d->rollback && d->activeUndoTransaction && pos->second->hasChildElement()) { // Preserve link group children global visibility. See comments in // removeObject() for more details. - for(auto &sub : pos->second->getSubObjects()) { - if(sub.empty()) + for (auto& sub : pos->second->getSubObjects()) { + if (sub.empty()) { continue; - if(sub[sub.size()-1]!='.') + } + if (sub[sub.size() - 1] != '.') { sub += '.'; + } auto sobj = pos->second->getSubObject(sub.c_str()); - if(sobj && sobj->getDocument()==this && !sobj->Visibility.getValue()) - d->activeUndoTransaction->addObjectChange(sobj,&sobj->Visibility); + if (sobj && sobj->getDocument() == this && !sobj->Visibility.getValue()) { + d->activeUndoTransaction->addObjectChange(sobj, &sobj->Visibility); + } } } - if (d->activeObject == pcObject) + if (d->activeObject == pcObject) { d->activeObject = nullptr; + } // Mark the object as about to be removed pcObject->setStatus(ObjectStatus::Remove, true); @@ -3627,7 +3979,7 @@ void Document::_removeObject(DocumentObject* pcObject) signalDeletedObject(*pcObject); // TODO Check me if it's needed (2015-09-01, Fat-Zer) - //remove the tip if needed + // remove the tip if needed if (Tip.getValue() == pcObject) { Tip.setValue(nullptr); TipName.setValue(""); @@ -3647,11 +3999,13 @@ void Document::_removeObject(DocumentObject* pcObject) breakDependency(pcObject, true); // remove from map - pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side + pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side d->objectIdMap.erase(pcObject->_Id); d->objectMap.erase(pos); - for (std::vector::iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { + for (std::vector::iterator it = d->objectArray.begin(); + it != d->objectArray.end(); + ++it) { if (*it == pcObject) { d->objectArray.erase(it); break; @@ -3668,33 +4022,36 @@ void Document::_removeObject(DocumentObject* pcObject) void Document::breakDependency(DocumentObject* pcObject, bool clear) { // Nullify all dependent objects - PropertyLinkBase::breakLinks(pcObject,d->objectArray,clear); + PropertyLinkBase::breakLinks(pcObject, d->objectArray, clear); } -std::vector Document::copyObject( - const std::vector &objs, bool recursive, bool returnAll) +std::vector +Document::copyObject(const std::vector& objs, bool recursive, bool returnAll) { std::vector deps; - if(!recursive) + if (!recursive) { deps = objs; - else - deps = getDependencyList(objs,DepNoXLinked|DepSort); + } + else { + deps = getDependencyList(objs, DepNoXLinked | DepSort); + } if (!testStatus(TempDoc) && !isSaved() && PropertyXLink::hasXLink(deps)) { throw Base::RuntimeError( - "Document must be saved at least once before link to external objects"); + "Document must be saved at least once before link to external objects"); } MergeDocuments md(this); // if not copying recursively then suppress possible warnings md.setVerbose(recursive); - unsigned int memsize=1000; // ~ for the meta-information - for (auto it : deps) + unsigned int memsize = 1000; // ~ for the meta-information + for (auto it : deps) { memsize += it->getMemSize(); + } // if less than ~10 MB - bool use_buffer=(memsize < 0xA00000); + bool use_buffer = (memsize < 0xA00000); QByteArray res; try { res.reserve(memsize); @@ -3713,7 +4070,8 @@ std::vector Document::copyObject( std::istream istr(nullptr); istr.rdbuf(&ibuf); imported = md.importObjects(istr); - } else { + } + else { static Base::FileInfo fi(App::Application::getTempFileName()); Base::ofstream ostr(fi, std::ios::out | std::ios::binary); exportObjects(deps, ostr); @@ -3723,42 +4081,45 @@ std::vector Document::copyObject( imported = md.importObjects(istr); } - if (returnAll || imported.size()!=deps.size()) + if (returnAll || imported.size() != deps.size()) { return imported; + } - std::unordered_map indices; - size_t i=0; - for(auto o : deps) + std::unordered_map indices; + size_t i = 0; + for (auto o : deps) { indices[o] = i++; + } std::vector result; result.reserve(objs.size()); - for(auto o : objs) + for (auto o : objs) { result.push_back(imported[indices[o]]); + } return result; } std::vector -Document::importLinks(const std::vector &objArray) +Document::importLinks(const std::vector& objArray) { std::set links; - getLinksTo(links,nullptr,GetLinkExternal,0,objArray); + getLinksTo(links, nullptr, GetLinkExternal, 0, objArray); std::vector objs; - objs.insert(objs.end(),links.begin(),links.end()); + objs.insert(objs.end(), links.begin(), links.end()); objs = App::Document::getDependencyList(objs); - if(objs.empty()) { + if (objs.empty()) { FC_ERR("nothing to import"); return objs; } - for(auto it=objs.begin();it!=objs.end();) { + for (auto it = objs.begin(); it != objs.end();) { auto obj = *it; - if(obj->getDocument() == this) { + if (obj->getDocument() == this) { it = objs.erase(it); continue; } ++it; - if(obj->testStatus(App::PartialObject)) { + if (obj->testStatus(App::PartialObject)) { throw Base::RuntimeError( "Cannot import partial loaded object. Please reload the current document"); } @@ -3778,20 +4139,21 @@ Document::importLinks(const std::vector &objArray) str.close(); fi.deleteFile(); - const auto &nameMap = mimeView.getNameMap(); + const auto& nameMap = mimeView.getNameMap(); // First, find all link type properties that needs to be changed - std::map > propMap; + std::map> propMap; std::vector propList; - for(auto obj : links) { + for (auto obj : links) { propList.clear(); obj->getPropertyList(propList); - for(auto prop : propList) { + for (auto prop : propList) { auto linkProp = Base::freecad_dynamic_cast(prop); - if(linkProp && !prop->testStatus(Property::Immutable) && !obj->isReadOnly(prop)) { + if (linkProp && !prop->testStatus(Property::Immutable) && !obj->isReadOnly(prop)) { auto copy = linkProp->CopyOnImportExternal(nameMap); - if(copy) + if (copy) { propMap[linkProp].reset(copy); + } } } } @@ -3801,23 +4163,26 @@ Document::importLinks(const std::vector &objArray) // properties, e.g. a link sub referring to some sub object of an xlink, If // that sub object is imported with a different name, and xlink is changed // before this link sub, it will break. - for(auto &v : propMap) + for (auto& v : propMap) { v.first->Paste(*v.second); + } return objs; } DocumentObject* Document::moveObject(DocumentObject* obj, bool recursive) { - if(!obj) + if (!obj) { return nullptr; + } Document* that = obj->getDocument(); - if (that == this) - return nullptr; // nothing todo + if (that == this) { + return nullptr; // nothing todo + } // True object move without copy is only safe when undo is off on both // documents. - if(!recursive && !d->iUndoMode && !that->d->iUndoMode && !that->d->rollback) { + if (!recursive && !d->iUndoMode && !that->d->iUndoMode && !that->d->rollback) { // all object of the other document that refer to this object must be nullified that->breakDependency(obj, false); std::string objname = getUniqueObjectName(obj->getNameInDocument()); @@ -3828,83 +4193,95 @@ DocumentObject* Document::moveObject(DocumentObject* obj, bool recursive) } std::vector deps; - if(recursive) - deps = getDependencyList({obj},DepNoXLinked|DepSort); - else + if (recursive) { + deps = getDependencyList({obj}, DepNoXLinked | DepSort); + } + else { deps.push_back(obj); + } - auto objs = copyObject(deps,false); - if(objs.empty()) + auto objs = copyObject(deps, false); + if (objs.empty()) { return nullptr; + } // Some object may delete its children if deleted, so we collect the IDs // or all depending objects for safety reason. std::vector ids; ids.reserve(deps.size()); - for(auto o : deps) + for (auto o : deps) { ids.push_back(o->getID()); + } // We only remove object if it is the moving object or it has no // depending objects, i.e. an empty inList, which is why we need to // iterate the depending list backwards. - for(auto iter=ids.rbegin();iter!=ids.rend();++iter) { + for (auto iter = ids.rbegin(); iter != ids.rend(); ++iter) { auto o = that->getObjectByID(*iter); - if(!o) continue; - if(iter==ids.rbegin() - || o->getInList().empty()) + if (!o) { + continue; + } + if (iter == ids.rbegin() || o->getInList().empty()) { that->removeObject(o->getNameInDocument()); + } } return objs.back(); } -DocumentObject * Document::getActiveObject() const +DocumentObject* Document::getActiveObject() const { return d->activeObject; } -DocumentObject * Document::getObject(const char *Name) const +DocumentObject* Document::getObject(const char* Name) const { auto pos = d->objectMap.find(Name); - if (pos != d->objectMap.end()) + if (pos != d->objectMap.end()) { return pos->second; - else + } + else { return nullptr; + } } -DocumentObject * Document::getObjectByID(long id) const +DocumentObject* Document::getObjectByID(long id) const { auto it = d->objectIdMap.find(id); - if(it!=d->objectIdMap.end()) + if (it != d->objectIdMap.end()) { return it->second; + } return nullptr; } // Note: This method is only used in Tree.cpp slotChangeObject(), see explanation there -bool Document::isIn(const DocumentObject *pFeat) const +bool Document::isIn(const DocumentObject* pFeat) const { - for (const auto & pos : d->objectMap) { - if (pos.second == pFeat) + for (const auto& pos : d->objectMap) { + if (pos.second == pFeat) { return true; + } } return false; } -const char * Document::getObjectName(DocumentObject *pFeat) const +const char* Document::getObjectName(DocumentObject* pFeat) const { - for (const auto & pos : d->objectMap) { - if (pos.second == pFeat) + for (const auto& pos : d->objectMap) { + if (pos.second == pFeat) { return pos.first.c_str(); + } } return nullptr; } -std::string Document::getUniqueObjectName(const char *Name) const +std::string Document::getUniqueObjectName(const char* Name) const { - if (!Name || *Name == '\0') + if (!Name || *Name == '\0') { return {}; + } std::string CleanName = Base::Tools::getIdentifier(Name); // name in use? @@ -3919,21 +4296,21 @@ std::string Document::getUniqueObjectName(const char *Name) const // like 'Box001001' if (!testStatus(KeepTrailingDigits)) { std::string::size_type index = CleanName.find_last_not_of("0123456789"); - if (index+1 < CleanName.size()) { - CleanName = CleanName.substr(0,index+1); + if (index + 1 < CleanName.size()) { + CleanName = CleanName.substr(0, index + 1); } } std::vector names; names.reserve(d->objectMap.size()); - for (pos = d->objectMap.begin();pos != d->objectMap.end();++pos) { + for (pos = d->objectMap.begin(); pos != d->objectMap.end(); ++pos) { names.push_back(pos->first); } return Base::Tools::getUniqueName(CleanName, names, 3); } } -std::string Document::getStandardObjectName(const char *Name, int d) const +std::string Document::getStandardObjectName(const char* Name, int d) const { std::vector mm = getObjects(); std::vector labels; @@ -3951,7 +4328,7 @@ std::vector Document::getDependingObjects() const return getDependencyList(d->objectArray); } -const std::vector &Document::getObjects() const +const std::vector& Document::getObjects() const { return d->objectArray; } @@ -3961,33 +4338,40 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId { std::vector Objects; for (auto it : d->objectArray) { - if (it->getTypeId().isDerivedFrom(typeId)) + if (it->getTypeId().isDerivedFrom(typeId)) { Objects.push_back(it); + } } return Objects; } -std::vector< DocumentObject* > Document::getObjectsWithExtension(const Base::Type& typeId, bool derived) const { +std::vector Document::getObjectsWithExtension(const Base::Type& typeId, + bool derived) const +{ std::vector Objects; for (auto it : d->objectArray) { - if (it->hasExtension(typeId, derived)) + if (it->hasExtension(typeId, derived)) { Objects.push_back(it); + } } return Objects; } -std::vector Document::findObjects(const Base::Type& typeId, const char* objname, const char* label) const +std::vector +Document::findObjects(const Base::Type& typeId, const char* objname, const char* label) const { boost::cmatch what; boost::regex rx_name, rx_label; - if (objname) + if (objname) { rx_name.set_expression(objname); + } - if (label) + if (label) { rx_label.set_expression(label); + } std::vector Objects; DocumentObject* found = nullptr; @@ -3995,14 +4379,17 @@ std::vector Document::findObjects(const Base::Type& typeId, con if (it->getTypeId().isDerivedFrom(typeId)) { found = it; - if (!rx_name.empty() && !boost::regex_search(it->getNameInDocument(), what, rx_name)) + if (!rx_name.empty() && !boost::regex_search(it->getNameInDocument(), what, rx_name)) { found = nullptr; + } - if (!rx_label.empty() && !boost::regex_search(it->Label.getValue(), what, rx_label)) + if (!rx_label.empty() && !boost::regex_search(it->Label.getValue(), what, rx_label)) { found = nullptr; + } - if (found) + if (found) { Objects.push_back(found); + } } } return Objects; @@ -4010,27 +4397,29 @@ std::vector Document::findObjects(const Base::Type& typeId, con int Document::countObjectsOfType(const Base::Type& typeId) const { - int ct=0; - for (const auto & it : d->objectMap) { - if (it.second->getTypeId().isDerivedFrom(typeId)) + int ct = 0; + for (const auto& it : d->objectMap) { + if (it.second->getTypeId().isDerivedFrom(typeId)) { ct++; + } } return ct; } -PyObject * Document::getPyObject() +PyObject* Document::getPyObject() { return Py::new_reference_to(d->DocumentPythonObject); } std::vector Document::getRootObjects() const { - std::vector < App::DocumentObject* > ret; + std::vector ret; for (auto objectIt : d->objectArray) { - if (objectIt->getInList().empty()) + if (objectIt->getInList().empty()) { ret.push_back(objectIt); + } } return ret; @@ -4046,9 +4435,9 @@ std::vector Document::getRootObjectsIgnoreLinks() const if (!noParents) { // App::Document getRootObjects returns the root objects of the dependency graph. - // So if an object is referenced by a App::Link, it will not be returned by that function. - // So here, as we want the tree-root level objects, - // we check if all the parents are links. In which case its still a root object. + // So if an object is referenced by a App::Link, it will not be returned by that + // function. So here, as we want the tree-root level objects, we check if all the + // parents are links. In which case its still a root object. noParents = std::all_of(list.cbegin(), list.cend(), [](App::DocumentObject* obj) { return obj->isDerivedFrom(); }); @@ -4062,14 +4451,16 @@ std::vector Document::getRootObjectsIgnoreLinks() const return ret; } -void DocumentP::findAllPathsAt(const std::vector &all_nodes, size_t id, - std::vector &all_paths, Path tmp) +void DocumentP::findAllPathsAt(const std::vector& all_nodes, + size_t id, + std::vector& all_paths, + Path tmp) { if (std::find(tmp.begin(), tmp.end(), id) != tmp.end()) { Path tmp2(tmp); tmp2.push_back(id); all_paths.push_back(tmp2); - return; // a cycle + return; // a cycle } tmp.push_back(id); @@ -4078,22 +4469,22 @@ void DocumentP::findAllPathsAt(const std::vector &all_nodes, size_t id, return; } - for (size_t i=0; i < all_nodes[id].size(); i++) { + for (size_t i = 0; i < all_nodes[id].size(); i++) { Path tmp2(tmp); findAllPathsAt(all_nodes, all_nodes[id][i], all_paths, tmp2); } } -std::vector > +std::vector> Document::getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const { std::map indexMap; - for (size_t i=0; iobjectArray.size(); ++i) { + for (size_t i = 0; i < d->objectArray.size(); ++i) { indexMap[d->objectArray[i]] = i; } - std::vector all_nodes(d->objectArray.size()); - for (size_t i=0; iobjectArray.size(); ++i) { + std::vector all_nodes(d->objectArray.size()); + for (size_t i = 0; i < d->objectArray.size(); ++i) { DocumentObject* obj = d->objectArray[i]; std::vector outList = obj->getOutList(); for (auto it : outList) { @@ -4101,9 +4492,10 @@ Document::getPathsByOutList(const App::DocumentObject* from, const App::Document } } - std::vector > array; - if (from == to) + std::vector> array; + if (from == to) { return array; + } size_t index_from = indexMap[from]; size_t index_to = indexMap[to]; @@ -4133,15 +4525,16 @@ Document::getPathsByOutList(const App::DocumentObject* from, const App::Document bool Document::mustExecute() const { - if(PropertyXLink::hasXLink(this)) { + if (PropertyXLink::hasXLink(this)) { bool touched = false; - _buildDependencyList(d->objectArray,false,nullptr,nullptr,nullptr,&touched); + _buildDependencyList(d->objectArray, false, nullptr, nullptr, nullptr, &touched); return touched; } for (auto It : d->objectArray) { - if (It->isTouched() || It->mustExecute()==1) + if (It->isTouched() || It->mustExecute() == 1) { return true; + } } return false; } diff --git a/src/App/Document.h b/src/App/Document.h index c49434ff7b59..36a878ee1043 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -37,33 +37,32 @@ #include #include -namespace Base { - class Writer; -} - -namespace App +namespace Base { - class TransactionalObject; - class DocumentObject; - class DocumentObjectExecReturn; - class Document; - class DocumentPy; // the python document class - class Application; - class Transaction; - class StringHasher; - using StringHasherRef = Base::Reference; +class Writer; } namespace App { +class TransactionalObject; +class DocumentObject; +class DocumentObjectExecReturn; +class Document; +class DocumentPy; +class Application; +class Transaction; +class StringHasher; +using StringHasherRef = Base::Reference; /// The document class -class AppExport Document : public App::PropertyContainer +class AppExport Document: public App::PropertyContainer { PROPERTY_HEADER_WITH_OVERRIDE(App::Document); public: - enum Status { + // clang-format off + enum Status + { SkipRecompute = 0, KeepTrailingDigits = 1, Closable = 2, @@ -72,14 +71,16 @@ class AppExport Document : public App::PropertyContainer PartialRestore = 5, Importing = 6, PartialDoc = 7, - AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set - TempDoc = 9, // Mark as temporary document without prompt for save + AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set + TempDoc = 9, // Mark as temporary document without prompt for save RestoreError = 10, - LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed - IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed - RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purposes + LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed + IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed + RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purposes }; + // clang-format on + // NOLINTBEGIN /** @name Properties */ //@{ /// holds the long name of the document (utf-8 coded) @@ -124,67 +125,66 @@ class AppExport Document : public App::PropertyContainer /** @name Signals of the document */ //@{ + // clang-format off /// signal before changing an doc property - boost::signals2::signal signalBeforeChange; + boost::signals2::signal signalBeforeChange; /// signal on changed doc property - boost::signals2::signal signalChanged; + boost::signals2::signal signalChanged; /// signal on new Object - boost::signals2::signal signalNewObject; - //boost::signals2::signal m_sig; + boost::signals2::signal signalNewObject; /// signal on deleted Object - boost::signals2::signal signalDeletedObject; + boost::signals2::signal signalDeletedObject; /// signal before changing an Object - boost::signals2::signal signalBeforeChangeObject; + boost::signals2::signal signalBeforeChangeObject; /// signal on changed Object - boost::signals2::signal signalChangedObject; + boost::signals2::signal signalChangedObject; /// signal on manually called DocumentObject::touch() - boost::signals2::signal signalTouchedObject; + boost::signals2::signal signalTouchedObject; /// signal on relabeled Object - boost::signals2::signal signalRelabelObject; + boost::signals2::signal signalRelabelObject; /// signal on activated Object - boost::signals2::signal signalActivatedObject; + boost::signals2::signal signalActivatedObject; /// signal on created object - boost::signals2::signal signalTransactionAppend; + boost::signals2::signal signalTransactionAppend; /// signal on removed object - boost::signals2::signal signalTransactionRemove; + boost::signals2::signal signalTransactionRemove; /// signal on undo - boost::signals2::signal signalUndo; + boost::signals2::signal signalUndo; /// signal on redo - boost::signals2::signal signalRedo; + boost::signals2::signal signalRedo; /** signal on load/save document * this signal is given when the document gets streamed. * you can use this hook to write additional information in * the file (like the Gui::Document does). */ - boost::signals2::signal signalSaveDocument; - boost::signals2::signal signalRestoreDocument; - boost::signals2::signal&, - Base::Writer &)> signalExportObjects; - boost::signals2::signal&, - Base::Writer &)> signalExportViewObjects; - boost::signals2::signal&, - Base::XMLReader&)> signalImportObjects; - boost::signals2::signal&, Base::Reader&, - const std::map&)> signalImportViewObjects; - boost::signals2::signal&)> signalFinishImportObjects; - //signal starting a save action to a file - boost::signals2::signal signalStartSave; - //signal finishing a save action to a file - boost::signals2::signal signalFinishSave; - boost::signals2::signal signalBeforeRecompute; - boost::signals2::signal&)> signalRecomputed; - boost::signals2::signal signalRecomputedObject; - //signal a new opened transaction - boost::signals2::signal signalOpenTransaction; + boost::signals2::signal signalSaveDocument; + boost::signals2::signal signalRestoreDocument; + boost::signals2::signal&, Base::Writer&)> signalExportObjects; + boost::signals2::signal&, Base::Writer&)> signalExportViewObjects; + boost::signals2::signal&, Base::XMLReader&)> signalImportObjects; + boost::signals2::signal&, Base::Reader&, + const std::map&)> signalImportViewObjects; + boost::signals2::signal&)> signalFinishImportObjects; + // signal starting a save action to a file + boost::signals2::signal signalStartSave; + // signal finishing a save action to a file + boost::signals2::signal signalFinishSave; + boost::signals2::signal signalBeforeRecompute; + boost::signals2::signal&)> signalRecomputed; + boost::signals2::signal signalRecomputedObject; + // signal a new opened transaction + boost::signals2::signal signalOpenTransaction; // signal a committed transaction - boost::signals2::signal signalCommitTransaction; + boost::signals2::signal signalCommitTransaction; // signal an aborted transaction - boost::signals2::signal signalAbortTransaction; - boost::signals2::signal&)> signalSkipRecompute; - boost::signals2::signal signalFinishRestoreObject; - boost::signals2::signal signalChangePropertyEditor; + boost::signals2::signal signalAbortTransaction; + boost::signals2::signal&)> signalSkipRecompute; + boost::signals2::signal signalFinishRestoreObject; + boost::signals2::signal signalChangePropertyEditor; + boost::signals2::signal signalLinkXsetValue; + // clang-format on //@} - boost::signals2::signal signalLinkXsetValue; + // NOLINTEND void clearDocument(); @@ -192,21 +192,23 @@ class AppExport Document : public App::PropertyContainer /** @name File handling of the document */ //@{ /// Save the Document under a new Name - //void saveAs (const char* Name); + // void saveAs (const char* Name); /// Save the document to the file in Property Path - bool save (); + bool save(); bool saveAs(const char* file); bool saveCopy(const char* file) const; /// Restore the document from the file in Property Path - void restore (const char *filename=nullptr, - bool delaySignal=false, const std::vector &objNames={}); - bool afterRestore(bool checkPartial=false); - bool afterRestore(const std::vector &, bool checkPartial=false); - enum ExportStatus { + void restore(const char* filename = nullptr, + bool delaySignal = false, + const std::vector& objNames = {}); + bool afterRestore(bool checkPartial = false); + bool afterRestore(const std::vector&, bool checkPartial = false); + enum ExportStatus + { NotExporting, Exporting, }; - ExportStatus isExporting(const App::DocumentObject *obj) const; + ExportStatus isExporting(const App::DocumentObject* obj) const; void exportObjects(const std::vector&, std::ostream&); void exportGraphviz(std::ostream&) const; std::vector importObjects(Base::XMLReader& reader); @@ -222,10 +224,10 @@ class AppExport Document : public App::PropertyContainer * * @return the list of imported objects */ - std::vector importLinks( - const std::vector &objs = {}); + std::vector + importLinks(const std::vector& objs = {}); /// Opens the document from its file name - //void open (void); + // void open (void); /// Is the document already saved to a file? bool isSaved() const; /// Get the document name @@ -241,31 +243,39 @@ class AppExport Document : public App::PropertyContainer const char* getFileName() const; //@} - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - /// returns the complete document memory consumption, including all managed DocObjects and Undo Redo. - unsigned int getMemSize () const override; + /// returns the complete document memory consumption, including all managed DocObjects and Undo + /// Redo. + unsigned int getMemSize() const override; /** @name Object handling */ //@{ /** Add a feature of sType with sName (ASCII) to this document and set it active. * Unicode names are set through the Label property. * @param sType the type of created object - * @param pObjectName if nonNULL use that name otherwise generate a new unique name based on the \a sType - * @param isNew if false don't call the \c DocumentObject::setupObject() callback (default is true) + * @param pObjectName if nonNULL use that name otherwise generate a new unique name based on the + * \a sType + * @param isNew if false don't call the \c DocumentObject::setupObject() callback (default + * is true) * @param viewType override object's view provider name * @param isPartial indicate if this object is meant to be partially loaded */ - DocumentObject *addObject(const char* sType, const char* pObjectName=nullptr, - bool isNew=true, const char *viewType=nullptr, bool isPartial=false); + DocumentObject* addObject(const char* sType, + const char* pObjectName = nullptr, + bool isNew = true, + const char* viewType = nullptr, + bool isPartial = false); /** Add an array of features of the given types and names. * Unicode names are set through the Label property. * @param sType The type of created object * @param objectNames A list of object names - * @param isNew If false don't call the \c DocumentObject::setupObject() callback (default is true) + * @param isNew If false don't call the \c DocumentObject::setupObject() callback (default + * is true) */ - std::vectoraddObjects(const char* sType, const std::vector& objectNames, bool isNew=true); + std::vector + addObjects(const char* sType, const std::vector& objectNames, bool isNew = true); /// Remove a feature out of the document void removeObject(const char* sName); /** Add an existing feature with sName (ASCII) to this document and set it active. @@ -275,7 +285,7 @@ class AppExport Document : public App::PropertyContainer * \note The passed feature must not yet be added to a document, otherwise an exception * is raised. */ - void addObject(DocumentObject*, const char* pObjectName=nullptr); + void addObject(DocumentObject*, const char* pObjectName = nullptr); /** Copy objects from another document to this document @@ -289,40 +299,44 @@ class AppExport Document : public App::PropertyContainer * * @return Returns the list of objects copied. */ - std::vector copyObject( - const std::vector &objs, - bool recursive=false, bool returnAll=false); + std::vector copyObject(const std::vector& objs, + bool recursive = false, + bool returnAll = false); /** Move an object from another document to this document * If \a recursive is true then all objects this object depends on * are moved as well. By default \a recursive is false. * Returns the moved object itself or 0 if the object is already part of this * document.. */ - DocumentObject* moveObject(DocumentObject* obj, bool recursive=false); + DocumentObject* moveObject(DocumentObject* obj, bool recursive = false); /// Returns the active Object of this document - DocumentObject *getActiveObject() const; + DocumentObject* getActiveObject() const; /// Returns a Object of this document - DocumentObject *getObject(const char *Name) const; + DocumentObject* getObject(const char* Name) const; /// Returns a Object of this document by its id - DocumentObject *getObjectByID(long id) const; + DocumentObject* getObjectByID(long id) const; /// Returns true if the DocumentObject is contained in this document - bool isIn(const DocumentObject *pFeat) const; + bool isIn(const DocumentObject* pFeat) const; /// Returns a Name of an Object or 0 - const char *getObjectName(DocumentObject *pFeat) const; + const char* getObjectName(DocumentObject* pFeat) const; /// Returns a Name of an Object or 0 - std::string getUniqueObjectName(const char *Name) const; + std::string getUniqueObjectName(const char* Name) const; /// Returns a name of the form prefix_number. d specifies the number of digits. - std::string getStandardObjectName(const char *Name, int d) const; + std::string getStandardObjectName(const char* Name, int d) const; /// Returns a list of document's objects including the dependencies std::vector getDependingObjects() const; /// Returns a list of all Objects - const std::vector &getObjects() const; + const std::vector& getObjects() const; std::vector getObjectsOfType(const Base::Type& typeId) const; - /// Returns all object with given extensions. If derived=true also all objects with extensions derived from the given one - std::vector getObjectsWithExtension(const Base::Type& typeId, bool derived = true) const; - std::vector findObjects(const Base::Type& typeId, const char* objname, const char* label) const; + /// Returns all object with given extensions. If derived=true also all objects with extensions + /// derived from the given one + std::vector getObjectsWithExtension(const Base::Type& typeId, + bool derived = true) const; + std::vector + findObjects(const Base::Type& typeId, const char* objname, const char* label) const; /// Returns an array with the correct types already. - template inline std::vector getObjectsOfType() const; + template + inline std::vector getObjectsOfType() const; int countObjectsOfType(const Base::Type& typeId) const; /// get the number of objects in the document int countObjects() const; @@ -338,7 +352,7 @@ class AppExport Document : public App::PropertyContainer /// check if there is any object must execute in this document bool mustExecute() const; /// returns all touched objects - std::vector getTouched() const; + std::vector getTouched() const; /// set the document to be closable, this is on by default. void setClosable(bool); /// check whether the document can be closed @@ -348,10 +362,12 @@ class AppExport Document : public App::PropertyContainer * @param objs: specify a sub set of objects to recompute. If empty, then * all object in this document is checked for recompute */ - int recompute(const std::vector &objs={}, - bool force=false,bool *hasError=nullptr, int options=0); + int recompute(const std::vector& objs = {}, + bool force = false, + bool* hasError = nullptr, + int options = 0); /// Recompute only one feature - bool recomputeFeature(DocumentObject* Feat,bool recursive=false); + bool recomputeFeature(DocumentObject* Feat, bool recursive = false); /// get the text of the error of a specified object const char* getErrorDescription(const App::DocumentObject*) const; /// return the status bits @@ -392,9 +408,9 @@ class AppExport Document : public App::PropertyContainer * to setup a potential transaction which will only be created if there is * actual changes. */ - void openTransaction(const char* name=nullptr); + void openTransaction(const char* name = nullptr); /// Rename the current transaction if the id matches - void renameTransaction(const char *name, int id); + void renameTransaction(const char* name, int id); /// Commit the Command transaction. Do nothing If there is no Command transaction open. void commitTransaction(); /// Abort the actually running transaction. @@ -402,49 +418,51 @@ class AppExport Document : public App::PropertyContainer /// Check if a transaction is open bool hasPendingTransaction() const; /// Return the undo/redo transaction ID starting from the back - int getTransactionID(bool undo, unsigned pos=0) const; + int getTransactionID(bool undo, unsigned pos = 0) const; /// Check if a transaction is open and its list is empty. /// If no transaction is open true is returned. bool isTransactionEmpty() const; /// Set the Undo limit in Byte! - void setUndoLimit(unsigned int UndoMemSize=0); + void setUndoLimit(unsigned int UndoMemSize = 0); /// Returns the actual memory consumption of the Undo redo stuff. - unsigned int getUndoMemSize () const; + unsigned int getUndoMemSize() const; /// Set the Undo limit as stack size - void setMaxUndoStackSize(unsigned int UndoMaxStackSize=20); + void setMaxUndoStackSize(unsigned int UndoMaxStackSize = 20); // NOLINT /// Set the Undo limit as stack size - unsigned int getMaxUndoStackSize()const; + unsigned int getMaxUndoStackSize() const; /// Remove all stored Undos and Redos void clearUndos(); /// Returns the number of stored Undos. If greater than 0 Undo will be effective. - int getAvailableUndos(int id=0) const; + int getAvailableUndos(int id = 0) const; /// Returns a list of the Undo names std::vector getAvailableUndoNames() const; /// Will UNDO one step, returns False if no undo was done (Undos == 0). - bool undo(int id=0); + bool undo(int id = 0); /// Returns the number of stored Redos. If greater than 0 Redo will be effective. - int getAvailableRedos(int id=0) const; + int getAvailableRedos(int id = 0) const; /// Returns a list of the Redo names. std::vector getAvailableRedoNames() const; /// Will REDO one step, returns False if no redo was done (Redos == 0). - bool redo(int id=0) ; - /// returns true if the document is in an Transaction phase, e.g. currently performing a redo/undo or rollback + bool redo(int id = 0); + /// returns true if the document is in an Transaction phase, e.g. currently performing a + /// redo/undo or rollback bool isPerformingTransaction() const; /// \internal add or remove property from a transactional object - void addOrRemovePropertyOfObject(TransactionalObject*, Property *prop, bool add); + void addOrRemovePropertyOfObject(TransactionalObject*, Property* prop, bool add); //@} /** @name dependency stuff */ //@{ /// write GraphViz file - void writeDependencyGraphViz(std::ostream &out); + void writeDependencyGraphViz(std::ostream& out); /// checks if the graph is directed and has no cycles bool checkOnCycle(); /// get a list of all objects linking to the given object std::vector getInList(const DocumentObject* me) const; /// Option bit flags used by getDepenencyList() - enum DependencyOption { + enum DependencyOption + { /// Return topological sorted list DepSort = 1, /// Do no include object linked by PropertyXLink, as it can handle external link @@ -461,14 +479,15 @@ class AppExport Document : public App::PropertyContainer * @param objs: input objects to query for dependency. * @param options: See DependencyOption */ - static std::vector getDependencyList( - const std::vector &objs, int options=0); + static std::vector + getDependencyList(const std::vector& objs, int options = 0); - std::vector getDependentDocuments(bool sort=true); - static std::vector getDependentDocuments(std::vector docs, bool sort); + std::vector getDependentDocuments(bool sort = true); + static std::vector getDependentDocuments(std::vector docs, + bool sort); // set Changed - //void setChanged(DocumentObject* change); + // void setChanged(DocumentObject* change); /// get a list of topological sorted objects (https://en.wikipedia.org/wiki/Topological_sorting) std::vector topologicalSort() const; /// get all root objects (objects no other one reference too) @@ -476,8 +495,8 @@ class AppExport Document : public App::PropertyContainer /// get all tree root objects (objects that are at the root of the object tree) std::vector getRootObjectsIgnoreLinks() const; /// get all possible paths from one object to another following the OutList - std::vector > getPathsByOutList - (const App::DocumentObject* from, const App::DocumentObject* to) const; + std::vector> + getPathsByOutList(const App::DocumentObject* from, const App::DocumentObject* to) const; //@} /** Called by a property during save to store its StringHasher @@ -493,7 +512,7 @@ class AppExport Document : public App::PropertyContainer * of the hasher. If the hasher has not been added before, the object must * save the hasher by calling StringHasher::Save */ - std::pair addStringHasher(const StringHasherRef & hasher) const; + std::pair addStringHasher(const StringHasherRef& hasher) const; /** Called by property to restore its StringHasher * @@ -505,7 +524,7 @@ class AppExport Document : public App::PropertyContainer * The caller is responsible for restoring the hasher if the caller is the first * owner of the hasher, i.e. if addStringHasher() returns true during save. */ - StringHasherRef getStringHasher(int index=-1) const; + StringHasherRef getStringHasher(int index = -1) const; /** Return the links to a given object * @@ -516,22 +535,32 @@ class AppExport Document : public App::PropertyContainer * @param objs: optional objects to search for, if empty, then all objects * of this document are searched. */ - void getLinksTo(std::set &links, - const DocumentObject *obj, int options, int maxCount=0, - const std::vector &objs = {}) const; + void getLinksTo(std::set& links, + const DocumentObject* obj, + int options, + int maxCount = 0, + const std::vector& objs = {}) const; /// Check if there is any link to the given object - bool hasLinksTo(const DocumentObject *obj) const; + bool hasLinksTo(const DocumentObject* obj) const; /// Called by objects during restore to ask for recompute - void addRecomputeObject(DocumentObject *obj); + void addRecomputeObject(DocumentObject* obj); - const std::string &getOldLabel() const {return oldLabel;} + const std::string& getOldLabel() const + { + return oldLabel; + } /// Function called to signal that an object identifier has been renamed - void renameObjectIdentifiers(const std::map & paths, const std::function &selector = [](const App::DocumentObject *) { return true; }); + void renameObjectIdentifiers( + const std::map& paths, + const std::function& selector = + [](const App::DocumentObject*) { + return true; + }); - PyObject *getPyObject() override; + PyObject* getPyObject() override; std::string getFullName() const override; @@ -550,23 +579,23 @@ class AppExport Document : public App::PropertyContainer protected: /// Construction - explicit Document(const char *documentName = ""); + explicit Document(const char* documentName = ""); void _removeObject(DocumentObject* pcObject); void _addObject(DocumentObject* pcObject, const char* pObjectName); /// checks if a valid transaction is open - void _checkTransaction(DocumentObject* pcDelObj, const Property *What, int line); + void _checkTransaction(DocumentObject* pcDelObj, const Property* What, int line); void breakDependency(DocumentObject* pcObject, bool clear); std::vector readObjects(Base::XMLReader& reader); - void writeObjects(const std::vector&, Base::Writer &writer) const; + void writeObjects(const std::vector&, Base::Writer& writer) const; bool saveToFile(const char* filename) const; void onBeforeChange(const Property* prop) override; void onChanged(const Property* prop) override; /// callback from the Document objects before property will be changed - void onBeforeChangeProperty(const TransactionalObject *Who, const Property *What); + void onBeforeChangeProperty(const TransactionalObject* Who, const Property* What); /// callback from the Document objects after property was changed - void onChangedProperty(const DocumentObject *Who, const Property *What); + void onChangedProperty(const DocumentObject* Who, const Property* What); /// helper which Recompute only this feature /// @return 0 if succeeded, 1 if failed, -1 if aborted by user. int _recomputeFeature(DocumentObject* Feat); @@ -574,9 +603,10 @@ class AppExport Document : public App::PropertyContainer /// refresh the internal dependency graph void _rebuildDependencyList( - const std::vector &objs = std::vector()); + const std::vector& objs = std::vector()); - std::string getTransientDirectoryName(const std::string& uuid, const std::string& filename) const; + std::string getTransientDirectoryName(const std::string& uuid, + const std::string& filename) const; /** Open a new command Undo/Redo, an UTF-8 name can be specified * @@ -588,18 +618,19 @@ class AppExport Document : public App::PropertyContainer * This function creates an actual transaction regardless of Application * AutoTransaction setting. */ - int _openTransaction(const char* name=nullptr, int id=0); + int _openTransaction(const char* name = nullptr, int id = 0); /// Internally called by App::Application to commit the Command transaction. - void _commitTransaction(bool notify=false); + void _commitTransaction(bool notify = false); /// Internally called by App::Application to abort the running transaction. void _abortTransaction(); private: - // # Data Member of the document +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // # Data Member of the document + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ std::list mUndoTransactions; - std::map mUndoMap; + std::map mUndoMap; std::list mRedoTransactions; - std::map mRedoMap; + std::map mRedoMap; struct DocumentP* d; @@ -613,12 +644,13 @@ inline std::vector Document::getObjectsOfType() const std::vector type; std::vector obj = this->getObjectsOfType(T::getClassTypeId()); type.reserve(obj.size()); - for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) - type.push_back(static_cast(*it)); + for (auto it : obj) { + type.push_back(static_cast(it)); + } return type; } -} //namespace App +} // namespace App -#endif // APP_DOCUMENT_H +#endif // APP_DOCUMENT_H diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index a7f1f93efe66..abff0d876fca 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -46,7 +46,7 @@ #include "PropertyLinks.h" -FC_LOG_LEVEL_INIT("App",true,true) +FC_LOG_LEVEL_INIT("App", true, true) using namespace App; @@ -57,7 +57,7 @@ using namespace App; PROPERTY_SOURCE(App::DocumentObject, App::TransactionalObject) -DocumentObjectExecReturn *DocumentObject::StdReturn = nullptr; +DocumentObjectExecReturn* DocumentObject::StdReturn = nullptr; //=========================================================================== // DocumentObject @@ -67,30 +67,30 @@ DocumentObject::DocumentObject() : ExpressionEngine() { // define Label of type 'Output' to avoid being marked as touched after relabeling - ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)"); - ADD_PROPERTY_TYPE(Label2,(""),"Base",Prop_Hidden,"User description of the object (UTF8)"); - Label2.setStatus(App::Property::Output,true); - ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions"); + ADD_PROPERTY_TYPE(Label, ("Unnamed"), "Base", Prop_Output, "User name of the object (UTF8)"); + ADD_PROPERTY_TYPE(Label2, (""), "Base", Prop_Hidden, "User description of the object (UTF8)"); + Label2.setStatus(App::Property::Output, true); + ADD_PROPERTY_TYPE(ExpressionEngine, (), "Base", Prop_Hidden, "Property expressions"); ADD_PROPERTY(Visibility, (true)); // default set Visibility status to hidden and output (no touch) for - // compatibitily reason. We use setStatus instead of PropertyType to + // compatibitily reason. We use setStatus instead of PropertyType to // allow user to change its status later - Visibility.setStatus(Property::Output,true); - Visibility.setStatus(Property::Hidden,true); - Visibility.setStatus(Property::NoModify,true); + Visibility.setStatus(Property::Output, true); + Visibility.setStatus(Property::Hidden, true); + Visibility.setStatus(Property::NoModify, true); } DocumentObject::~DocumentObject() { - if (!PythonObject.is(Py::_None())){ + if (!PythonObject.is(Py::_None())) { Base::PyGILStateLocker lock; // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed - // Python object or not. In the constructor we forced the wrapper to own the object so we need - // not to dec'ref the Python object any more. - // But we must still invalidate the Python object because it need not to be - // destructed right now because the interpreter can own several references to it. + // Python object or not. In the constructor we forced the wrapper to own the object so we + // need not to dec'ref the Python object any more. But we must still invalidate the Python + // object because it need not to be destructed right now because the interpreter can own + // several references to it. Base::PyObjectBase* obj = static_cast(PythonObject.ptr()); // Call before decrementing the reference counter, otherwise a heap error can occur obj->setInvalid(); @@ -101,7 +101,8 @@ void DocumentObject::printInvalidLinks() const { try { // Get objects that have invalid link scope, and print their names. - // Truncate the invalid object list name strings for readability, if they happen to be very long. + // Truncate the invalid object list name strings for readability, if they happen to be very + // long. std::vector invalid_linkobjs; std::string objnames, scopenames; GeoFeatureGroupExtension::getInvalidLinkObjects(this, invalid_linkobjs); @@ -138,17 +139,21 @@ void DocumentObject::printInvalidLinks() const scopenames.pop_back(); } - Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. Instead, the linked object(s) reside within '%s'.\n", - getTypeId().getName(), objnames.c_str(), getNameInDocument(), scopenames.c_str()); + Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. " + "Instead, the linked object(s) reside within '%s'.\n", + getTypeId().getName(), + objnames.c_str(), + getNameInDocument(), + scopenames.c_str()); } catch (const Base::Exception& e) { e.ReportException(); } } -App::DocumentObjectExecReturn *DocumentObject::recompute() +App::DocumentObjectExecReturn* DocumentObject::recompute() { - //check if the links are valid before making the recompute + // check if the links are valid before making the recompute if (!GeoFeatureGroupExtension::areLinksValid(this)) { printInvalidLinks(); } @@ -171,20 +176,21 @@ App::DocumentObjectExecReturn *DocumentObject::recompute() return ret; } -DocumentObjectExecReturn *DocumentObject::execute() +DocumentObjectExecReturn* DocumentObject::execute() { return executeExtensions(); } App::DocumentObjectExecReturn* DocumentObject::executeExtensions() { - //execute extensions but stop on error - this->setStatus(App::RecomputeExtension, false); // reset the flag + // execute extensions but stop on error + this->setStatus(App::RecomputeExtension, false); // reset the flag auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) { + for (auto ext : vector) { auto ret = ext->extensionExecute(); - if (ret != StdReturn) + if (ret != StdReturn) { return ret; + } } return StdReturn; @@ -193,8 +199,9 @@ App::DocumentObjectExecReturn* DocumentObject::executeExtensions() bool DocumentObject::recomputeFeature(bool recursive) { Document* doc = this->getDocument(); - if (doc) - return doc->recomputeFeature(this,recursive); + if (doc) { + return doc->recomputeFeature(this, recursive); + } return isValid(); } @@ -207,11 +214,13 @@ bool DocumentObject::recomputeFeature(bool recursive) */ void DocumentObject::touch(bool noRecompute) { - if(!noRecompute) + if (!noRecompute) { StatusBits.set(ObjectStatus::Enforce); + } StatusBits.set(ObjectStatus::Touch); - if (_pDoc) + if (_pDoc) { _pDoc->signalTouchedObject(*this); + } } /** @@ -222,8 +231,9 @@ void DocumentObject::freeze() { StatusBits.set(ObjectStatus::Freeze); // use the signalTouchedObject to refresh the Gui - if (_pDoc) + if (_pDoc) { _pDoc->signalTouchedObject(*this); + } } /** @@ -263,25 +273,29 @@ void DocumentObject::enforceRecompute() */ bool DocumentObject::mustRecompute() const { - if (StatusBits.test(ObjectStatus::Freeze)) + if (StatusBits.test(ObjectStatus::Freeze)) { return false; + } - if (StatusBits.test(ObjectStatus::Enforce)) + if (StatusBits.test(ObjectStatus::Enforce)) { return true; + } return mustExecute() > 0; } short DocumentObject::mustExecute() const { - if (ExpressionEngine.isTouched()) + if (ExpressionEngine.isTouched()) { return 1; + } - //ask all extensions + // ask all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) { - if (ext->extensionMustExecute()) + for (auto ext : vector) { + if (ext->extensionMustExecute()) { return 1; + } } return 0; @@ -293,24 +307,30 @@ const char* DocumentObject::getStatusString() const const char* text = getDocument()->getErrorDescription(this); return text ? text : "Error"; } - else if (isTouched()) + else if (isTouched()) { return "Touched"; - else + } + else { return "Valid"; + } } -std::string DocumentObject::getFullName() const { - if(!getDocument() || !isAttachedToDocument()) +std::string DocumentObject::getFullName() const +{ + if (!getDocument() || !isAttachedToDocument()) { return "?"; + } std::string name(getDocument()->getName()); name += '#'; name += *pcNameInDocument; return name; } -std::string DocumentObject::getFullLabel() const { - if(!getDocument()) +std::string DocumentObject::getFullLabel() const +{ + if (!getDocument()) { return "?"; + } auto name = getDocument()->Label.getStrValue(); name += "#"; @@ -320,37 +340,42 @@ std::string DocumentObject::getFullLabel() const { const char* DocumentObject::getDagKey() const { - if(!pcNameInDocument) - { + if (!pcNameInDocument) { return nullptr; } return pcNameInDocument->c_str(); } -const char *DocumentObject::getNameInDocument() const +const char* DocumentObject::getNameInDocument() const { // Note: It can happen that we query the internal name of an object even if it is not // part of a document (anymore). This is the case e.g. if we have a reference in Python // to an object that has been removed from the document. In this case we should rather // return 0. - //assert(pcNameInDocument); - if (!pcNameInDocument) + // assert(pcNameInDocument); + if (!pcNameInDocument) { return nullptr; + } return pcNameInDocument->c_str(); } -int DocumentObject::isExporting() const { - if(!getDocument() || !isAttachedToDocument()) +int DocumentObject::isExporting() const +{ + if (!getDocument() || !isAttachedToDocument()) { return 0; + } return getDocument()->isExporting(this); } -std::string DocumentObject::getExportName(bool forced) const { - if(!isAttachedToDocument()) +std::string DocumentObject::getExportName(bool forced) const +{ + if (!isAttachedToDocument()) { return {}; + } - if(!forced && !isExporting()) + if (!forced && !isExporting()) { return *pcNameInDocument; + } // '@' is an invalid character for an internal name, which ensures the // following returned name will be unique in any document. Saving external @@ -371,10 +396,11 @@ const char* DocumentObject::detachFromDocument() return name ? name->c_str() : nullptr; } -const std::vector &DocumentObject::getOutList() const { - if(!_outListCached) { +const std::vector& DocumentObject::getOutList() const +{ + if (!_outListCached) { _outList.clear(); - getOutList(0,_outList); + getOutList(0, _outList); _outListCached = true; } return _outList; @@ -383,34 +409,39 @@ const std::vector &DocumentObject::getOutList() const { std::vector DocumentObject::getOutList(int options) const { std::vector res; - getOutList(options,res); + getOutList(options, res); return res; } -void DocumentObject::getOutList(int options, std::vector &res) const { - if(_outListCached && !options) { - res.insert(res.end(),_outList.begin(),_outList.end()); +void DocumentObject::getOutList(int options, std::vector& res) const +{ + if (_outListCached && !options) { + res.insert(res.end(), _outList.begin(), _outList.end()); return; } std::vector props; getPropertyList(props); bool noHidden = !!(options & OutListNoHidden); std::size_t size = res.size(); - for(auto prop : props) { + for (auto prop : props) { auto link = dynamic_cast(prop); - if(link) - link->getLinks(res,noHidden); + if (link) { + link->getLinks(res, noHidden); + } } - if(!(options & OutListNoExpression)) + if (!(options & OutListNoExpression)) { ExpressionEngine.getLinks(res); + } - if(options & OutListNoXLinked) { - for(auto it=res.begin()+size;it!=res.end();) { + if (options & OutListNoXLinked) { + for (auto it = res.begin() + size; it != res.end();) { auto obj = *it; - if(obj && obj->getDocument()!=getDocument()) + if (obj && obj->getDocument() != getDocument()) { it = res.erase(it); - else + } + else { ++it; + } } } } @@ -418,32 +449,36 @@ void DocumentObject::getOutList(int options, std::vector &res) std::vector DocumentObject::getOutListOfProperty(App::Property* prop) const { std::vector ret; - if (!prop || prop->getContainer() != this) + if (!prop || prop->getContainer() != this) { return ret; + } auto link = dynamic_cast(prop); - if(link) + if (link) { link->getLinks(ret); + } return ret; } #ifdef USE_OLD_DAG std::vector DocumentObject::getInList(void) const { - if (_pDoc) + if (_pDoc) { return _pDoc->getInList(this); - else + } + else { return std::vector(); + } } -#else // ifndef USE_OLD_DAG +#else // ifndef USE_OLD_DAG -const std::vector &DocumentObject::getInList() const +const std::vector& DocumentObject::getInList() const { return _inList; } -#endif // if USE_OLD_DAG +#endif // if USE_OLD_DAG // The original algorithm is highly inefficient in some special case. @@ -454,10 +489,11 @@ const std::vector &DocumentObject::getInList() const // of objects. And this may not be the worst case. getInListEx() has no such // problem. -std::vector DocumentObject::getInListRecursive() const { +std::vector DocumentObject::getInListRecursive() const +{ std::set inSet; std::vector res; - getInListEx(inSet,true,&res); + getInListEx(inSet, true, &res); return res; } @@ -465,61 +501,64 @@ std::vector DocumentObject::getInListRecursive() const { // More efficient algorithm to find the recursive inList of an object, // including possible external parents. One shortcoming of this algorithm is // it does not detect cyclic reference, althgouth it won't crash either. -void DocumentObject::getInListEx(std::set &inSet, - bool recursive, std::vector *inList) const +void DocumentObject::getInListEx(std::set& inSet, + bool recursive, + std::vector* inList) const { #ifdef USE_OLD_DAG - std::map > outLists; + std::map> outLists; // Old DAG does not have pre-built InList, and must calculate The InList by // going through all objects' OutLists. So we collect all objects and their // outLists first here. - for(auto doc : GetApplication().getDocuments()) { - for(auto obj : doc->getObjects()) { - if(!obj || !obj->isAttachedToDocument() || obj==this) + for (auto doc : GetApplication().getDocuments()) { + for (auto obj : doc->getObjects()) { + if (!obj || !obj->isAttachedToDocument() || obj == this) { continue; - const auto &outList = obj->getOutList(); - outLists[obj].insert(outList.begin(),outList.end()); + } + const auto& outList = obj->getOutList(); + outLists[obj].insert(outList.begin(), outList.end()); } } std::stack pendings; pendings.push(const_cast(this)); - while(pendings.size()) { + while (pendings.size()) { auto obj = pendings.top(); pendings.pop(); - for(auto &v : outLists) { - if(v.first == obj) continue; - auto &outList = v.second; + for (auto& v : outLists) { + if (v.first == obj) { + continue; + } + auto& outList = v.second; // Check the outList to see if the object is there, and pend the // object for recursive check if it's not already in the inList - if(outList.find(obj)!=outList.end() && - inSet.insert(v.first).second && - recursive) - { + if (outList.find(obj) != outList.end() && inSet.insert(v.first).second && recursive) { pendings.push(v.first); } } } -#else // USE_OLD_DAG +#else // USE_OLD_DAG - if(!recursive) { - inSet.insert(_inList.begin(),_inList.end()); - if(inList) + if (!recursive) { + inSet.insert(_inList.begin(), _inList.end()); + if (inList) { *inList = _inList; + } return; } std::stack pendings; pendings.push(const_cast(this)); - while(!pendings.empty()) { + while (!pendings.empty()) { auto obj = pendings.top(); pendings.pop(); - for(auto o : obj->getInList()) { - if(o && o->isAttachedToDocument() && inSet.insert(o).second) { + for (auto o : obj->getInList()) { + if (o && o->isAttachedToDocument() && inSet.insert(o).second) { pendings.push(o); - if(inList) + if (inList) { inList->push_back(o); + } } } } @@ -527,26 +566,30 @@ void DocumentObject::getInListEx(std::set &inSet, #endif } -std::set DocumentObject::getInListEx(bool recursive) const { +std::set DocumentObject::getInListEx(bool recursive) const +{ std::set ret; - getInListEx(ret,recursive); + getInListEx(ret, recursive); return ret; } void _getOutListRecursive(std::set& objSet, const DocumentObject* obj, - const DocumentObject* checkObj, int depth) + const DocumentObject* checkObj, + int depth) { for (const auto objIt : obj->getOutList()) { // if the check object is in the recursive inList we have a cycle! if (objIt == checkObj || depth <= 0) { - throw Base::BadGraphError("DocumentObject::getOutListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::getOutListRecursive(): cyclic dependency detected!"); } // if the element was already in the set then there is no need to process it again auto pair = objSet.insert(objIt); - if (pair.second) - _getOutListRecursive(objSet, objIt, checkObj, depth-1); + if (pair.second) { + _getOutListRecursive(objSet, objIt, checkObj, depth - 1); + } } } @@ -565,20 +608,22 @@ std::vector DocumentObject::getOutListRecursive() const } // helper for isInInListRecursive() -bool _isInInListRecursive(const DocumentObject* act, - const DocumentObject* checkObj, int depth) +bool _isInInListRecursive(const DocumentObject* act, const DocumentObject* checkObj, int depth) { -#ifndef USE_OLD_DAG +#ifndef USE_OLD_DAG for (auto obj : act->getInList()) { - if (obj == checkObj) + if (obj == checkObj) { return true; + } // if we reach the depth limit we have a cycle! if (depth <= 0) { - throw Base::BadGraphError("DocumentObject::isInInListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::isInInListRecursive(): cyclic dependency detected!"); } - if (_isInInListRecursive(obj, checkObj, depth - 1)) + if (_isInInListRecursive(obj, checkObj, depth - 1)) { return true; + } } #else (void)act; @@ -589,18 +634,20 @@ bool _isInInListRecursive(const DocumentObject* act, return false; } -bool DocumentObject::isInInListRecursive(DocumentObject *linkTo) const +bool DocumentObject::isInInListRecursive(DocumentObject* linkTo) const { - return this==linkTo || getInListEx(true).count(linkTo); + return this == linkTo || getInListEx(true).count(linkTo); } -bool DocumentObject::isInInList(DocumentObject *linkTo) const +bool DocumentObject::isInInList(DocumentObject* linkTo) const { -#ifndef USE_OLD_DAG - if (std::find(_inList.begin(), _inList.end(), linkTo) != _inList.end()) +#ifndef USE_OLD_DAG + if (std::find(_inList.begin(), _inList.end(), linkTo) != _inList.end()) { return true; - else + } + else { return false; + } #else (void)linkTo; return false; @@ -608,20 +655,22 @@ bool DocumentObject::isInInList(DocumentObject *linkTo) const } // helper for isInOutListRecursive() -bool _isInOutListRecursive(const DocumentObject* act, - const DocumentObject* checkObj, int depth) +bool _isInOutListRecursive(const DocumentObject* act, const DocumentObject* checkObj, int depth) { -#ifndef USE_OLD_DAG +#ifndef USE_OLD_DAG for (auto obj : act->getOutList()) { - if (obj == checkObj) + if (obj == checkObj) { return true; + } // if we reach the depth limit we have a cycle! if (depth <= 0) { - throw Base::BadGraphError("DocumentObject::isInOutListRecursive(): cyclic dependency detected!"); + throw Base::BadGraphError( + "DocumentObject::isInOutListRecursive(): cyclic dependency detected!"); } - if (_isInOutListRecursive(obj, checkObj, depth - 1)) + if (_isInOutListRecursive(obj, checkObj, depth - 1)) { return true; + } } #else (void)act; @@ -632,13 +681,13 @@ bool _isInOutListRecursive(const DocumentObject* act, return false; } -bool DocumentObject::isInOutListRecursive(DocumentObject *linkTo) const +bool DocumentObject::isInOutListRecursive(DocumentObject* linkTo) const { int maxDepth = getDocument()->countObjects() + 2; return _isInOutListRecursive(this, linkTo, maxDepth); } -std::vector > +std::vector> DocumentObject::getPathsByOutList(App::DocumentObject* to) const { return _pDoc->getPathsByOutList(this, to); @@ -649,30 +698,32 @@ DocumentObjectGroup* DocumentObject::getGroup() const return dynamic_cast(GroupExtension::getGroupOfObject(this)); } -bool DocumentObject::testIfLinkDAGCompatible(DocumentObject *linkTo) const +bool DocumentObject::testIfLinkDAGCompatible(DocumentObject* linkTo) const { std::vector linkTo_in_vector; linkTo_in_vector.push_back(linkTo); return this->testIfLinkDAGCompatible(linkTo_in_vector); } -bool DocumentObject::testIfLinkDAGCompatible(const std::vector &linksTo) const +bool DocumentObject::testIfLinkDAGCompatible(const std::vector& linksTo) const { auto inLists = getInListEx(true); inLists.emplace(const_cast(this)); - for(auto obj : linksTo) - if(inLists.count(obj)) + for (auto obj : linksTo) { + if (inLists.count(obj)) { return false; + } + } return true; } -bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList &linksTo) const +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList& linksTo) const { - const std::vector &linksTo_in_vector = linksTo.getValues(); + const std::vector& linksTo_in_vector = linksTo.getValues(); return this->testIfLinkDAGCompatible(linksTo_in_vector); } -bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub& linkTo) const { std::vector linkTo_in_vector; linkTo_in_vector.reserve(1); @@ -681,32 +732,33 @@ bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const } void DocumentObject::onLostLinkToObject(DocumentObject*) -{ - -} +{} -App::Document *DocumentObject::getDocument() const +App::Document* DocumentObject::getDocument() const { return _pDoc; } void DocumentObject::setDocument(App::Document* doc) { - _pDoc=doc; + _pDoc = doc; onSettingDocument(); } bool DocumentObject::removeDynamicProperty(const char* name) { - if (!_pDoc || testStatus(ObjectStatus::Destroy)) + if (!_pDoc || testStatus(ObjectStatus::Destroy)) { return false; + } Property* prop = getDynamicPropertyByName(name); - if(!prop || prop->testStatus(App::Property::LockDynamic)) + if (!prop || prop->testStatus(App::Property::LockDynamic)) { return false; + } - if(prop->isDerivedFrom(PropertyLinkBase::getClassTypeId())) + if (prop->isDerivedFrom(PropertyLinkBase::getClassTypeId())) { clearOutListCache(); + } _pDoc->addOrRemovePropertyOfObject(this, prop, false); @@ -726,44 +778,49 @@ bool DocumentObject::removeDynamicProperty(const char* name) return TransactionalObject::removeDynamicProperty(name); } -App::Property* DocumentObject::addDynamicProperty( - const char* type, const char* name, const char* group, const char* doc, - short attr, bool ro, bool hidden) +App::Property* DocumentObject::addDynamicProperty(const char* type, + const char* name, + const char* group, + const char* doc, + short attr, + bool ro, + bool hidden) { - auto prop = TransactionalObject::addDynamicProperty(type,name,group,doc,attr,ro,hidden); - if(prop && _pDoc) + auto prop = TransactionalObject::addDynamicProperty(type, name, group, doc, attr, ro, hidden); + if (prop && _pDoc) { _pDoc->addOrRemovePropertyOfObject(this, prop, true); + } return prop; } void DocumentObject::onBeforeChange(const Property* prop) { - // Store current name in oldLabel, to be able to easily retrieve old name of document object later - // when renaming expressions. - if (prop == &Label) + // Store current name in oldLabel, to be able to easily retrieve old name of document object + // later when renaming expressions. + if (prop == &Label) { oldLabel = Label.getStrValue(); + } - if (_pDoc) + if (_pDoc) { onBeforeChangeProperty(_pDoc, prop); + } - signalBeforeChange(*this,*prop); + signalBeforeChange(*this, *prop); } -void DocumentObject::onEarlyChange(const Property *prop) +void DocumentObject::onEarlyChange(const Property* prop) { - if(GetApplication().isClosingAll()) + if (GetApplication().isClosingAll()) { return; + } - if(!GetApplication().isRestoring() && - !prop->testStatus(Property::PartialTrigger) && - getDocument() && - getDocument()->testStatus(Document::PartialDoc)) - { - static App::Document *warnedDoc; - if(warnedDoc != getDocument()) { + if (!GetApplication().isRestoring() && !prop->testStatus(Property::PartialTrigger) + && getDocument() && getDocument()->testStatus(Document::PartialDoc)) { + static App::Document* warnedDoc; + if (warnedDoc != getDocument()) { warnedDoc = getDocument(); - FC_WARN("Changes to partial loaded document will not be saved: " - << getFullName() << '.' << prop->getName()); + FC_WARN("Changes to partial loaded document will not be saved: " << getFullName() << '.' + << prop->getName()); } } @@ -773,22 +830,21 @@ void DocumentObject::onEarlyChange(const Property *prop) /// get called by the container when a Property was changed void DocumentObject::onChanged(const Property* prop) { - if (isFreezed()) + if (isFreezed()) { return; + } - if(GetApplication().isClosingAll()) + if (GetApplication().isClosingAll()) { return; + } - if(!GetApplication().isRestoring() && - !prop->testStatus(Property::PartialTrigger) && - getDocument() && - getDocument()->testStatus(Document::PartialDoc)) - { - static App::Document *warnedDoc; - if(warnedDoc != getDocument()) { + if (!GetApplication().isRestoring() && !prop->testStatus(Property::PartialTrigger) + && getDocument() && getDocument()->testStatus(Document::PartialDoc)) { + static App::Document* warnedDoc; + if (warnedDoc != getDocument()) { warnedDoc = getDocument(); - FC_WARN("Changes to partial loaded document will not be saved: " - << getFullName() << '.' << prop->getName()); + FC_WARN("Changes to partial loaded document will not be saved: " << getFullName() << '.' + << prop->getName()); } } @@ -797,94 +853,106 @@ void DocumentObject::onChanged(const Property* prop) // if (_pDoc) // _pDoc->onChangedProperty(this,prop); - if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) + if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) { _pDoc->signalRelabelObject(*this); + } // set object touched if it is an input property - if (!testStatus(ObjectStatus::NoTouch) - && !(prop->getType() & Prop_Output) - && !prop->testStatus(Property::Output)) - { - if(!StatusBits.test(ObjectStatus::Touch)) { + if (!testStatus(ObjectStatus::NoTouch) && !(prop->getType() & Prop_Output) + && !prop->testStatus(Property::Output)) { + if (!StatusBits.test(ObjectStatus::Touch)) { FC_TRACE("touch '" << getFullName() << "' on change of '" << prop->getName() << "'"); StatusBits.set(ObjectStatus::Touch); } // must execute on document recompute - if (!(prop->getType() & Prop_NoRecompute)) + if (!(prop->getType() & Prop_NoRecompute)) { StatusBits.set(ObjectStatus::Enforce); + } } - //call the parent for appropriate handling + // call the parent for appropriate handling TransactionalObject::onChanged(prop); // Now signal the view provider - if (_pDoc) - _pDoc->onChangedProperty(this,prop); + if (_pDoc) { + _pDoc->onChangedProperty(this, prop); + } - signalChanged(*this,*prop); + signalChanged(*this, *prop); } -void DocumentObject::clearOutListCache() const { +void DocumentObject::clearOutListCache() const +{ _outList.clear(); _outListMap.clear(); _outListCached = false; } -PyObject *DocumentObject::getPyObject() +PyObject* DocumentObject::getPyObject() { if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); + PythonObject = Py::Object(new DocumentObjectPy(this), true); } return Py::new_reference_to(PythonObject); } -DocumentObject *DocumentObject::getSubObject(const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +DocumentObject* DocumentObject::getSubObject(const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { - DocumentObject *ret = nullptr; + DocumentObject* ret = nullptr; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetSubObject(ret,subname,pyObj,mat,transform, depth)) + for (auto ext : exts) { + if (ext->extensionGetSubObject(ret, subname, pyObj, mat, transform, depth)) { return ret; + } } std::string name; - const char *dot=nullptr; - if(!subname || !(dot=strchr(subname,'.'))) { + const char* dot = nullptr; + if (!subname || !(dot = strchr(subname, '.'))) { ret = const_cast(this); - }else if(subname[0]=='$') { - name = std::string(subname+1,dot); - for(auto obj : getOutList()) { - if(name == obj->Label.getValue()) { + } + else if (subname[0] == '$') { + name = std::string(subname + 1, dot); + for (auto obj : getOutList()) { + if (name == obj->Label.getValue()) { ret = obj; break; } } - }else{ - name = std::string(subname,dot); - const auto &outList = getOutList(); - if(outList.size()!=_outListMap.size()) { + } + else { + name = std::string(subname, dot); + const auto& outList = getOutList(); + if (outList.size() != _outListMap.size()) { _outListMap.clear(); - for(auto obj : outList) + for (auto obj : outList) { _outListMap[obj->getDagKey()] = obj; + } } auto it = _outListMap.find(name.c_str()); - if(it != _outListMap.end()) + if (it != _outListMap.end()) { ret = it->second; + } } // TODO: By right, normal object's placement does not transform its sub // objects (think of the claimed children of a Fusion). But I do think we // should change that. - if(transform && mat) { + if (transform && mat) { auto pla = Base::freecad_dynamic_cast(getPropertyByName("Placement")); - if(pla) + if (pla) { *mat *= pla->getValue().toMatrix(); + } } - if(ret && dot) - return ret->getSubObject(dot+1,pyObj,mat,true,depth+1); + if (ret && dot) { + return ret->getSubObject(dot + 1, pyObj, mat, true, depth + 1); + } return ret; } @@ -979,18 +1047,22 @@ std::vector DocumentObject::getSubObjectList(const char* subnam return res; } -std::vector DocumentObject::getSubObjects(int reason) const { +std::vector DocumentObject::getSubObjects(int reason) const +{ std::vector ret; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetSubObjects(ret,reason)) + for (auto ext : exts) { + if (ext->extensionGetSubObjects(ret, reason)) { return ret; + } } return ret; } -std::vector> DocumentObject::getParents(int depth) const { - std::vector> ret; +std::vector> +DocumentObject::getParents(int depth) const +{ + std::vector> ret; if (!isAttachedToDocument() || !GetApplication().checkLinkDepth(depth, MessageOption::Throw)) { return ret; } @@ -1002,8 +1074,8 @@ std::vector> DocumentObject::getPar continue; } - if (!parent->hasChildElement() && - !parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) { + if (!parent->hasChildElement() + && !parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) { continue; } @@ -1020,7 +1092,7 @@ std::vector> DocumentObject::getPar parents.emplace_back(parent, std::string()); } - for (auto &v : parents) { + for (auto& v : parents) { ret.emplace_back(v.first, v.second + name); } } @@ -1040,27 +1112,32 @@ App::DocumentObject* DocumentObject::getFirstParent() const return nullptr; } -DocumentObject *DocumentObject::getLinkedObject( - bool recursive, Base::Matrix4D *mat, bool transform, int depth) const +DocumentObject* DocumentObject::getLinkedObject(bool recursive, + Base::Matrix4D* mat, + bool transform, + int depth) const { - DocumentObject *ret = nullptr; + DocumentObject* ret = nullptr; auto exts = getExtensionsDerivedFromType(); - for(auto ext : exts) { - if(ext->extensionGetLinkedObject(ret,recursive,mat,transform,depth)) + for (auto ext : exts) { + if (ext->extensionGetLinkedObject(ret, recursive, mat, transform, depth)) { return ret; + } } - if(transform && mat) { + if (transform && mat) { auto pla = dynamic_cast(getPropertyByName("Placement")); - if(pla) + if (pla) { *mat *= pla->getValue().toMatrix(); + } } return const_cast(this); } -void DocumentObject::Save (Base::Writer &writer) const +void DocumentObject::Save(Base::Writer& writer) const { - if (this->isAttachedToDocument()) + if (this->isAttachedToDocument()) { writer.ObjectName = this->getNameInDocument(); + } App::ExtensionContainer::Save(writer); } @@ -1070,7 +1147,7 @@ void DocumentObject::Save (Base::Writer &writer) const * @param expr Expression tree */ -void DocumentObject::setExpression(const ObjectIdentifier &path, std::shared_ptr expr) +void DocumentObject::setExpression(const ObjectIdentifier& path, std::shared_ptr expr) { ExpressionEngine.setValue(path, expr); } @@ -1080,7 +1157,7 @@ void DocumentObject::setExpression(const ObjectIdentifier &path, std::shared_ptr * @param path Target object identifier */ -void DocumentObject::clearExpression(const ObjectIdentifier & path) +void DocumentObject::clearExpression(const ObjectIdentifier& path) { setExpression(path, std::shared_ptr()); } @@ -1091,14 +1168,17 @@ void DocumentObject::clearExpression(const ObjectIdentifier & path) * @return Expression info, containing expression and optional comment. */ -const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const +const PropertyExpressionEngine::ExpressionInfo +DocumentObject::getExpression(const ObjectIdentifier& path) const { boost::any value = ExpressionEngine.getPathValue(path); - if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo)) + if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo)) { return boost::any_cast(value); - else + } + else { return PropertyExpressionEngine::ExpressionInfo(); + } } /** @@ -1108,58 +1188,63 @@ const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(con * @param paths */ -void DocumentObject::renameObjectIdentifiers(const std::map &paths) +void DocumentObject::renameObjectIdentifiers( + const std::map& paths) { ExpressionEngine.renameObjectIdentifiers(paths); } void DocumentObject::onDocumentRestored() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedDocumentRestored(); - if(Visibility.testStatus(Property::Output)) - Visibility.setStatus(Property::NoModify,true); + } + if (Visibility.testStatus(Property::Output)) { + Visibility.setStatus(Property::NoModify, true); + } } void DocumentObject::onUndoRedoFinished() -{ - -} +{} void DocumentObject::onSettingDocument() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedSettingDocument(); + } } void DocumentObject::setupObject() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedSetupObject(); + } } void DocumentObject::unsetupObject() { - //call all extensions + // call all extensions auto vector = getExtensionsDerivedFromType(); - for(auto ext : vector) + for (auto ext : vector) { ext->onExtendedUnsetupObject(); + } } void App::DocumentObject::_removeBackLink(DocumentObject* rmvObj) { #ifndef USE_OLD_DAG - //do not use erase-remove idom, as this erases ALL entries that match. we only want to remove a - //single one. + // do not use erase-remove idom, as this erases ALL entries that match. we only want to remove a + // single one. auto it = std::find(_inList.begin(), _inList.end(), rmvObj); - if(it != _inList.end()) + if (it != _inList.end()) { _inList.erase(it); + } #else (void)rmvObj; #endif @@ -1168,110 +1253,131 @@ void App::DocumentObject::_removeBackLink(DocumentObject* rmvObj) void App::DocumentObject::_addBackLink(DocumentObject* newObj) { #ifndef USE_OLD_DAG - //we need to add all links, even if they are available multiple times. The reason for this is the - //removal: If a link loses this object it removes the backlink. If we would have added it only once - //this removal would clear the object from the inlist, even though there may be other link properties - //from this object that link to us. + // we need to add all links, even if they are available multiple times. The reason for this is + // the removal: If a link loses this object it removes the backlink. If we would have added it + // only once this removal would clear the object from the inlist, even though there may be other + // link properties from this object that link to us. _inList.push_back(newObj); #else (void)newObj; -#endif //USE_OLD_DAG +#endif // USE_OLD_DAG } -int DocumentObject::setElementVisible(const char *element, bool visible) { - for(auto ext : getExtensionsDerivedFromType()) { - int ret = ext->extensionSetElementVisible(element,visible); - if(ret>=0) +int DocumentObject::setElementVisible(const char* element, bool visible) +{ + for (auto ext : getExtensionsDerivedFromType()) { + int ret = ext->extensionSetElementVisible(element, visible); + if (ret >= 0) { return ret; + } } return -1; } -int DocumentObject::isElementVisible(const char *element) const { - for(auto ext : getExtensionsDerivedFromType()) { +int DocumentObject::isElementVisible(const char* element) const +{ + for (auto ext : getExtensionsDerivedFromType()) { int ret = ext->extensionIsElementVisible(element); - if(ret>=0) + if (ret >= 0) { return ret; + } } return -1; } -bool DocumentObject::hasChildElement() const { - for(auto ext : getExtensionsDerivedFromType()) { - if(ext->extensionHasChildElement()) +bool DocumentObject::hasChildElement() const +{ + for (auto ext : getExtensionsDerivedFromType()) { + if (ext->extensionHasChildElement()) { return true; + } } return false; } -DocumentObject *DocumentObject::resolve(const char *subname, - App::DocumentObject **parent, std::string *childName, const char **subElement, - PyObject **pyObj, Base::Matrix4D *pmat, bool transform, int depth) const +DocumentObject* DocumentObject::resolve(const char* subname, + App::DocumentObject** parent, + std::string* childName, + const char** subElement, + PyObject** pyObj, + Base::Matrix4D* pmat, + bool transform, + int depth) const { auto self = const_cast(this); - if(parent) *parent = nullptr; - if(subElement) *subElement = nullptr; + if (parent) { + *parent = nullptr; + } + if (subElement) { + *subElement = nullptr; + } - auto obj = getSubObject(subname,pyObj,pmat,transform,depth); - if(!obj || !subname || *subname==0) + auto obj = getSubObject(subname, pyObj, pmat, transform, depth); + if (!obj || !subname || *subname == 0) { return self; + } - if(!parent && !subElement) + if (!parent && !subElement) { return obj; + } // NOTE, the convention of '.' separated SubName demands a mandatory ending // '.' for each object name in SubName, even if there is no subelement // following it. So finding the last dot will give us the end of the last // object name. - const char *dot=nullptr; - if(Data::isMappedElement(subname) || - !(dot=strrchr(subname,'.')) || - dot == subname) - { - if(subElement) - *subElement = dot?dot+1:subname; - return obj; // this means no parent object reference in SubName + const char* dot = nullptr; + if (Data::isMappedElement(subname) || !(dot = strrchr(subname, '.')) || dot == subname) { + if (subElement) { + *subElement = dot ? dot + 1 : subname; + } + return obj; // this means no parent object reference in SubName } - if(parent) + if (parent) { *parent = self; + } bool elementMapChecked = false; - const char *lastDot = dot; - for(--dot;;--dot) { + const char* lastDot = dot; + for (--dot;; --dot) { // check for the second last dot, which is the end of the last parent object - if(*dot == '.' || dot == subname) { + if (*dot == '.' || dot == subname) { // We can't get parent object by its name, because the object may be // externally linked (i.e. in a different document). So go through // getSubObject again. - if(!elementMapChecked) { + if (!elementMapChecked) { elementMapChecked = true; - const char *sub = dot==subname?dot:dot+1; - if(Data::isMappedElement(sub)) { + const char* sub = dot == subname ? dot : dot + 1; + if (Data::isMappedElement(sub)) { lastDot = dot; - if(dot==subname) + if (dot == subname) { break; - else + } + else { continue; + } } } - if(dot==subname) + if (dot == subname) { break; - auto sobj = getSubObject(std::string(subname,dot-subname+1).c_str()); - if(sobj!=obj) { - if(parent) { + } + auto sobj = getSubObject(std::string(subname, dot - subname + 1).c_str()); + if (sobj != obj) { + if (parent) { // Link/LinkGroup has special visibility handling of plain // group, so keep ascending - if(!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) { + if (!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { *parent = sobj; break; } - for(auto ddot=dot-1;ddot!=subname;--ddot) { - if(*ddot != '.') continue; - auto sobj = getSubObject(std::string(subname,ddot-subname+1).c_str()); - if(!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) { + for (auto ddot = dot - 1; ddot != subname; --ddot) { + if (*ddot != '.') { + continue; + } + auto sobj = getSubObject(std::string(subname, ddot - subname + 1).c_str()); + if (!sobj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { *parent = sobj; break; } @@ -1281,97 +1387,105 @@ DocumentObject *DocumentObject::resolve(const char *subname, } } } - if(childName && lastDot!=dot) { - if(*dot == '.') + if (childName && lastDot != dot) { + if (*dot == '.') { ++dot; - const char *nextDot = strchr(dot,'.'); + } + const char* nextDot = strchr(dot, '.'); assert(nextDot); - *childName = std::string(dot,nextDot-dot); + *childName = std::string(dot, nextDot - dot); + } + if (subElement) { + *subElement = *lastDot == '.' ? lastDot + 1 : lastDot; } - if(subElement) - *subElement = *lastDot=='.'?lastDot+1:lastDot; return obj; } -DocumentObject *DocumentObject::resolveRelativeLink(std::string &subname, - DocumentObject *&link, std::string &linkSub) const +DocumentObject* DocumentObject::resolveRelativeLink(std::string& subname, + DocumentObject*& link, + std::string& linkSub) const { - if(!link || !link->isAttachedToDocument() || !isAttachedToDocument()) + if (!link || !link->isAttachedToDocument() || !isAttachedToDocument()) { return nullptr; + } auto ret = const_cast(this); - if(link != ret) { + if (link != ret) { auto sub = subname.c_str(); auto nextsub = sub; - for(auto dot=strchr(nextsub,'.');dot;nextsub=dot+1,dot=strchr(nextsub,'.')) { - std::string subcheck(sub,nextsub-sub); + for (auto dot = strchr(nextsub, '.'); dot; nextsub = dot + 1, dot = strchr(nextsub, '.')) { + std::string subcheck(sub, nextsub - sub); subcheck += link->getNameInDocument(); subcheck += '.'; - if(getSubObject(subcheck.c_str())==link) { - ret = getSubObject(std::string(sub,dot+1-sub).c_str()); - if(!ret) + if (getSubObject(subcheck.c_str()) == link) { + ret = getSubObject(std::string(sub, dot + 1 - sub).c_str()); + if (!ret) { return nullptr; - subname = std::string(dot+1); + } + subname = std::string(dot + 1); break; } } return ret; } - size_t pos=0,linkPos=0; - std::string linkssub,ssub; + size_t pos = 0, linkPos = 0; + std::string linkssub, ssub; do { - linkPos = linkSub.find('.',linkPos); - if(linkPos == std::string::npos) { + linkPos = linkSub.find('.', linkPos); + if (linkPos == std::string::npos) { link = nullptr; return nullptr; } ++linkPos; - pos = subname.find('.',pos); - if(pos == std::string::npos) { + pos = subname.find('.', pos); + if (pos == std::string::npos) { subname.clear(); ret = nullptr; break; } ++pos; - }while(subname.compare(0,pos,linkSub,0,linkPos)==0); + } while (subname.compare(0, pos, linkSub, 0, linkPos) == 0); - if(pos != std::string::npos) { - ret = getSubObject(subname.substr(0,pos).c_str()); - if(!ret) { + if (pos != std::string::npos) { + ret = getSubObject(subname.substr(0, pos).c_str()); + if (!ret) { link = nullptr; return nullptr; } subname = subname.substr(pos); } - if(linkPos) { - link = link->getSubObject(linkSub.substr(0,linkPos).c_str()); - if(!link) + if (linkPos) { + link = link->getSubObject(linkSub.substr(0, linkPos).c_str()); + if (!link) { return nullptr; + } linkSub = linkSub.substr(linkPos); } return ret; } -bool DocumentObject::adjustRelativeLinks( - const std::set &inList, - std::set *visited) +bool DocumentObject::adjustRelativeLinks(const std::set& inList, + std::set* visited) { - if(visited) + if (visited) { visited->insert(this); + } bool touched = false; std::vector props; getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto linkProp = Base::freecad_dynamic_cast(prop); - if(linkProp && linkProp->adjustLink(inList)) + if (linkProp && linkProp->adjustLink(inList)) { touched = true; + } } - if(visited) { - for(auto obj : getOutList()) { - if(!visited->count(obj)) { - if(obj->adjustRelativeLinks(inList,visited)) + if (visited) { + for (auto obj : getOutList()) { + if (!visited->count(obj)) { + if (obj->adjustRelativeLinks(inList, visited)) { touched = true; + } } } } @@ -1396,28 +1510,36 @@ bool DocumentObject::checkElementMapVersion(const App::Property* _prop, const ch return prop->checkElementMapVersion(ver); } -const std::string &DocumentObject::hiddenMarker() { +const std::string& DocumentObject::hiddenMarker() +{ static std::string marker("!hide"); return marker; } -const char *DocumentObject::hasHiddenMarker(const char *subname) { - if(!subname) +const char* DocumentObject::hasHiddenMarker(const char* subname) +{ + if (!subname) { return nullptr; - const char *marker = strrchr(subname,'.'); - if(!marker) + } + const char* marker = strrchr(subname, '.'); + if (!marker) { marker = subname; - else + } + else { ++marker; - return hiddenMarker()==marker?marker:nullptr; + } + return hiddenMarker() == marker ? marker : nullptr; } -bool DocumentObject::redirectSubName(std::ostringstream &, DocumentObject *, DocumentObject *) const { +bool DocumentObject::redirectSubName(std::ostringstream&, DocumentObject*, DocumentObject*) const +{ return false; } -void DocumentObject::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) { +void DocumentObject::onPropertyStatusChanged(const Property& prop, unsigned long oldStatus) +{ (void)oldStatus; - if(!Document::isAnyRestoring() && isAttachedToDocument() && getDocument()) - getDocument()->signalChangePropertyEditor(*getDocument(),prop); + if (!Document::isAnyRestoring() && isAttachedToDocument() && getDocument()) { + getDocument()->signalChangePropertyEditor(*getDocument(), prop); + } } diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index 8c5ae0215551..72f78fe13d91 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -46,44 +46,49 @@ class DocumentObjectGroup; class DocumentObjectPy; class Expression; -enum ObjectStatus { +// clang-format off +enum ObjectStatus +{ Touch = 0, Error = 1, New = 2, - Recompute = 3, // set when the object is currently being recomputed + Recompute = 3, // set when the object is currently being recomputed Restore = 4, Remove = 5, PythonCall = 6, Destroy = 7, Enforce = 8, - Recompute2 = 9, // set when the object is being recomputed in the second pass + Recompute2 = 9, // set when the object is being recomputed in the second pass PartialObject = 10, - PendingRecompute = 11, // set by Document, indicating the object is in recomputation queue - ObjImporting = 13, // Mark the object as importing - NoTouch = 14, // no touch on any property change - GeoExcluded = 15, // mark as a member but not claimed by GeoFeatureGroup - Expand = 16, // indicate the object's tree item expansion status - NoAutoExpand = 17, // disable tree item auto expand on selection for this object - PendingTransactionUpdate = 18, // mark that the object expects a call to onUndoRedoFinished() after transaction is finished. - RecomputeExtension = 19, // mark the object to recompute its extensions - TouchOnColorChange = 20, // inform view provider touch object on color change - Freeze = 21, // do not recompute ever + PendingRecompute = 11, // set by Document, indicating the object is in recomputation queue + ObjImporting = 13, // Mark the object as importing + NoTouch = 14, // no touch on any property change + GeoExcluded = 15, // mark as a member but not claimed by GeoFeatureGroup + Expand = 16, // indicate the object's tree item expansion status + NoAutoExpand = 17, // disable tree item auto expand on selection for this object + PendingTransactionUpdate = 18, // mark that the object expects a call to onUndoRedoFinished() after transaction is finished. + RecomputeExtension = 19, // mark the object to recompute its extensions + TouchOnColorChange = 20, // inform view provider touch object on color change + Freeze = 21, // do not recompute ever }; +// clang-format on /** Return object for feature execution -*/ + */ class AppExport DocumentObjectExecReturn { public: - explicit DocumentObjectExecReturn(const std::string& sWhy, DocumentObject* WhichObject=nullptr) - : Why(sWhy), Which(WhichObject) - { - } - explicit DocumentObjectExecReturn(const char* sWhy, DocumentObject* WhichObject=nullptr) + explicit DocumentObjectExecReturn(const std::string& sWhy, + DocumentObject* WhichObject = nullptr) + : Why(sWhy) + , Which(WhichObject) + {} + explicit DocumentObjectExecReturn(const char* sWhy, DocumentObject* WhichObject = nullptr) : Which(WhichObject) { - if (sWhy) + if (sWhy) { Why = sWhy; + } } std::string Why; @@ -91,7 +96,6 @@ class AppExport DocumentObjectExecReturn }; - /** Base class of all Classes handled in the Document */ class AppExport DocumentObject: public App::TransactionalObject @@ -99,7 +103,6 @@ class AppExport DocumentObject: public App::TransactionalObject PROPERTY_HEADER_WITH_OVERRIDE(App::DocumentObject); public: - PropertyString Label; PropertyString Label2; PropertyExpressionEngine ExpressionEngine; @@ -107,15 +110,18 @@ class AppExport DocumentObject: public App::TransactionalObject /// Allow control visibility status in App name space PropertyBool Visibility; + // clang-format off /// signal before changing a property of this object - boost::signals2::signal signalBeforeChange; + boost::signals2::signal signalBeforeChange; /// signal on changed property of this object - boost::signals2::signal signalChanged; + boost::signals2::signal signalChanged; /// signal on changed property of this object before document scoped signalChangedObject - boost::signals2::signal signalEarlyChanged; + boost::signals2::signal signalEarlyChanged; + // clang-format on /// returns the type name of the ViewProvider - virtual const char* getViewProviderName() const { + virtual const char* getViewProviderName() const + { return ""; } /** @@ -127,7 +133,8 @@ class AppExport DocumentObject: public App::TransactionalObject * If not, the view provider will be reverted to the one returned from \ref * getViewProviderName(). */ - virtual const char *getViewProviderNameOverride() const { + virtual const char* getViewProviderNameOverride() const + { return getViewProviderName(); } @@ -138,11 +145,14 @@ class AppExport DocumentObject: public App::TransactionalObject /// returns a value that uniquely identifies this DocumentObject. const char* getDagKey() const; /// returns the name which is set in the document for this object (not the name property!) - const char *getNameInDocument() const; + const char* getNameInDocument() const; /// Return the object ID that is unique within its owner document - long getID() const {return _Id;} + long getID() const + { + return _Id; + } /// returns the name that is safe to be exported to other document - std::string getExportName(bool forced=false) const; + std::string getExportName(bool forced = false) const; /// Return the object full name of the form DocName#ObjName std::string getFullName() const override; /// Return the object full label in the form DocName#ObjName @@ -150,13 +160,13 @@ class AppExport DocumentObject: public App::TransactionalObject bool isAttachedToDocument() const override; const char* detachFromDocument() override; /// gets the document in which this Object is handled - App::Document *getDocument() const; + App::Document* getDocument() const; /** Set the property touched -> changed, cause recomputation in Update() */ //@{ /// set this document object touched (cause recomputation on dependent features) - void touch(bool noRecompute=false); + void touch(bool noRecompute = false); /// test if this document object is touched bool isTouched() const; /// Enforce this document object to be recomputed @@ -164,32 +174,63 @@ class AppExport DocumentObject: public App::TransactionalObject /// Test if this document object must be recomputed bool mustRecompute() const; /// reset this document object touched - void purgeTouched() { + void purgeTouched() + { StatusBits.reset(ObjectStatus::Touch); StatusBits.reset(ObjectStatus::Enforce); - setPropertyStatus(0,false); + setPropertyStatus(0, false); } /// set this feature to error - bool isError() const {return StatusBits.test(ObjectStatus::Error);} - bool isValid() const {return !StatusBits.test(ObjectStatus::Error);} + bool isError() const + { + return StatusBits.test(ObjectStatus::Error); + } + bool isValid() const + { + return !StatusBits.test(ObjectStatus::Error); + } /// remove the error from the object - void purgeError(){StatusBits.reset(ObjectStatus::Error);} + void purgeError() + { + StatusBits.reset(ObjectStatus::Error); + } /// returns true if this objects is currently recomputing - bool isRecomputing() const {return StatusBits.test(ObjectStatus::Recompute);} + bool isRecomputing() const + { + return StatusBits.test(ObjectStatus::Recompute); + } /// returns true if this objects is currently restoring from file - bool isRestoring() const {return StatusBits.test(ObjectStatus::Restore);} + bool isRestoring() const + { + return StatusBits.test(ObjectStatus::Restore); + } /// returns true if this objects is currently removed from the document - bool isRemoving() const {return StatusBits.test(ObjectStatus::Remove);} + bool isRemoving() const + { + return StatusBits.test(ObjectStatus::Remove); + } /// set this document object freezed (prevent recomputation) void freeze(); /// set this document object unfreezed (and touch it) - void unfreeze(bool noRecompute=false); + void unfreeze(bool noRecompute = false); /// returns true if this objects is currently freezed - bool isFreezed() const {return StatusBits.test(ObjectStatus::Freeze);} + bool isFreezed() const + { + return StatusBits.test(ObjectStatus::Freeze); + } /// return the status bits - unsigned long getStatus() const {return StatusBits.to_ulong();} - bool testStatus(ObjectStatus pos) const {return StatusBits.test(size_t(pos));} - void setStatus(ObjectStatus pos, bool on) {StatusBits.set(size_t(pos), on);} + unsigned long getStatus() const + { + return StatusBits.to_ulong(); + } + bool testStatus(ObjectStatus pos) const + { + return StatusBits.test(size_t(pos)); + } + void setStatus(ObjectStatus pos, bool on) + { + StatusBits.set(size_t(pos), on); + } //@} int isExporting() const; @@ -205,14 +246,14 @@ class AppExport DocumentObject: public App::TransactionalObject * @return -1 if element visibility is not supported, 0 if element is not * found, 1 if success */ - virtual int setElementVisible(const char *element, bool visible); + virtual int setElementVisible(const char* element, bool visible); /** Get sub-element visibility * * @return -1 if element visibility is not supported or element not found, 0 * if element is invisible, or else 1 */ - virtual int isElementVisible(const char *element) const; + virtual int isElementVisible(const char* element) const; /// return true to activate tree view group object handling and element visibility virtual bool hasChildElement() const; @@ -225,7 +266,8 @@ class AppExport DocumentObject: public App::TransactionalObject */ //@{ /// OutList options - enum OutListOption { + enum OutListOption + { /// Do not include link from expression engine OutListNoExpression = 1, /// Do not hide any link (i.e. include links with LinkScopeHidden) @@ -234,9 +276,9 @@ class AppExport DocumentObject: public App::TransactionalObject OutListNoXLinked = 4, }; /// returns a list of objects this object is pointing to by Links - const std::vector &getOutList() const; + const std::vector& getOutList() const; std::vector getOutList(int option) const; - void getOutList(int option, std::vector &res) const; + void getOutList(int option, std::vector& res) const; /// returns a list of objects linked by the property std::vector getOutListOfProperty(App::Property*) const; @@ -245,15 +287,15 @@ class AppExport DocumentObject: public App::TransactionalObject /// clear internal out list cache void clearOutListCache() const; /// get all possible paths from this to another object following the OutList - std::vector > getPathsByOutList(App::DocumentObject* to) const; + std::vector> getPathsByOutList(App::DocumentObject* to) const; #ifdef USE_OLD_DAG /// get all objects link to this object std::vector getInList(void) const #else - const std::vector &getInList() const; + const std::vector& getInList() const; #endif - /// get all objects link directly or indirectly to this object - std::vector getInListRecursive() const; + /// get all objects link directly or indirectly to this object + std::vector getInListRecursive() const; /** Get a set of all objects linking to this object, including possible external parent objects * * @param inSet [out]: a set containing all objects linking to this object. @@ -261,9 +303,11 @@ class AppExport DocumentObject: public App::TransactionalObject * @param inList [in, out]: optional pointer to a vector holding the output * objects, with the furthest linking object ordered last. */ - void getInListEx(std::set &inSet, - bool recursive, std::vector *inList=nullptr) const; - /** Return a set of all objects linking to this object, including possible external parent objects + void getInListEx(std::set& inSet, + bool recursive, + std::vector* inList = nullptr) const; + /** Return a set of all objects linking to this object, including possible external parent + * objects * @param recursive [in]: whether to obtain recursive in list */ std::set getInListEx(bool recursive) const; @@ -296,9 +340,9 @@ class AppExport DocumentObject: public App::TransactionalObject * That is, if the return is true, the link is allowed. */ bool testIfLinkDAGCompatible(DocumentObject* linkTo) const; - bool testIfLinkDAGCompatible(const std::vector &linksTo) const; - bool testIfLinkDAGCompatible(App::PropertyLinkSubList &linksTo) const; - bool testIfLinkDAGCompatible(App::PropertyLinkSub &linkTo) const; + bool testIfLinkDAGCompatible(const std::vector& linksTo) const; + bool testIfLinkDAGCompatible(App::PropertyLinkSubList& linksTo) const; + bool testIfLinkDAGCompatible(App::PropertyLinkSub& linkTo) const; /** Return the element map version of the geometry data stored in the given property * @@ -309,10 +353,11 @@ class AppExport DocumentObject: public App::TransactionalObject * * @return Return the element map version string. */ - virtual std::string getElementMapVersion(const App::Property *prop, bool restored=false) const; + virtual std::string getElementMapVersion(const App::Property* prop, + bool restored = false) const; /// Return true to signal re-generation of geometry element names - virtual bool checkElementMapVersion(const App::Property *prop, const char *ver) const; + virtual bool checkElementMapVersion(const App::Property* prop, const char* ver) const; public: /** mustExecute @@ -332,10 +377,10 @@ class AppExport DocumentObject: public App::TransactionalObject * * @param recursive: set to true to recompute any dependent objects as well */ - bool recomputeFeature(bool recursive=false); + bool recomputeFeature(bool recursive = false); /// get the status Message - const char *getStatusString() const; + const char* getStatusString() const; /** Called in case of losing a link * Get called by the document when a object got deleted a link property of this @@ -344,7 +389,7 @@ class AppExport DocumentObject: public App::TransactionalObject * additional or different behavior. */ virtual void onLostLinkToObject(DocumentObject*); - PyObject *getPyObject() override; + PyObject* getPyObject() override; /** Get the sub element/object by name * @@ -374,8 +419,11 @@ class AppExport DocumentObject: public App::TransactionalObject * then it shall return itself. If subname is invalid, then it shall return * zero. */ - virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj=nullptr, - Base::Matrix4D *mat=nullptr, bool transform=true, int depth=0) const; + virtual DocumentObject* getSubObject(const char* subname, + PyObject** pyObj = nullptr, + Base::Matrix4D* mat = nullptr, + bool transform = true, + int depth = 0) const; /** Return a list of objects referenced by a given subname including this object * @param subname: the sub name path @@ -391,7 +439,8 @@ class AppExport DocumentObject: public App::TransactionalObject bool flatten = false) const; /// reason of calling getSubObjects() - enum GSReason { + enum GSReason + { /// default, mostly for exporting shape objects GS_DEFAULT, /// for element selection @@ -413,10 +462,10 @@ class AppExport DocumentObject: public App::TransactionalObject * need special transformation. For example, sub objects of an array type * of object. */ - virtual std::vector getSubObjects(int reason=0) const; + virtual std::vector getSubObjects(int reason = 0) const; - ///Obtain top parents and subnames of this object using its InList - std::vector > getParents(int depth=0) const; + /// Obtain top parents and subnames of this object using its InList + std::vector> getParents(int depth = 0) const; /// Obtain the first parent group of this object App::DocumentObject* getFirstParent() const; @@ -436,20 +485,34 @@ class AppExport DocumentObject: public App::TransactionalObject * @return Return the linked object. This function must return itself if the * it is not a link or the link is invalid. */ - virtual DocumentObject *getLinkedObject(bool recurse=true, - Base::Matrix4D *mat=nullptr, bool transform=false, int depth=0) const; + virtual DocumentObject* getLinkedObject(bool recurse = true, + Base::Matrix4D* mat = nullptr, + bool transform = false, + int depth = 0) const; /* Return true to cause PropertyView to show linked object's property */ - virtual bool canLinkProperties() const {return true;} + virtual bool canLinkProperties() const + { + return true; + } /* Return whether this object is a link */ - virtual bool isLink() const {return false;}; + virtual bool isLink() const + { + return false; + } /* Return whether this object is a link group */ - virtual bool isLinkGroup() const {return false;}; + virtual bool isLinkGroup() const + { + return false; + } /* Return true to bypass duplicate label checking */ - virtual bool allowDuplicateLabel() const {return false;} + virtual bool allowDuplicateLabel() const + { + return false; + } /*** Called to let object itself control relabeling * @@ -457,38 +520,50 @@ class AppExport DocumentObject: public App::TransactionalObject * * This function is called before onBeforeChange() */ - virtual void onBeforeChangeLabel(std::string &newLabel) {(void)newLabel;} + virtual void onBeforeChangeLabel(std::string& newLabel) + { + (void)newLabel; + } friend class Document; friend class Transaction; friend class ObjectExecution; - static DocumentObjectExecReturn *StdReturn; + static DocumentObjectExecReturn* StdReturn; - void Save (Base::Writer &writer) const override; + void Save(Base::Writer& writer) const override; /* Expression support */ - virtual void setExpression(const ObjectIdentifier & path, std::shared_ptr expr); + virtual void setExpression(const ObjectIdentifier& path, std::shared_ptr expr); - void clearExpression(const ObjectIdentifier & path); + void clearExpression(const ObjectIdentifier& path); - virtual const PropertyExpressionEngine::ExpressionInfo getExpression(const ObjectIdentifier &path) const; + virtual const PropertyExpressionEngine::ExpressionInfo + getExpression(const ObjectIdentifier& path) const; - virtual void renameObjectIdentifiers(const std::map & paths); + virtual void + renameObjectIdentifiers(const std::map& paths); - const std::string & getOldLabel() const { return oldLabel; } + const std::string& getOldLabel() const + { + return oldLabel; + } - const char *getViewProviderNameStored() const { + const char* getViewProviderNameStored() const + { return _pcViewProviderName.c_str(); } bool removeDynamicProperty(const char* prop) override; - App::Property* addDynamicProperty( - const char* type, const char* name=nullptr, - const char* group=nullptr, const char* doc=nullptr, - short attr=0, bool ro=false, bool hidden=false) override; + App::Property* addDynamicProperty(const char* type, + const char* name = nullptr, + const char* group = nullptr, + const char* doc = nullptr, + short attr = 0, + bool ro = false, + bool hidden = false) override; /** Resolve the last document object referenced in the subname * @@ -502,9 +577,14 @@ class AppExport DocumentObject: public App::TransactionalObject * @return Returns the last referenced document object in the subname. If no * such object in subname, return pObject. */ - App::DocumentObject *resolve(const char *subname, App::DocumentObject **parent=nullptr, - std::string *childName=nullptr, const char **subElement=nullptr, - PyObject **pyObj=nullptr, Base::Matrix4D *mat=nullptr, bool transform=true, int depth=0) const; + App::DocumentObject* resolve(const char* subname, + App::DocumentObject** parent = nullptr, + std::string* childName = nullptr, + const char** subElement = nullptr, + PyObject** pyObj = nullptr, + Base::Matrix4D* mat = nullptr, + bool transform = true, + int depth = 0) const; /** Resolve a link reference that is relative to this object reference * @@ -550,8 +630,9 @@ class AppExport DocumentObject: public App::TransactionalObject * * The common parent 'Group' is removed. */ - App::DocumentObject *resolveRelativeLink(std::string &subname, - App::DocumentObject *&link, std::string &linkSub) const; + App::DocumentObject* resolveRelativeLink(std::string& subname, + App::DocumentObject*& link, + std::string& linkSub) const; /** Called to adjust link properties to avoid cyclic links * @@ -567,8 +648,8 @@ class AppExport DocumentObject: public App::TransactionalObject * properties that can hold subnames) to avoid cyclic when added to the * future parent. */ - virtual bool adjustRelativeLinks(const std::set &inList, - std::set *visited=nullptr); + virtual bool adjustRelativeLinks(const std::set& inList, + std::set* visited = nullptr); /** allow partial loading of dependent objects * @@ -576,9 +657,13 @@ class AppExport DocumentObject: public App::TransactionalObject * dependent objects to be partially loaded, i.e. only create, but not * restored. 2 means this object itself can be partially loaded. */ - virtual int canLoadPartial() const {return 0;} + virtual int canLoadPartial() const + { + return 0; + } - virtual void onUpdateElementReference(const Property *) {} + virtual void onUpdateElementReference(const Property*) + {} /** Allow object to redirect a subname path * @@ -593,34 +678,34 @@ class AppExport DocumentObject: public App::TransactionalObject * item is selected in the tree. Document object can use this function to * redirect the selection to some other objects. */ - virtual bool redirectSubName(std::ostringstream &ss, - DocumentObject *topParent, DocumentObject *child) const; + virtual bool + redirectSubName(std::ostringstream& ss, DocumentObject* topParent, DocumentObject* child) const; /** Special marker to mark the object as hidden * * It is used by Gui::ViewProvider::getElementColors(), but exposed here * for convenience */ - static const std::string &hiddenMarker(); + static const std::string& hiddenMarker(); /// Check if the subname reference ends with hidden marker. - static const char *hasHiddenMarker(const char *subname); + static const char* hasHiddenMarker(const char* subname); protected: /// recompute only this object - virtual App::DocumentObjectExecReturn *recompute(); + virtual App::DocumentObjectExecReturn* recompute(); /** get called by the document to recompute this feature - * Normally this method get called in the processing of - * Document::recompute(). - * In execute() the output properties get recomputed - * with the data from linked objects and objects own - * properties. - */ - virtual App::DocumentObjectExecReturn *execute(); + * Normally this method get called in the processing of + * Document::recompute(). + * In execute() the output properties get recomputed + * with the data from linked objects and objects own + * properties. + */ + virtual App::DocumentObjectExecReturn* execute(); /** * Executes the extensions of a document object. */ - App::DocumentObjectExecReturn *executeExtensions(); + App::DocumentObjectExecReturn* executeExtensions(); /** Status bits of the document object * The first 8 bits are used for the base system the rest can be used in @@ -638,8 +723,14 @@ class AppExport DocumentObject: public App::TransactionalObject */ std::bitset<32> StatusBits; - void setError(){StatusBits.set(ObjectStatus::Error);} - void resetError(){StatusBits.reset(ObjectStatus::Error);} + void setError() + { + StatusBits.set(ObjectStatus::Error); + } + void resetError() + { + StatusBits.reset(ObjectStatus::Error); + } void setDocument(App::Document* doc); /// get called before the value is changed @@ -660,39 +751,40 @@ class AppExport DocumentObject: public App::TransactionalObject virtual void unsetupObject(); /// get called when a property status has changed - void onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) override; + void onPropertyStatusChanged(const Property& prop, unsigned long oldStatus) override; private: void printInvalidLinks() const; - /// python object of this class and all descendent -protected: // attributes + /// python object of this class and all descendent +protected: // attributes Py::SmartPtr PythonObject; /// pointer to the document this object belongs to - App::Document* _pDoc{nullptr}; + App::Document* _pDoc {nullptr}; /// Old label; used for renaming expressions std::string oldLabel; // pointer to the document name string (for performance) - const std::string *pcNameInDocument{nullptr}; + const std::string* pcNameInDocument {nullptr}; private: // accessed by App::Document to record and restore the correct view provider type std::string _pcViewProviderName; // unique identifier (among a document) of this object. - long _Id{0}; + long _Id {0}; private: // Back pointer to all the fathers in a DAG of the document // this is used by the document (via friend) to have a effective DAG handling std::vector _inList; - mutable std::vector _outList; - mutable std::unordered_map _outListMap; + mutable std::vector _outList; + mutable std::unordered_map + _outListMap; mutable bool _outListCached = false; }; -} //namespace App +} // namespace App -#endif // APP_DOCUMENTOBJECT_H +#endif // APP_DOCUMENTOBJECT_H diff --git a/src/App/ExpressionParser.h b/src/App/ExpressionParser.h index 4535e64719f7..3836d64a99ac 100644 --- a/src/App/ExpressionParser.h +++ b/src/App/ExpressionParser.h @@ -30,7 +30,8 @@ #include #include -namespace App { +namespace App +{ //////////////////////////////////////////////////////////////////////////////////// // Expecting the extended expression is going to be constantly amended (to @@ -39,67 +40,87 @@ namespace App { // included by everyone /////////////////////////////////////////////////////////////////////////////////// -struct AppExport Expression::Component { +struct AppExport Expression::Component +{ ObjectIdentifier::Component comp; Expression* e1; Expression* e2; Expression* e3; - explicit Component(const std::string &n); - Component(Expression *e1, Expression *e2, Expression *e3, bool isRange=false); - explicit Component(const ObjectIdentifier::Component &comp); - Component(const Component &other); + explicit Component(const std::string& n); + Component(Expression* e1, Expression* e2, Expression* e3, bool isRange = false); + explicit Component(const ObjectIdentifier::Component& comp); + Component(const Component& other); ~Component(); - Component &operator=(const Component &)=delete; + Component& operator=(const Component&) = delete; - void visit(ExpressionVisitor &v); + void visit(ExpressionVisitor& v); bool isTouched() const; - void toString(std::ostream &ss, bool persistent) const; - Component *copy() const; - Component *eval() const; + void toString(std::ostream& ss, bool persistent) const; + Component* copy() const; + Component* eval() const; - Py::Object get(const Expression *owner, const Py::Object &pyobj) const; - void set(const Expression *owner, Py::Object &pyobj, const Py::Object &value) const; - void del(const Expression *owner, Py::Object &pyobj) const; + Py::Object get(const Expression* owner, const Py::Object& pyobj) const; + void set(const Expression* owner, Py::Object& pyobj, const Py::Object& value) const; + void del(const Expression* owner, Py::Object& pyobj) const; }; //////////////////////////////////////////////////////////////////////////////////// /** - * Part of an expressions that contains a unit. - * - */ + * Part of an expressions that contains a unit. + * + */ -class AppExport UnitExpression : public Expression { +class AppExport UnitExpression: public Expression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit UnitExpression(const App::DocumentObject *_owner = nullptr, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string()); + explicit UnitExpression(const App::DocumentObject* _owner = nullptr, + const Base::Quantity& _quantity = Base::Quantity(), + const std::string& _unitStr = std::string()); ~UnitExpression() override; - Expression * simplify() const override; + Expression* simplify() const override; - void setUnit(const Base::Quantity &_quantity); + void setUnit(const Base::Quantity& _quantity); - void setQuantity(const Base::Quantity &_quantity); + void setQuantity(const Base::Quantity& _quantity); - double getValue() const { return quantity.getValue(); } + double getValue() const + { + return quantity.getValue(); + } - const Base::Unit & getUnit() const { return quantity.getUnit(); } + const Base::Unit& getUnit() const + { + return quantity.getUnit(); + } - const Base::Quantity & getQuantity() const { return quantity; } + const Base::Quantity& getQuantity() const + { + return quantity; + } - const std::string getUnitString() const { return unitStr; } + const std::string getUnitString() const + { + return unitStr; + } - double getScaler() const { return quantity.getValue(); } + double getScaler() const + { + return quantity.getValue(); + } protected: - Expression * _copy() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Py::Object _getPyValue() const override; protected: - mutable PyObject *cache = nullptr; + mutable PyObject* cache = nullptr; private: Base::Quantity quantity; @@ -107,54 +128,65 @@ class AppExport UnitExpression : public Expression { }; /** - * Class implementing a number with an optional unit - */ + * Class implementing a number with an optional unit + */ -class AppExport NumberExpression : public UnitExpression { +class AppExport NumberExpression: public UnitExpression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit NumberExpression(const App::DocumentObject *_owner = nullptr, const Base::Quantity & quantity = Base::Quantity()); + explicit NumberExpression(const App::DocumentObject* _owner = nullptr, + const Base::Quantity& quantity = Base::Quantity()); - Expression * simplify() const override; + Expression* simplify() const override; void negate(); - bool isInteger(long *v=nullptr) const; + bool isInteger(long* v = nullptr) const; protected: - Expression * _copy() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; }; -class AppExport ConstantExpression : public NumberExpression { +class AppExport ConstantExpression: public NumberExpression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit ConstantExpression(const App::DocumentObject *_owner = nullptr, - const char *_name = "", - const Base::Quantity &_quantity = Base::Quantity()); + explicit ConstantExpression(const App::DocumentObject* _owner = nullptr, + const char* _name = "", + const Base::Quantity& _quantity = Base::Quantity()); - std::string getName() const { return name; } + std::string getName() const + { + return name; + } bool isNumber() const; protected: Py::Object _getPyValue() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Expression* _copy() const override; protected: - const char *name; + const char* name; }; /** - * Class implementing an infix expression. - * - */ + * Class implementing an infix expression. + * + */ -class AppExport OperatorExpression : public UnitExpression { +class AppExport OperatorExpression: public UnitExpression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - enum Operator { + enum Operator + { NONE, ADD, SUB, @@ -172,30 +204,42 @@ class AppExport OperatorExpression : public UnitExpression { NEG, POS }; - explicit OperatorExpression(const App::DocumentObject *_owner = nullptr, Expression * _left = nullptr, Operator _op = NONE, Expression * _right = nullptr); + explicit OperatorExpression(const App::DocumentObject* _owner = nullptr, + Expression* _left = nullptr, + Operator _op = NONE, + Expression* _right = nullptr); ~OperatorExpression() override; bool isTouched() const override; - Expression * simplify() const override; + Expression* simplify() const override; int priority() const override; - Operator getOperator() const { return op; } + Operator getOperator() const + { + return op; + } - Expression * getLeft() const { return left; } + Expression* getLeft() const + { + return left; + } - Expression * getRight() const { return right; } + Expression* getRight() const + { + return right; + } protected: - Expression * _copy() const override; + Expression* _copy() const override; Py::Object _getPyValue() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; - void _visit(ExpressionVisitor & v) override; + void _visit(ExpressionVisitor& v) override; virtual bool isCommutative() const; @@ -203,46 +247,53 @@ class AppExport OperatorExpression : public UnitExpression { virtual bool isRightAssociative() const; - Operator op; /**< Operator working on left and right */ - Expression * left; /**< Left operand */ - Expression * right; /**< Right operand */ + Operator op; /**< Operator working on left and right */ + Expression* left; /**< Left operand */ + Expression* right; /**< Right operand */ }; -class AppExport ConditionalExpression : public Expression { +class AppExport ConditionalExpression: public Expression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit ConditionalExpression(const App::DocumentObject *_owner = nullptr, Expression * _condition = nullptr,Expression * _trueExpr = nullptr, Expression * _falseExpr = nullptr); + explicit ConditionalExpression(const App::DocumentObject* _owner = nullptr, + Expression* _condition = nullptr, + Expression* _trueExpr = nullptr, + Expression* _falseExpr = nullptr); ~ConditionalExpression() override; bool isTouched() const override; - Expression * simplify() const override; + Expression* simplify() const override; int priority() const override; protected: - Expression * _copy() const override; - void _visit(ExpressionVisitor & v) override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _visit(ExpressionVisitor& v) override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Py::Object _getPyValue() const override; protected: - - Expression * condition; /**< Condition */ - Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */ - Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */ + Expression* condition; /**< Condition */ + Expression* trueExpr; /**< Expression if abs(condition) is > 0.5 */ + Expression* falseExpr; /**< Expression if abs(condition) is < 0.5 */ }; /** - * Class implementing various functions, e.g sin, cos, etc. - * - */ + * Class implementing various functions, e.g sin, cos, etc. + * + */ -class AppExport FunctionExpression : public UnitExpression { +class AppExport FunctionExpression: public UnitExpression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - enum Function { + enum Function + { NONE, // Normal functions taking one or two arguments @@ -287,31 +338,32 @@ class AppExport FunctionExpression : public UnitExpression { VSCALEZ, // Matrix - MINVERT, // invert matrix/placement/rotation - MROTATE, // Rotate matrix/placement/rotation around axis, by rotation object, or by euler angles. - MROTATEX, // Rotate matrix/placement/rotation around x-axis. - MROTATEY, // Rotate matrix/placement/rotation around y-axis. - MROTATEZ, // Rotate matrix/placement/rotation around z-axis. - MSCALE, // matrix scale by vector - MTRANSLATE, // Translate matrix/placement. + MINVERT, // invert matrix/placement/rotation + MROTATE, // Rotate matrix/placement/rotation around axis, by rotation object, or by euler + // angles. + MROTATEX, // Rotate matrix/placement/rotation around x-axis. + MROTATEY, // Rotate matrix/placement/rotation around y-axis. + MROTATEZ, // Rotate matrix/placement/rotation around z-axis. + MSCALE, // matrix scale by vector + MTRANSLATE, // Translate matrix/placement. // Object creation - CREATE, // Create new object of a given type. - LIST, // Create Python list. - MATRIX, // Create matrix object. - PLACEMENT, // Create placement object. - ROTATION, // Create rotation object. - ROTATIONX, // Create x-axis rotation object. - ROTATIONY, // Create y-axis rotation object. - ROTATIONZ, // Create z-axis rotation object. - STR, // stringify - PARSEQUANT, // parse string quantity - TRANSLATIONM, // Create translation matrix object. - TUPLE, // Create Python tuple. - VECTOR, // Create vector object. - - HIDDENREF, // hidden reference that has no dependency check - HREF, // deprecated alias of HIDDENREF + CREATE, // Create new object of a given type. + LIST, // Create Python list. + MATRIX, // Create matrix object. + PLACEMENT, // Create placement object. + ROTATION, // Create rotation object. + ROTATIONX, // Create x-axis rotation object. + ROTATIONY, // Create y-axis rotation object. + ROTATIONZ, // Create z-axis rotation object. + STR, // stringify + PARSEQUANT, // parse string quantity + TRANSLATIONM, // Create translation matrix object. + TUPLE, // Create Python tuple. + VECTOR, // Create vector object. + + HIDDENREF, // hidden reference that has no dependency check + HREF, // deprecated alias of HIDDENREF // Aggregates AGGREGATES, @@ -327,219 +379,273 @@ class AppExport FunctionExpression : public UnitExpression { LAST, }; - explicit FunctionExpression(const App::DocumentObject *_owner = nullptr, Function _f = NONE, - std::string &&name = std::string(), std::vector _args = std::vector()); + explicit FunctionExpression(const App::DocumentObject* _owner = nullptr, + Function _f = NONE, + std::string&& name = std::string(), + std::vector _args = std::vector()); ~FunctionExpression() override; bool isTouched() const override; - Expression * simplify() const override; + Expression* simplify() const override; - static Py::Object evaluate(const Expression *owner, int type, const std::vector &args); + static Py::Object + evaluate(const Expression* owner, int type, const std::vector& args); - Function getFunction() const {return f;} - const std::vector &getArgs() const {return args;} + Function getFunction() const + { + return f; + } + const std::vector& getArgs() const + { + return args; + } protected: - static Py::Object evalAggregate(const Expression *owner, int type, const std::vector &args); - static Base::Vector3d evaluateSecondVectorArgument(const Expression *expression, const std::vector &arguments); - static double extractLengthValueArgument(const Expression *expression, const std::vector &arguments, int argumentIndex); - static Base::Vector3d extractVectorArgument(const Expression *expression, const std::vector &arguments, int argumentIndex); - static void initialiseObject(const Py::Object *object, const std::vector &arguments, const unsigned long offset = 0); - static Py::Object transformFirstArgument( - const Expression *expression, - const std::vector &arguments, - const Base::Matrix4D *transformationMatrix); + static Py::Object + evalAggregate(const Expression* owner, int type, const std::vector& args); + static Base::Vector3d evaluateSecondVectorArgument(const Expression* expression, + const std::vector& arguments); + static double extractLengthValueArgument(const Expression* expression, + const std::vector& arguments, + int argumentIndex); + static Base::Vector3d extractVectorArgument(const Expression* expression, + const std::vector& arguments, + int argumentIndex); + static void initialiseObject(const Py::Object* object, + const std::vector& arguments, + const unsigned long offset = 0); + static Py::Object transformFirstArgument(const Expression* expression, + const std::vector& arguments, + const Base::Matrix4D* transformationMatrix); static Py::Object translationMatrix(double x, double y, double z); Py::Object _getPyValue() const override; - Expression * _copy() const override; - void _visit(ExpressionVisitor & v) override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _visit(ExpressionVisitor& v) override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; - Function f; /**< Function to execute */ + Function f; /**< Function to execute */ std::string fname; - std::vector args; /** Arguments to function*/ + std::vector args; /** Arguments to function*/ }; /** - * Class implementing a reference to a property. If the name is unqualified, - * the owner of the expression is searched. If it is qualified, the document - * that contains the owning document object is searched for other document - * objects to search. Both labels and internal document names are searched. - * - */ - -class AppExport VariableExpression : public UnitExpression { + * Class implementing a reference to a property. If the name is unqualified, + * the owner of the expression is searched. If it is qualified, the document + * that contains the owning document object is searched for other document + * objects to search. Both labels and internal document names are searched. + * + */ + +class AppExport VariableExpression: public UnitExpression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit VariableExpression(const App::DocumentObject *_owner = nullptr, const ObjectIdentifier& _var = ObjectIdentifier()); + explicit VariableExpression(const App::DocumentObject* _owner = nullptr, + const ObjectIdentifier& _var = ObjectIdentifier()); ~VariableExpression() override; bool isTouched() const override; - Expression * simplify() const override; + Expression* simplify() const override; - std::string name() const { return var.getPropertyName(); } + std::string name() const + { + return var.getPropertyName(); + } - ObjectIdentifier getPath() const { return var; } + ObjectIdentifier getPath() const + { + return var; + } - void setPath(const ObjectIdentifier & path); + void setPath(const ObjectIdentifier& path); - const App::Property *getProperty() const; + const App::Property* getProperty() const; void addComponent(Component* component) override; protected: - Expression * _copy() const override; + Expression* _copy() const override; Py::Object _getPyValue() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; bool _isIndexable() const override; - void _getIdentifiers(std::map &) const override; - bool _adjustLinks(const std::set &, ExpressionVisitor &) override; - void _importSubNames(const ObjectIdentifier::SubNameMap &) override; - void _updateLabelReference(App::DocumentObject *, const std::string &, const char *) override; - bool _updateElementReference(App::DocumentObject *,bool,ExpressionVisitor &) override; - bool _relabeledDocument(const std::string &, const std::string &, ExpressionVisitor &) override; - bool _renameObjectIdentifier(const std::map &, - const ObjectIdentifier &, ExpressionVisitor &) override; - void _collectReplacement(std::map &, - const App::DocumentObject *parent, App::DocumentObject *oldObj, - App::DocumentObject *newObj) const override; - void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override; - void _offsetCells(int, int, ExpressionVisitor &) override; + void _getIdentifiers(std::map&) const override; + bool _adjustLinks(const std::set&, ExpressionVisitor&) override; + void _importSubNames(const ObjectIdentifier::SubNameMap&) override; + void _updateLabelReference(App::DocumentObject*, const std::string&, const char*) override; + bool _updateElementReference(App::DocumentObject*, bool, ExpressionVisitor&) override; + bool _relabeledDocument(const std::string&, const std::string&, ExpressionVisitor&) override; + bool _renameObjectIdentifier(const std::map&, + const ObjectIdentifier&, + ExpressionVisitor&) override; + void _collectReplacement(std::map&, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; + void _moveCells(const CellAddress&, int, int, ExpressionVisitor&) override; + void _offsetCells(int, int, ExpressionVisitor&) override; protected: - ObjectIdentifier var; /**< Variable name */ }; ////////////////////////////////////////////////////////////////////// -class AppExport PyObjectExpression : public Expression { +class AppExport PyObjectExpression: public Expression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - explicit PyObjectExpression(const App::DocumentObject *_owner=nullptr, PyObject *pyobj=nullptr, bool owned=false) - :Expression(_owner) + explicit PyObjectExpression(const App::DocumentObject* _owner = nullptr, + PyObject* pyobj = nullptr, + bool owned = false) + : Expression(_owner) { - setPyValue(pyobj,owned); + setPyValue(pyobj, owned); } ~PyObjectExpression() override; void setPyValue(Py::Object pyobj); - void setPyValue(PyObject *pyobj, bool owned=false); - Expression * simplify() const override { return copy(); } + void setPyValue(PyObject* pyobj, bool owned = false); + Expression* simplify() const override + { + return copy(); + } protected: Expression* _copy() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Py::Object _getPyValue() const override; protected: - PyObject *pyObj = nullptr; + PyObject* pyObj = nullptr; }; /** - * Class implementing a string. Used to signal either a genuine string or - * a failed evaluation of an expression. - */ + * Class implementing a string. Used to signal either a genuine string or + * a failed evaluation of an expression. + */ -class AppExport StringExpression : public Expression { +class AppExport StringExpression: public Expression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit StringExpression(const App::DocumentObject *_owner = nullptr, const std::string & _text = std::string()); + explicit StringExpression(const App::DocumentObject* _owner = nullptr, + const std::string& _text = std::string()); ~StringExpression() override; - Expression * simplify() const override; + Expression* simplify() const override; + + virtual std::string getText() const + { + return text; + } - virtual std::string getText() const { return text; } protected: - Expression * _copy() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Py::Object _getPyValue() const override; - bool _isIndexable() const override { return true; } + bool _isIndexable() const override + { + return true; + } private: std::string text; /**< Text string */ - mutable PyObject *cache = nullptr; + mutable PyObject* cache = nullptr; }; -class AppExport RangeExpression : public App::Expression { +class AppExport RangeExpression: public App::Expression +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - explicit RangeExpression(const App::DocumentObject * _owner = nullptr, const std::string & begin = std::string(), const std::string & end = std::string()); + explicit RangeExpression(const App::DocumentObject* _owner = nullptr, + const std::string& begin = std::string(), + const std::string& end = std::string()); ~RangeExpression() override = default; bool isTouched() const override; - App::Expression * simplify() const override; + App::Expression* simplify() const override; Range getRange() const; protected: - Expression * _copy() const override; - void _toString(std::ostream &ss, bool persistent, int indent) const override; + Expression* _copy() const override; + void _toString(std::ostream& ss, bool persistent, int indent) const override; Py::Object _getPyValue() const override; - void _getIdentifiers(std::map &) const override; - bool _renameObjectIdentifier(const std::map &, - const ObjectIdentifier &, ExpressionVisitor &) override; - void _moveCells(const CellAddress &, int, int, ExpressionVisitor &) override; - void _offsetCells(int, int, ExpressionVisitor &) override; + void _getIdentifiers(std::map&) const override; + bool _renameObjectIdentifier(const std::map&, + const ObjectIdentifier&, + ExpressionVisitor&) override; + void _moveCells(const CellAddress&, int, int, ExpressionVisitor&) override; + void _offsetCells(int, int, ExpressionVisitor&) override; protected: std::string begin; std::string end; }; -namespace ExpressionParser { -AppExport Expression * parse(const App::DocumentObject *owner, const char *buffer); -AppExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer); -AppExport ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer); -AppExport bool isTokenAnIndentifier(const std::string & str); -AppExport bool isTokenAConstant(const std::string & str); -AppExport bool isTokenAUnit(const std::string & str); -AppExport std::vector > tokenize(const std::string & str); +namespace ExpressionParser +{ +AppExport Expression* parse(const App::DocumentObject* owner, const char* buffer); +AppExport UnitExpression* parseUnit(const App::DocumentObject* owner, const char* buffer); +AppExport ObjectIdentifier parsePath(const App::DocumentObject* owner, const char* buffer); +AppExport bool isTokenAnIndentifier(const std::string& str); +AppExport bool isTokenAConstant(const std::string& str); +AppExport bool isTokenAUnit(const std::string& str); +AppExport std::vector> tokenize(const std::string& str); /// Convenient class to mark begin of importing -class AppExport ExpressionImporter { +class AppExport ExpressionImporter +{ public: - explicit ExpressionImporter(Base::XMLReader &reader); + explicit ExpressionImporter(Base::XMLReader& reader); ~ExpressionImporter(); - static Base::XMLReader *reader(); + static Base::XMLReader* reader(); }; -AppExport bool isModuleImported(PyObject *); +AppExport bool isModuleImported(PyObject*); /** * @brief The semantic_type class encapsulates the value in the parse tree during parsing. */ -class semantic_type { +class semantic_type +{ public: - struct { - Base::Quantity scaler; - std::string unitStr; - } quantity; - Expression::Component *component{nullptr}; - Expression * expr{nullptr}; - ObjectIdentifier path; - std::deque components; - long long int ivalue{0}; - double fvalue{0}; - struct { - const char *name = ""; - double fvalue = 0; - } constant; - std::vector arguments; - std::vector list; - std::string string; - std::pair func; - ObjectIdentifier::String string_or_identifier; - semantic_type() : func({FunctionExpression::NONE, std::string()}) {} + struct + { + Base::Quantity scaler; + std::string unitStr; + } quantity; + Expression::Component* component {nullptr}; + Expression* expr {nullptr}; + ObjectIdentifier path; + std::deque components; + long long int ivalue {0}; + double fvalue {0}; + struct + { + const char* name = ""; + double fvalue = 0; + } constant; + std::vector arguments; + std::vector list; + std::string string; + std::pair func; + ObjectIdentifier::String string_or_identifier; + semantic_type() + : func({FunctionExpression::NONE, std::string()}) + {} }; #define YYSTYPE semantic_type @@ -547,8 +653,8 @@ class semantic_type { #undef YYTOKENTYPE #undef YYSTYPE #undef YYSTYPE_ISDECLARED -} +} // namespace ExpressionParser -} +} // namespace App -#endif //EXPRESSION_PARSER_H +#endif // EXPRESSION_PARSER_H diff --git a/src/App/ExpressionTokenizer.cpp b/src/App/ExpressionTokenizer.cpp index 57e5bea07c45..aefa56c61f20 100644 --- a/src/App/ExpressionTokenizer.cpp +++ b/src/App/ExpressionTokenizer.cpp @@ -44,16 +44,16 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) std::vector> result = ExpressionParser::tokenize(expr.toStdString()); std::vector> tokens; - std::transform(result.cbegin(), - result.cend(), - std::back_inserter(tokens), - [&](const std::tuple& item) { - return std::make_tuple( - std::get<0>(item), - QString::fromStdString(expr.toStdString().substr(0, std::get<1>(item))).size(), - QString::fromStdString(std::get<2>(item)) - ); - }); + std::transform( + result.cbegin(), + result.cend(), + std::back_inserter(tokens), + [&](const std::tuple& item) { + return std::make_tuple( + std::get<0>(item), + QString::fromStdString(expr.toStdString().substr(0, std::get<1>(item))).size(), + QString::fromStdString(std::get<2>(item))); + }); return tokens; }; @@ -63,7 +63,7 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) int start = (prefix.size() > 0 && prefix.at(0) == QChar::fromLatin1('=')) ? 1 : 0; // Tokenize prefix - std::vector > tokens = tokenizeExpression(prefix.mid(start)); + std::vector> tokens = tokenizeExpression(prefix.mid(start)); // No tokens if (tokens.empty()) { @@ -78,8 +78,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) if (std::get<1>(*it) >= pos) { // Include the immediately followed '.' or '#', because we'll be // inserting these separators too, in ExpressionCompleteModel::pathFromIndex() - if (it != tokens.begin() && std::get<0>(*it) != '.' && std::get<0>(*it) != '#') + if (it != tokens.begin() && std::get<0>(*it) != '.' && std::get<0>(*it) != '#') { it = it - 1; + } tokens.resize(it - tokens.begin() + 1); prefixEnd = start + std::get<1>(*it) + (int)std::get<2>(*it).size(); break; @@ -87,8 +88,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) } int trim = 0; - if (prefixEnd > pos) + if (prefixEnd > pos) { trim = prefixEnd - pos; + } // Extract last tokens that can be rebuilt to a variable long i = static_cast(tokens.size()) - 1; @@ -111,9 +113,8 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) } // Not an unclosed string and the last character is a space - if (!stringing && !prefix.isEmpty() && - prefixEnd > 0 && prefixEnd <= prefix.size() && - prefix[prefixEnd-1] == QChar(32)) { + if (!stringing && !prefix.isEmpty() && prefixEnd > 0 && prefixEnd <= prefix.size() + && prefix[prefixEnd - 1] == QChar(32)) { return {}; } @@ -121,23 +122,22 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) i = static_cast(tokens.size()) - 1; for (; i >= 0; --i) { int token = std::get<0>(tokens[i]); - if (token != '.' && - token != '#' && - token != ExpressionParser::IDENTIFIER && - token != ExpressionParser::INTEGER && - token != ExpressionParser::STRING && - token != ExpressionParser::UNIT && - token != ExpressionParser::ONE) + if (token != '.' && token != '#' && token != ExpressionParser::IDENTIFIER + && token != ExpressionParser::INTEGER && token != ExpressionParser::STRING + && token != ExpressionParser::UNIT && token != ExpressionParser::ONE) { break; + } } ++i; } // Set prefix start for use when replacing later - if (i == static_cast(tokens.size())) + if (i == static_cast(tokens.size())) { prefixStart = prefixEnd; - else + } + else { prefixStart = start + std::get<1>(tokens[i]); + } // Build prefix from tokens while (i < static_cast(tokens.size())) { @@ -145,8 +145,9 @@ QString ExpressionTokenizer::perform(const QString& prefix, int pos) ++i; } - if (trim && trim < int(completionPrefix.size())) + if (trim && trim < int(completionPrefix.size())) { completionPrefix.resize(completionPrefix.size() - trim); + } return completionPrefix; } diff --git a/src/App/ExpressionTokenizer.h b/src/App/ExpressionTokenizer.h index 17ffad250de3..273179bf0de3 100644 --- a/src/App/ExpressionTokenizer.h +++ b/src/App/ExpressionTokenizer.h @@ -34,12 +34,14 @@ class AppExport ExpressionTokenizer public: QString perform(const QString& text, int pos); - void getPrefixRange(int &start, int &end) const { + void getPrefixRange(int& start, int& end) const + { start = prefixStart; end = prefixEnd; } - void updatePrefixEnd(int end) { + void updatePrefixEnd(int end) + { prefixEnd = end; } @@ -48,6 +50,6 @@ class AppExport ExpressionTokenizer int prefixEnd = 0; }; -} +} // namespace App -#endif //EXPRESSIONTOKENIZER_H +#endif // EXPRESSIONTOKENIZER_H diff --git a/src/App/ExpressionVisitors.h b/src/App/ExpressionVisitors.h index 2dc3c46b2b8a..ea111821e92f 100644 --- a/src/App/ExpressionVisitors.h +++ b/src/App/ExpressionVisitors.h @@ -25,48 +25,57 @@ #include "Expression.h" -namespace App { +namespace App +{ /** - * @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of an expression, and - * possibly rename VariableExpression nodes. + * @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of + * an expression, and possibly rename VariableExpression nodes. */ -template class RenameObjectIdentifierExpressionVisitor : public ExpressionModifier

{ +template +class RenameObjectIdentifierExpressionVisitor: public ExpressionModifier

+{ public: RenameObjectIdentifierExpressionVisitor( - P &_prop, - const std::map &_paths, - const ObjectIdentifier &_owner) + P& _prop, + const std::map& _paths, + const ObjectIdentifier& _owner) : ExpressionModifier

(_prop) - , paths( _paths ) - , owner( _owner ) - { - } + , paths(_paths) + , owner(_owner) + {} - void visit(Expression &node) override { - this->renameObjectIdentifier(node,paths,owner); + void visit(Expression& node) override + { + this->renameObjectIdentifier(node, paths, owner); } private: - const std::map &paths; /**< Map with current and new object identifiers */ - const ObjectIdentifier owner; /**< Owner of expression */ + const std::map& + paths; /**< Map with current and new object identifiers */ + const ObjectIdentifier owner; /**< Owner of expression */ }; -template class UpdateElementReferenceExpressionVisitor : public ExpressionModifier

{ +template +class UpdateElementReferenceExpressionVisitor: public ExpressionModifier

+{ public: + explicit UpdateElementReferenceExpressionVisitor(P& _prop, + App::DocumentObject* feature = nullptr, + bool reverse = false) + : ExpressionModifier

(_prop) + , feature(feature) + , reverse(reverse) + {} - explicit UpdateElementReferenceExpressionVisitor(P & _prop, App::DocumentObject *feature=nullptr, bool reverse=false) - : ExpressionModifier

(_prop),feature(feature),reverse(reverse) + void visit(Expression& node) override { - } - - void visit(Expression &node) override { - this->updateElementReference(node,feature,reverse); + this->updateElementReference(node, feature, reverse); } private: - App::DocumentObject *feature; + App::DocumentObject* feature; bool reverse; }; @@ -74,30 +83,36 @@ template class UpdateElementReferenceExpressionVisitor : public Express // ExpressionModifier, hence not calling aboutToSetValue/hasSetValue(). // By right, modification of document label should not change evaluation result // of any expression. -class RelabelDocumentExpressionVisitor : public ExpressionVisitor { +class RelabelDocumentExpressionVisitor: public ExpressionVisitor +{ public: + explicit RelabelDocumentExpressionVisitor(const App::Document& doc) + : doc(doc) + {} - explicit RelabelDocumentExpressionVisitor(const App::Document &doc) - : doc(doc) + void visit(Expression& node) override { - } - - void visit(Expression &node) override { - this->relabeledDocument(node,doc.getOldLabel(),doc.Label.getStrValue()); + this->relabeledDocument(node, doc.getOldLabel(), doc.Label.getStrValue()); } private: - const App::Document &doc; + const App::Document& doc; }; -template class MoveCellsExpressionVisitor : public ExpressionModifier

{ +template +class MoveCellsExpressionVisitor: public ExpressionModifier

+{ public: - MoveCellsExpressionVisitor(P &prop, const CellAddress &address, int rowCount, int colCount) - : ExpressionModifier

(prop),address(address),rowCount(rowCount),colCount(colCount) + MoveCellsExpressionVisitor(P& prop, const CellAddress& address, int rowCount, int colCount) + : ExpressionModifier

(prop) + , address(address) + , rowCount(rowCount) + , colCount(colCount) {} - void visit(Expression &node) override { - this->moveCells(node,address,rowCount,colCount); + void visit(Expression& node) override + { + this->moveCells(node, address, rowCount, colCount); } private: @@ -106,14 +121,19 @@ template class MoveCellsExpressionVisitor : public ExpressionModifier

class OffsetCellsExpressionVisitor : public ExpressionModifier

{ +template +class OffsetCellsExpressionVisitor: public ExpressionModifier

+{ public: - OffsetCellsExpressionVisitor(P &prop, int rowOffset, int colOffset) - : ExpressionModifier

(prop),rowOffset(rowOffset),colOffset(colOffset) + OffsetCellsExpressionVisitor(P& prop, int rowOffset, int colOffset) + : ExpressionModifier

(prop) + , rowOffset(rowOffset) + , colOffset(colOffset) {} - void visit(Expression &node) override { - this->offsetCells(node,rowOffset,colOffset); + void visit(Expression& node) override + { + this->offsetCells(node, rowOffset, colOffset); } private: @@ -121,6 +141,6 @@ template class OffsetCellsExpressionVisitor : public ExpressionModifier int colOffset; }; -} +} // namespace App -#endif // RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H +#endif // RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H diff --git a/src/App/FeatureTest.cpp b/src/App/FeatureTest.cpp index 9b804d0d6387..4d5592447fc8 100644 --- a/src/App/FeatureTest.cpp +++ b/src/App/FeatureTest.cpp @@ -38,8 +38,8 @@ #include "Range.h" #ifdef _MSC_VER -#pragma warning( disable : 4700 ) -#pragma warning( disable : 4723 ) +#pragma warning(disable : 4700) +#pragma warning(disable : 4723) #endif using namespace App; @@ -47,73 +47,106 @@ using namespace App; PROPERTY_SOURCE(App::FeatureTest, App::DocumentObject) -const char* enums[]= {"Zero","One","Two","Three","Four",nullptr}; -const PropertyIntegerConstraint::Constraints intPercent = {0,100,1}; -const PropertyFloatConstraint::Constraints floatPercent = {0.0,100.0,1.0}; +const char* enums[] = {"Zero", "One", "Two", "Three", "Four", nullptr}; +const PropertyIntegerConstraint::Constraints intPercent = {0, 100, 1}; +const PropertyFloatConstraint::Constraints floatPercent = {0.0, 100.0, 1.0}; FeatureTest::FeatureTest() { - ADD_PROPERTY(Integer,(4711) ); - ADD_PROPERTY(Float ,(47.11f) ); - ADD_PROPERTY(Bool ,(true) ); - ADD_PROPERTY(BoolList,(false)); - ADD_PROPERTY(String ,("4711")); - ADD_PROPERTY(Path ,("c:\\temp")); - ADD_PROPERTY(StringList ,("4711")); - - ADD_PROPERTY(Enum ,(4)); - Enum.setEnums(enums); - ADD_PROPERTY(ConstraintInt ,(5)); - ConstraintInt.setConstraints(&intPercent); - ADD_PROPERTY(ConstraintFloat ,(5.0)); - ConstraintFloat.setConstraints(&floatPercent); - - App::Color c; - App::Material mat(App::Material::GOLD); - ADD_PROPERTY(Colour ,(c) ); - ADD_PROPERTY(ColourList ,(c) ); - ADD_PROPERTY(Material ,(mat)); - ADD_PROPERTY(MaterialList,(mat)); - - ADD_PROPERTY(Distance,(47.11f) ); - ADD_PROPERTY(Angle ,(3.0f) ); - - ADD_PROPERTY(IntegerList,(4711) ); - ADD_PROPERTY(FloatList ,(47.11f) ); - - ADD_PROPERTY(Link ,(nullptr)); - ADD_PROPERTY(LinkSub ,(nullptr)); - ADD_PROPERTY(LinkList ,(nullptr)); - ADD_PROPERTY(LinkSubList,(nullptr)); - - ADD_PROPERTY(Vector ,(1.0,2.0,3.0)); - ADD_PROPERTY(VectorList,(3.0,2.0,1.0)); - ADD_PROPERTY(Matrix ,(Base::Matrix4D(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0))); - ADD_PROPERTY(Placement ,(Base::Placement())); - - // properties for recompute testing - static const char* group = "Feature Test"; - ADD_PROPERTY_TYPE(Source1 ,(nullptr),group,Prop_None,"Source for testing links"); - ADD_PROPERTY_TYPE(Source2 ,(nullptr),group,Prop_None,"Source for testing links"); - ADD_PROPERTY_TYPE(SourceN ,(nullptr),group,Prop_None,"Source for testing links"); - ADD_PROPERTY_TYPE(ExecResult ,("empty"),group,Prop_None,"Result of the execution"); - ADD_PROPERTY_TYPE(ExceptionType ,(0),group,Prop_None,"The type of exception the execution method throws"); - ADD_PROPERTY_TYPE(ExecCount ,(0),group,Prop_None,"Number of executions"); - - // properties with types - ADD_PROPERTY_TYPE(TypeHidden ,(4711),group,Prop_Hidden,"An example property which has the type 'Hidden'" ); - ADD_PROPERTY_TYPE(TypeReadOnly,(4711),group,Prop_ReadOnly ,"An example property which has the type 'ReadOnly'" ); - ADD_PROPERTY_TYPE(TypeOutput ,(4711),group,Prop_Output ,"An example property which has the type 'Output'" ); - ADD_PROPERTY_TYPE(TypeTransient,(4711),group,Prop_Transient ,"An example property which has the type 'Transient'" ); - ADD_PROPERTY_TYPE(TypeNoRecompute,(4711),group,Prop_NoRecompute,"An example property which has the type 'NoRecompute'"); - ADD_PROPERTY_TYPE(TypeAll ,(4711),group,(App::PropertyType) (Prop_Output|Prop_ReadOnly |Prop_Hidden ), - "An example property which has the types 'Output', 'ReadOnly' and 'Hidden'"); - - ADD_PROPERTY(QuantityLength,(1.0)); - QuantityLength.setUnit(Base::Unit::Length); - ADD_PROPERTY(QuantityOther,(5.0)); - QuantityOther.setUnit(Base::Unit(-3,1)); + // clang-format off + ADD_PROPERTY(Integer, (4711)); + ADD_PROPERTY(Float, (47.11f)); + ADD_PROPERTY(Bool, (true)); + ADD_PROPERTY(BoolList, (false)); + ADD_PROPERTY(String, ("4711")); + ADD_PROPERTY(Path, ("c:\\temp")); + ADD_PROPERTY(StringList, ("4711")); + + ADD_PROPERTY(Enum, (4)); + Enum.setEnums(enums); + ADD_PROPERTY(ConstraintInt, (5)); + ConstraintInt.setConstraints(&intPercent); + ADD_PROPERTY(ConstraintFloat, (5.0)); + ConstraintFloat.setConstraints(&floatPercent); + + App::Color c; + App::Material mat(App::Material::GOLD); + ADD_PROPERTY(Colour, (c)); + ADD_PROPERTY(ColourList, (c)); + ADD_PROPERTY(Material, (mat)); + ADD_PROPERTY(MaterialList, (mat)); + + ADD_PROPERTY(Distance, (47.11f)); + ADD_PROPERTY(Angle, (3.0f)); + + ADD_PROPERTY(IntegerList, (4711)); + ADD_PROPERTY(FloatList, (47.11f)); + + ADD_PROPERTY(Link, (nullptr)); + ADD_PROPERTY(LinkSub, (nullptr)); + ADD_PROPERTY(LinkList, (nullptr)); + ADD_PROPERTY(LinkSubList, (nullptr)); + + ADD_PROPERTY(Vector, (1.0, 2.0, 3.0)); + ADD_PROPERTY(VectorList, (3.0, 2.0, 1.0)); + ADD_PROPERTY(Matrix, + (Base::Matrix4D( 1.0, 2.0, 3.0, 4.0, + 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, + 13.0, 14.0, 15.0, 16.0))); + ADD_PROPERTY(Placement, (Base::Placement())); + + // properties for recompute testing + static const char* group = "Feature Test"; + ADD_PROPERTY_TYPE(Source1, (nullptr), group, Prop_None, "Source for testing links"); + ADD_PROPERTY_TYPE(Source2, (nullptr), group, Prop_None, "Source for testing links"); + ADD_PROPERTY_TYPE(SourceN, (nullptr), group, Prop_None, "Source for testing links"); + ADD_PROPERTY_TYPE(ExecResult, ("empty"), group, Prop_None, "Result of the execution"); + ADD_PROPERTY_TYPE(ExceptionType, + (0), + group, + Prop_None, + "The type of exception the execution method throws"); + ADD_PROPERTY_TYPE(ExecCount, (0), group, Prop_None, "Number of executions"); + + // properties with types + ADD_PROPERTY_TYPE(TypeHidden, + (4711), + group, + Prop_Hidden, + "An example property which has the type 'Hidden'"); + ADD_PROPERTY_TYPE(TypeReadOnly, + (4711), + group, + Prop_ReadOnly, + "An example property which has the type 'ReadOnly'"); + ADD_PROPERTY_TYPE(TypeOutput, + (4711), + group, + Prop_Output, + "An example property which has the type 'Output'"); + ADD_PROPERTY_TYPE(TypeTransient, + (4711), + group, + Prop_Transient, + "An example property which has the type 'Transient'"); + ADD_PROPERTY_TYPE(TypeNoRecompute, + (4711), + group, + Prop_NoRecompute, + "An example property which has the type 'NoRecompute'"); + ADD_PROPERTY_TYPE(TypeAll, + (4711), + group, + (App::PropertyType)(Prop_Output | Prop_ReadOnly | Prop_Hidden), + "An example property which has the types 'Output', 'ReadOnly' and 'Hidden'"); + + ADD_PROPERTY(QuantityLength, (1.0)); + QuantityLength.setUnit(Base::Unit::Length); + ADD_PROPERTY(QuantityOther, (5.0)); + QuantityOther.setUnit(Base::Unit(-3, 1)); + // clang-format on } FeatureTest::~FeatureTest() = default; @@ -123,7 +156,7 @@ short FeatureTest::mustExecute() const return DocumentObject::mustExecute(); } -DocumentObjectExecReturn *FeatureTest::execute() +DocumentObjectExecReturn* FeatureTest::execute() { // Enum handling Enumeration enumObj1 = Enum.getEnum(); @@ -159,19 +192,27 @@ DocumentObjectExecReturn *FeatureTest::execute() enumObj6.setEnums(list); enumObj6.setValue(list.back()); - int *i=nullptr,j; + int *i = nullptr, j; float f; - void *s; + void* s; std::string t; // Code analyzers may complain about some errors. This can be ignored // because this is done on purpose to test the error handling mechanism - switch(ExceptionType.getValue()) - { - case 0: break; - case 1: throw std::runtime_error("Test Exception"); - case 2: throw Base::RuntimeError("FeatureTestException::execute(): Testexception"); - default: (void)i; (void)j; (void)f; (void)s; (void)t; break; + switch (ExceptionType.getValue()) { + case 0: + break; + case 1: + throw std::runtime_error("Test Exception"); + case 2: + throw Base::RuntimeError("FeatureTestException::execute(): Testexception"); + default: + (void)i; + (void)j; + (void)f; + (void)s; + (void)t; + break; } ExecCount.setValue(ExecCount.getValue() + 1); @@ -188,12 +229,12 @@ PROPERTY_SOURCE(App::FeatureTestException, App::FeatureTest) FeatureTestException::FeatureTestException() { - ADD_PROPERTY(ExceptionType,(Base::Exception::getClassTypeId().getKey()) ); + ADD_PROPERTY(ExceptionType, (Base::Exception::getClassTypeId().getKey())); } -DocumentObjectExecReturn *FeatureTestException::execute() +DocumentObjectExecReturn* FeatureTestException::execute() { - //ExceptionType; + // ExceptionType; throw Base::RuntimeError("FeatureTestException::execute(): Testexception ;-)"); return nullptr; @@ -211,7 +252,7 @@ FeatureTestColumn::FeatureTestColumn() ADD_PROPERTY_TYPE(Value, (0L), "Test", App::Prop_Output, ""); } -DocumentObjectExecReturn *FeatureTestColumn::execute() +DocumentObjectExecReturn* FeatureTestColumn::execute() { Value.setValue(decodeColumn(Column.getStrValue(), Silent.getValue())); return nullptr; @@ -229,7 +270,7 @@ FeatureTestRow::FeatureTestRow() ADD_PROPERTY_TYPE(Value, (0L), "Test", App::Prop_Output, ""); } -DocumentObjectExecReturn *FeatureTestRow::execute() +DocumentObjectExecReturn* FeatureTestRow::execute() { Value.setValue(decodeRow(Row.getStrValue(), Silent.getValue())); return nullptr; @@ -246,7 +287,7 @@ FeatureTestAbsAddress::FeatureTestAbsAddress() ADD_PROPERTY_TYPE(Valid, (false), "Test", PropertyType(Prop_Output | Prop_ReadOnly), ""); } -DocumentObjectExecReturn *FeatureTestAbsAddress::execute() +DocumentObjectExecReturn* FeatureTestAbsAddress::execute() { CellAddress address; Valid.setValue(address.parseAbsoluteAddress(Address.getValue())); @@ -266,7 +307,7 @@ FeatureTestPlacement::FeatureTestPlacement() ADD_PROPERTY_TYPE(MultRight, (Base::Placement()), "Test", Prop_Output, ""); } -DocumentObjectExecReturn *FeatureTestPlacement::execute() +DocumentObjectExecReturn* FeatureTestPlacement::execute() { Base::Placement p1 = Input1.getValue(); Base::Placement q1 = Input1.getValue(); @@ -295,8 +336,9 @@ FeatureTestAttribute::~FeatureTestAttribute() #if PYCXX_VERSION_MAJOR >= 7 Py::ifPyErrorThrowCxxException(); #else - if (PyErr_Occurred()) + if (PyErr_Occurred()) { throw Py::RuntimeError(); + } #endif } catch (Py::RuntimeError& e) { @@ -308,7 +350,7 @@ FeatureTestAttribute::~FeatureTestAttribute() } } -DocumentObjectExecReturn *FeatureTestAttribute::execute() +DocumentObjectExecReturn* FeatureTestAttribute::execute() { Base::PyGILStateLocker lock; try { @@ -316,8 +358,9 @@ DocumentObjectExecReturn *FeatureTestAttribute::execute() #if PYCXX_VERSION_MAJOR >= 7 Py::ifPyErrorThrowCxxException(); #else - if (PyErr_Occurred()) + if (PyErr_Occurred()) { throw Py::AttributeError(); + } #endif } catch (Py::AttributeError& e) { diff --git a/src/App/FeatureTest.h b/src/App/FeatureTest.h index 2a52a6ed837b..bd10619f3252 100644 --- a/src/App/FeatureTest.h +++ b/src/App/FeatureTest.h @@ -35,107 +35,110 @@ namespace App { /// The testing feature -class FeatureTest : public DocumentObject +class FeatureTest: public DocumentObject { - PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTest); + PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTest); public: - FeatureTest(); - - ~FeatureTest() override; - - // Standard Properties (PropertyStandard.h) - App::PropertyInteger Integer; - App::PropertyFloat Float; - App::PropertyBool Bool; - App::PropertyBoolList BoolList; - App::PropertyString String; - App::PropertyPath Path; - App::PropertyStringList StringList; - - App::PropertyColor Colour; - App::PropertyColorList ColourList; - App::PropertyMaterial Material; - App::PropertyMaterialList MaterialList; - - // special types - App::PropertyDistance Distance; - App::PropertyAngle Angle; - - // Constraint types - App::PropertyEnumeration Enum; - App::PropertyIntegerConstraint ConstraintInt; - App::PropertyFloatConstraint ConstraintFloat; - - // Standard Properties (PrppertyStandard.h) - App::PropertyIntegerList IntegerList; - App::PropertyFloatList FloatList; - - // Standard Properties (PropertyLinks.h) - App::PropertyLink Link; - App::PropertyLinkSub LinkSub; - App::PropertyLinkList LinkList; - App::PropertyLinkSubList LinkSubList; - - // Standard Properties (PropertyGeo.h) - App::PropertyMatrix Matrix; - App::PropertyVector Vector; - App::PropertyVectorList VectorList; - App::PropertyPlacement Placement; - - // Properties to test the Document::recompute() - App::PropertyLink Source1; - App::PropertyLink Source2; - App::PropertyLinkList SourceN; - App::PropertyString ExecResult; - App::PropertyInteger ExceptionType; - App::PropertyInteger ExecCount; - - App::PropertyInteger TypeHidden; - App::PropertyInteger TypeReadOnly; - App::PropertyInteger TypeOutput; - App::PropertyInteger TypeAll; - App::PropertyInteger TypeTransient; - App::PropertyInteger TypeNoRecompute; - - App::PropertyQuantity QuantityLength; - App::PropertyQuantity QuantityOther; - //App::PropertyQuantity QuantityMass; - //App::PropertyQuantity QuantityAngle; - - /** @name methods override Feature */ - //@{ - short mustExecute() const override; - /// recalculate the Feature - DocumentObjectExecReturn *execute() override; - /// returns the type name of the ViewProvider - //Hint: Probably it makes sense to have a view provider for unittests (e.g. Gui::ViewProviderTest) - const char* getViewProviderName() const override { - return "Gui::ViewProviderFeature"; - } - //@} + FeatureTest(); + + ~FeatureTest() override; + + // Standard Properties (PropertyStandard.h) + App::PropertyInteger Integer; + App::PropertyFloat Float; + App::PropertyBool Bool; + App::PropertyBoolList BoolList; + App::PropertyString String; + App::PropertyPath Path; + App::PropertyStringList StringList; + + App::PropertyColor Colour; + App::PropertyColorList ColourList; + App::PropertyMaterial Material; + App::PropertyMaterialList MaterialList; + + // special types + App::PropertyDistance Distance; + App::PropertyAngle Angle; + + // Constraint types + App::PropertyEnumeration Enum; + App::PropertyIntegerConstraint ConstraintInt; + App::PropertyFloatConstraint ConstraintFloat; + + // Standard Properties (PrppertyStandard.h) + App::PropertyIntegerList IntegerList; + App::PropertyFloatList FloatList; + + // Standard Properties (PropertyLinks.h) + App::PropertyLink Link; + App::PropertyLinkSub LinkSub; + App::PropertyLinkList LinkList; + App::PropertyLinkSubList LinkSubList; + + // Standard Properties (PropertyGeo.h) + App::PropertyMatrix Matrix; + App::PropertyVector Vector; + App::PropertyVectorList VectorList; + App::PropertyPlacement Placement; + + // Properties to test the Document::recompute() + App::PropertyLink Source1; + App::PropertyLink Source2; + App::PropertyLinkList SourceN; + App::PropertyString ExecResult; + App::PropertyInteger ExceptionType; + App::PropertyInteger ExecCount; + + App::PropertyInteger TypeHidden; + App::PropertyInteger TypeReadOnly; + App::PropertyInteger TypeOutput; + App::PropertyInteger TypeAll; + App::PropertyInteger TypeTransient; + App::PropertyInteger TypeNoRecompute; + + App::PropertyQuantity QuantityLength; + App::PropertyQuantity QuantityOther; + // App::PropertyQuantity QuantityMass; + // App::PropertyQuantity QuantityAngle; + + /** @name methods override Feature */ + //@{ + short mustExecute() const override; + /// recalculate the Feature + DocumentObjectExecReturn* execute() override; + /// returns the type name of the ViewProvider + // Hint: Probably it makes sense to have a view provider for unittests (e.g. + // Gui::ViewProviderTest) + const char* getViewProviderName() const override + { + return "Gui::ViewProviderFeature"; + } + //@} }; /// The exception testing feature -class FeatureTestException :public FeatureTest +class FeatureTestException: public FeatureTest { - PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestException); + PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestException); public: - FeatureTestException(); - - /// this property defines which kind of exceptio the feature throw on you - App::PropertyInteger ExceptionType; - - /// recalculate the Feature and throw an exception - DocumentObjectExecReturn *execute() override; - /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { - return "Gui::ViewProviderFeature"; - } + FeatureTestException(); + + /// this property defines which kind of exceptio the feature throw on you + App::PropertyInteger ExceptionType; + + /// recalculate the Feature and throw an exception + DocumentObjectExecReturn* execute() override; + /// returns the type name of the ViewProvider + const char* getViewProviderName() const override + { + return "Gui::ViewProviderFeature"; + } }; -class FeatureTestColumn : public DocumentObject +class FeatureTestColumn: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestColumn); @@ -143,17 +146,17 @@ class FeatureTestColumn : public DocumentObject FeatureTestColumn(); // Standard Properties (PropertyStandard.h) - App::PropertyString Column; - App::PropertyBool Silent; + App::PropertyString Column; + App::PropertyBool Silent; App::PropertyInteger Value; /** @name methods override Feature */ //@{ - DocumentObjectExecReturn *execute() override; + DocumentObjectExecReturn* execute() override; //@} }; -class FeatureTestRow : public DocumentObject +class FeatureTestRow: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestRow); @@ -161,29 +164,29 @@ class FeatureTestRow : public DocumentObject FeatureTestRow(); // Standard Properties (PropertyStandard.h) - App::PropertyString Row; - App::PropertyBool Silent; + App::PropertyString Row; + App::PropertyBool Silent; App::PropertyInteger Value; /** @name methods override Feature */ //@{ - DocumentObjectExecReturn *execute() override; + DocumentObjectExecReturn* execute() override; //@} }; -class FeatureTestAbsAddress : public DocumentObject +class FeatureTestAbsAddress: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestAbsAddress); public: FeatureTestAbsAddress(); - DocumentObjectExecReturn *execute() override; + DocumentObjectExecReturn* execute() override; App::PropertyString Address; App::PropertyBool Valid; }; -class FeatureTestPlacement : public DocumentObject +class FeatureTestPlacement: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestPlacement); @@ -198,24 +201,24 @@ class FeatureTestPlacement : public DocumentObject /** @name methods override Feature */ //@{ - DocumentObjectExecReturn *execute() override; + DocumentObjectExecReturn* execute() override; //@} }; -class FeatureTestAttribute : public DocumentObject +class FeatureTestAttribute: public DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::FeatureTestAttribute); public: FeatureTestAttribute(); ~FeatureTestAttribute() override; - DocumentObjectExecReturn *execute() override; + DocumentObjectExecReturn* execute() override; App::PropertyPythonObject Object; App::PropertyString Attribute; }; -} //namespace App +} // namespace App -#endif // APP_FEATURETEST_H +#endif // APP_FEATURETEST_H diff --git a/src/App/GeoFeature.cpp b/src/App/GeoFeature.cpp index e3f448fac961..c434b599e5dd 100644 --- a/src/App/GeoFeature.cpp +++ b/src/App/GeoFeature.cpp @@ -47,12 +47,12 @@ PROPERTY_SOURCE(App::GeoFeature, App::DocumentObject) GeoFeature::GeoFeature() { - ADD_PROPERTY_TYPE(Placement,(Base::Placement()),nullptr,Prop_NoRecompute,nullptr); + ADD_PROPERTY_TYPE(Placement, (Base::Placement()), nullptr, Prop_NoRecompute, nullptr); } GeoFeature::~GeoFeature() = default; -void GeoFeature::transformPlacement(const Base::Placement &transform) +void GeoFeature::transformPlacement(const Base::Placement& transform) { Base::Placement plm = this->Placement.getValue(); plm = transform * plm; @@ -66,7 +66,7 @@ Base::Placement GeoFeature::globalPlacement() const auto ext = group->getExtensionByType(); return ext->globalGroupPlacement() * Placement.getValue(); } - return Placement.getValue(); + return Placement.getValue(); } const PropertyComplexGeoData* GeoFeature::getPropertyOfGeometry() const @@ -78,22 +78,22 @@ PyObject* GeoFeature::getPyObject() { if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new GeoFeaturePy(this),true); + PythonObject = Py::Object(new GeoFeaturePy(this), true); } return Py::new_reference_to(PythonObject); } -ElementNamePair -GeoFeature::getElementName(const char *name, ElementNameType type) const +ElementNamePair GeoFeature::getElementName(const char* name, ElementNameType type) const { (void)type; - if(!name) + if (!name) { return {}; + } auto prop = getPropertyOfGeometry(); if (!prop) { - return ElementNamePair("",name); + return ElementNamePair("", name); } auto geo = prop->getComplexData(); @@ -104,8 +104,8 @@ GeoFeature::getElementName(const char *name, ElementNameType type) const return _getElementName(name, geo->getElementName(name)); } -ElementNamePair -GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped) const +ElementNamePair GeoFeature::_getElementName(const char* name, + const Data::MappedElement& mapped) const { ElementNamePair ret; if (mapped.index && mapped.name) { @@ -123,9 +123,9 @@ GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped) // missing reference std::ostringstream ss; ss << Data::MISSING_PREFIX << dot + 1; - return ElementNamePair(name, ss.str().c_str() ); + return ElementNamePair(name, ss.str().c_str()); } - return ElementNamePair(name,""); + return ElementNamePair(name, ""); } else { std::string oldName; @@ -134,53 +134,70 @@ GeoFeature::_getElementName(const char* name, const Data::MappedElement& mapped) } } -DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subname, - ElementNamePair &elementName, bool append, - ElementNameType type, const DocumentObject *filter, - const char **_element, GeoFeature **geoFeature) +DocumentObject* GeoFeature::resolveElement(DocumentObject* obj, + const char* subname, + ElementNamePair& elementName, + bool append, + ElementNameType type, + const DocumentObject* filter, + const char** _element, + GeoFeature** geoFeature) { elementName.newName.clear(); elementName.oldName.clear(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { return nullptr; - if(!subname) + } + if (!subname) { subname = ""; - const char *element = Data::findElementName(subname); - if(_element) *_element = element; + } + const char* element = Data::findElementName(subname); + if (_element) { + *_element = element; + } auto sobj = obj->getSubObject(std::string(subname, element).c_str()); - if(!sobj) + if (!sobj) { return nullptr; + } auto linked = sobj->getLinkedObject(true); auto geo = Base::freecad_dynamic_cast(linked); - if(!geo && linked) { + if (!geo && linked) { auto ext = linked->getExtensionByType(true); - if(ext) + if (ext) { geo = Base::freecad_dynamic_cast(ext->getTrueLinkedObject(true)); + } } - if(geoFeature) + if (geoFeature) { *geoFeature = geo; - if(filter && geo!=filter) + } + if (filter && geo != filter) { return nullptr; - if(!element || !element[0]) { - if(append) + } + if (!element || !element[0]) { + if (append) { elementName.oldName = Data::oldElementName(subname); + } return sobj; } - if(!geo || hasHiddenMarker(element)) { - if(!append) + if (!geo || hasHiddenMarker(element)) { + if (!append) { elementName.oldName = element; - else + } + else { elementName.oldName = Data::oldElementName(subname); + } return sobj; } - if(!append) - elementName = geo->getElementName(element,type); - else{ - const auto &names = geo->getElementName(element,type); - std::string prefix(subname,element-subname); - if(!names.newName.empty()) + if (!append) { + elementName = geo->getElementName(element, type); + } + else { + const auto& names = geo->getElementName(element, type); + std::string prefix(subname, element - subname); + if (!names.newName.empty()) { elementName.newName = prefix + names.newName; + } elementName.oldName = prefix + names.oldName; } return sobj; @@ -264,12 +281,12 @@ std::vector GeoFeature::getElementTypes(bool /*all*/) const return prop->getComplexData()->getElementTypes(); } -std::vector -GeoFeature::getHigherElements(const char *element, bool silent) const +std::vector GeoFeature::getHigherElements(const char* element, bool silent) const { auto prop = getPropertyOfGeometry(); - if (!prop) + if (!prop) { return {}; + } return prop->getComplexData()->getHigherElements(element, silent); } @@ -284,8 +301,8 @@ Base::Placement GeoFeature::getPlacementFromProp(App::DocumentObject* obj, const } Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj, - App::DocumentObject* rootObj, - const std::string& sub) + App::DocumentObject* rootObj, + const std::string& sub) { if (!targetObj || !rootObj || sub.empty()) { return Base::Placement(); @@ -295,7 +312,9 @@ Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj, App::Document* doc = rootObj->getDocument(); Base::Placement plc = getPlacementFromProp(rootObj, "Placement"); - if (targetObj == rootObj) return plc; + if (targetObj == rootObj) { + return plc; + } for (auto& name : names) { App::DocumentObject* obj = doc->getObject(name.c_str()); @@ -319,7 +338,7 @@ Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj, } Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj, - App::PropertyXLinkSub* prop) + App::PropertyXLinkSub* prop) { if (!targetObj || !prop) { return Base::Placement(); diff --git a/src/App/GeoFeature.h b/src/App/GeoFeature.h index 1f35ab1e79aa..7288a5f3bd6f 100644 --- a/src/App/GeoFeature.h +++ b/src/App/GeoFeature.h @@ -36,7 +36,7 @@ namespace App /** Base class of all geometric document objects. */ -class AppExport GeoFeature : public App::DocumentObject +class AppExport GeoFeature: public App::DocumentObject { PROPERTY_HEADER_WITH_OVERRIDE(App::GeoFeature); @@ -54,7 +54,7 @@ class AppExport GeoFeature : public App::DocumentObject * was only called by alignment task (Edit->Alignment) * @param transform (input). */ - virtual void transformPlacement(const Base::Placement &transform); + virtual void transformPlacement(const Base::Placement& transform); /** * This method returns the main property of a geometric object that holds * the actual geometry. For a part object this is the Shape property, for @@ -68,14 +68,15 @@ class AppExport GeoFeature : public App::DocumentObject */ PyObject* getPyObject() override; - /// Specify the type of element name to return when calling getElementName() - enum ElementNameType { + /// Specify the type of element name to return when calling getElementName() + enum ElementNameType + { /// Normal usage - Normal=0, + Normal = 0, /// For importing - Import=1, + Import = 1, /// For exporting - Export=2, + Export = 2, }; /** Return the new and old style sub-element name @@ -86,12 +87,13 @@ class AppExport GeoFeature : public App::DocumentObject * @return a struct with the newName and oldName. New element name may be empty. */ virtual ElementNamePair getElementName( // NOLINT(google-default-arguments) - const char *name, ElementNameType type=Normal) const; + const char* name, + ElementNameType type = Normal) const; /** Resolve both the new and old style element name * * @param obj: top parent object - * @param subname: subname reference + * @param subname: subname reference * @param elementName: output of a pair(newElementName,oldElementName) * @param append: Whether to include subname prefix into the returned * element name @@ -102,22 +104,26 @@ class AppExport GeoFeature : public App::DocumentObject * * @return Return the owner object of the element */ - static DocumentObject *resolveElement(App::DocumentObject *obj, - const char *subname, ElementNamePair &elementName, - bool append=false, ElementNameType type=Normal, - const DocumentObject *filter=nullptr,const char **element=nullptr, GeoFeature **geo=nullptr); + static DocumentObject* resolveElement(App::DocumentObject* obj, + const char* subname, + ElementNamePair& elementName, + bool append = false, + ElementNameType type = Normal, + const DocumentObject* filter = nullptr, + const char** element = nullptr, + GeoFeature** geo = nullptr); /** * @brief Deprecated. Calculates the placement in the global reference coordinate system - * + * * Deprecated: This does not handle App::Links correctly. Use getGlobalPlacement() instead. * In FreeCAD the GeoFeature placement describes the local placement of the object in its parent * coordinate system. This is however not always the same as the global reference system. If the * object is in a GeoFeatureGroup, hence in another local coordinate system, the Placement - * property does only give the local transformation. This function can be used to calculate the - * placement of the object in the global reference coordinate system taking all stacked local + * property does only give the local transformation. This function can be used to calculate the + * placement of the object in the global reference coordinate system taking all stacked local * systems into account. - * + * * @return Base::Placement The transformation from the global reference coordinate system */ Base::Placement globalPlacement() const; @@ -148,7 +154,8 @@ class AppExport GeoFeature : public App::DocumentObject * * @return bool whether or not a direction is found. */ - virtual bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname = nullptr) const; + virtual bool getCameraAlignmentDirection(Base::Vector3d& direction, + const char* subname = nullptr) const; /** Search sub element using internal cached geometry * * @param element: element name @@ -164,36 +171,41 @@ class AppExport GeoFeature : public App::DocumentObject * code may call this function to search for the new element name that * reference to the same geometry of the old element. */ - virtual const std::vector& searchElementCache(const std::string &element, - Data::SearchOptions options = Data::SearchOption::CheckGeometry, - double tol = 1e-7, - double atol = 1e-10) const; + virtual const std::vector& + searchElementCache(const std::string& element, + Data::SearchOptions options = Data::SearchOption::CheckGeometry, + double tol = 1e-7, + double atol = 1e-10) const; - static bool hasMissingElement(const char *subname); + static bool hasMissingElement(const char* subname); /// Return the object that owns the shape that contains the give element name - virtual DocumentObject *getElementOwner(const Data::MappedName & /*name*/) const - {return nullptr;} + virtual DocumentObject* getElementOwner(const Data::MappedName& /*name*/) const + { + return nullptr; + } - virtual std::vector getElementTypes(bool all=true) const; + virtual std::vector getElementTypes(bool all = true) const; /// Return the higher level element names of the given element - virtual std::vector getHigherElements(const char *name, bool silent=false) const; + virtual std::vector getHigherElements(const char* name, + bool silent = false) const; static Base::Placement getPlacementFromProp(DocumentObject* obj, const char* propName); - static Base::Placement getGlobalPlacement(DocumentObject* targetObj, DocumentObject* rootObj, const std::string& sub); + static Base::Placement + getGlobalPlacement(DocumentObject* targetObj, DocumentObject* rootObj, const std::string& sub); static Base::Placement getGlobalPlacement(DocumentObject* targetObj, PropertyXLinkSub* prop); protected: void onChanged(const Property* prop) override; -// void onDocumentRestored() override; + // void onDocumentRestored() override; void updateElementReference(); + protected: - ElementNamePair _getElementName(const char* name, - const Data::MappedElement& mapped) const; + ElementNamePair _getElementName(const char* name, const Data::MappedElement& mapped) const; }; -} //namespace App +} // namespace App -#endif // APP_GEOFEATURE_H +#endif // APP_GEOFEATURE_H diff --git a/src/App/Link.cpp b/src/App/Link.cpp index 815787de66fa..c520d43a20d5 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -37,13 +37,13 @@ #include "Link.h" #include "LinkBaseExtensionPy.h" -//FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro +// FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #endif -FC_LOG_LEVEL_INIT("App::Link", true,true) +FC_LOG_LEVEL_INIT("App::Link", true, true) using namespace App; using namespace Base; @@ -58,22 +58,27 @@ import LinkParams LinkParams.define() ]]]*/ -namespace { +namespace +{ // Auto generated code. See class document of LinkParams. -class LinkParamsP: public ParameterGrp::ObserverType { +class LinkParamsP: public ParameterGrp::ObserverType +{ public: // Auto generated code. See class document of LinkParams. ParameterGrp::handle handle; // Auto generated code. See class document of LinkParams. - std::unordered_map funcs; + std::unordered_map + funcs; - bool CopyOnChangeApplyToAll; // Auto generated code. See class document of LinkParams. + bool CopyOnChangeApplyToAll; // Auto generated code. See class document of LinkParams. // Auto generated code. See class document of LinkParams. - LinkParamsP() { - handle = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Link"); + LinkParamsP() + { + handle = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Link"); handle->Attach(this); CopyOnChangeApplyToAll = handle->GetBool("CopyOnChangeApplyToAll", true); @@ -84,61 +89,73 @@ class LinkParamsP: public ParameterGrp::ObserverType { ~LinkParamsP() override = default; // Auto generated code. See class document of LinkParams. - void OnChange(Base::Subject &, const char* sReason) override { - if(!sReason) + void OnChange(Base::Subject&, const char* sReason) override + { + if (!sReason) { return; + } auto it = funcs.find(sReason); - if(it == funcs.end()) + if (it == funcs.end()) { return; + } it->second(this); } // Auto generated code. See class document of LinkParams. - static void updateCopyOnChangeApplyToAll(LinkParamsP *self) { + static void updateCopyOnChangeApplyToAll(LinkParamsP* self) + { self->CopyOnChangeApplyToAll = self->handle->GetBool("CopyOnChangeApplyToAll", true); } }; // Auto generated code. See class document of LinkParams. -LinkParamsP *instance() { - static LinkParamsP *inst = new LinkParamsP; +LinkParamsP* instance() +{ + static LinkParamsP* inst = new LinkParamsP; return inst; } -} // Anonymous namespace +} // Anonymous namespace // Auto generated code. See class document of LinkParams. -ParameterGrp::handle LinkParams::getHandle() { +ParameterGrp::handle LinkParams::getHandle() +{ return instance()->handle; } // Auto generated code. See class document of LinkParams. -const char *LinkParams::docCopyOnChangeApplyToAll() { - return QT_TRANSLATE_NOOP("LinkParams", -"Stores the last user choice of whether to apply CopyOnChange setup to all links\n" -"that reference the same configurable object"); +const char* LinkParams::docCopyOnChangeApplyToAll() +{ + return QT_TRANSLATE_NOOP( + "LinkParams", + "Stores the last user choice of whether to apply CopyOnChange setup to all links\n" + "that reference the same configurable object"); } // Auto generated code. See class document of LinkParams. -const bool & LinkParams::getCopyOnChangeApplyToAll() { +const bool& LinkParams::getCopyOnChangeApplyToAll() +{ return instance()->CopyOnChangeApplyToAll; } // Auto generated code. See class document of LinkParams. -const bool & LinkParams::defaultCopyOnChangeApplyToAll() { +const bool& LinkParams::defaultCopyOnChangeApplyToAll() +{ static const bool def = true; return def; } // Auto generated code. See class document of LinkParams. -void LinkParams::setCopyOnChangeApplyToAll(const bool &v) { - instance()->handle->SetBool("CopyOnChangeApplyToAll",v); +void LinkParams::setCopyOnChangeApplyToAll(const bool& v) +{ + instance()->handle->SetBool("CopyOnChangeApplyToAll", v); instance()->CopyOnChangeApplyToAll = v; } // Auto generated code. See class document of LinkParams. -void LinkParams::removeCopyOnChangeApplyToAll() { +void LinkParams::removeCopyOnChangeApplyToAll() +{ instance()->handle->RemoveBool("CopyOnChangeApplyToAll"); } //[[[end]]] @@ -150,235 +167,267 @@ EXTENSION_PROPERTY_SOURCE(App::LinkBaseExtension, App::DocumentObjectExtension) LinkBaseExtension::LinkBaseExtension() { initExtensionType(LinkBaseExtension::getExtensionClassTypeId()); - EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, (false), " Link", - PropertyType(Prop_Hidden|Prop_NoPersist),0); - EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, (), " Link", - PropertyType(Prop_Hidden|Prop_NoPersist|Prop_ReadOnly),0); + EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, + (false), + " Link", + PropertyType(Prop_Hidden | Prop_NoPersist), + 0); + EXTENSION_ADD_PROPERTY_TYPE(_ChildCache, + (), + " Link", + PropertyType(Prop_Hidden | Prop_NoPersist | Prop_ReadOnly), + 0); _ChildCache.setScope(LinkScope::Global); - EXTENSION_ADD_PROPERTY_TYPE(_LinkOwner, (0), " Link", - PropertyType(Prop_Hidden|Prop_Output),0); - props.resize(PropMax,nullptr); + EXTENSION_ADD_PROPERTY_TYPE(_LinkOwner, + (0), + " Link", + PropertyType(Prop_Hidden | Prop_Output), + 0); + props.resize(PropMax, nullptr); } -PyObject* LinkBaseExtension::getExtensionPyObject() { - if (ExtensionPythonObject.is(Py::_None())){ +PyObject* LinkBaseExtension::getExtensionPyObject() +{ + if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 - ExtensionPythonObject = Py::Object(new LinkBaseExtensionPy(this),true); + ExtensionPythonObject = Py::Object(new LinkBaseExtensionPy(this), true); } return Py::new_reference_to(ExtensionPythonObject); } -const std::vector &LinkBaseExtension::getPropertyInfo() const { +const std::vector& LinkBaseExtension::getPropertyInfo() const +{ static std::vector PropsInfo; - if(PropsInfo.empty()) { - BOOST_PP_SEQ_FOR_EACH(LINK_PROP_INFO,PropsInfo,LINK_PARAMS); + if (PropsInfo.empty()) { + BOOST_PP_SEQ_FOR_EACH(LINK_PROP_INFO, PropsInfo, LINK_PARAMS); } return PropsInfo; } -const LinkBaseExtension::PropInfoMap &LinkBaseExtension::getPropertyInfoMap() const { +const LinkBaseExtension::PropInfoMap& LinkBaseExtension::getPropertyInfoMap() const +{ static PropInfoMap PropsMap; - if(PropsMap.empty()) { - const auto &infos = getPropertyInfo(); - for(const auto &info : infos) + if (PropsMap.empty()) { + const auto& infos = getPropertyInfo(); + for (const auto& info : infos) { PropsMap[info.name] = info; + } } return PropsMap; } -Property *LinkBaseExtension::getProperty(int idx) { - if(idx>=0 && idx<(int)props.size()) +Property* LinkBaseExtension::getProperty(int idx) +{ + if (idx >= 0 && idx < (int)props.size()) { return props[idx]; + } return nullptr; } -Property *LinkBaseExtension::getProperty(const char *name) { - const auto &info = getPropertyInfoMap(); +Property* LinkBaseExtension::getProperty(const char* name) +{ + const auto& info = getPropertyInfoMap(); auto it = info.find(name); - if(it == info.end()) + if (it == info.end()) { return nullptr; + } return getProperty(it->second.index); } -void LinkBaseExtension::setProperty(int idx, Property *prop) { - const auto &infos = getPropertyInfo(); - if(idx<0 || idx>=(int)infos.size()) - LINK_THROW(Base::RuntimeError,"App::LinkBaseExtension: property index out of range"); +void LinkBaseExtension::setProperty(int idx, Property* prop) +{ + const auto& infos = getPropertyInfo(); + if (idx < 0 || idx >= (int)infos.size()) { + LINK_THROW(Base::RuntimeError, "App::LinkBaseExtension: property index out of range"); + } - if(props[idx]) { - props[idx]->setStatus(Property::LockDynamic,false); + if (props[idx]) { + props[idx]->setStatus(Property::LockDynamic, false); props[idx] = nullptr; } - if(!prop) + if (!prop) { return; - if(!prop->isDerivedFrom(infos[idx].type)) { + } + if (!prop->isDerivedFrom(infos[idx].type)) { std::ostringstream str; - str << "App::LinkBaseExtension: expected property type '" << - infos[idx].type.getName() << "', instead of '" << - prop->getClassTypeId().getName() << "'"; - LINK_THROW(Base::TypeError,str.str().c_str()); + str << "App::LinkBaseExtension: expected property type '" << infos[idx].type.getName() + << "', instead of '" << prop->getClassTypeId().getName() << "'"; + LINK_THROW(Base::TypeError, str.str().c_str()); } props[idx] = prop; - props[idx]->setStatus(Property::LockDynamic,true); - - switch(idx) { - case PropLinkMode: { - static const char *linkModeEnums[] = {"None","Auto Delete","Auto Link","Auto Unlink",nullptr}; - auto propLinkMode = static_cast(prop); - if(!propLinkMode->hasEnums()) - propLinkMode->setEnums(linkModeEnums); - break; - } - case PropLinkCopyOnChange: { - static const char *enums[] = {"Disabled","Enabled","Owned","Tracking",nullptr}; - auto propEnum = static_cast(prop); - if(!propEnum->hasEnums()) - propEnum->setEnums(enums); - break; - } - case PropLinkCopyOnChangeSource: - case PropLinkCopyOnChangeGroup: - if (auto linkProp = Base::freecad_dynamic_cast(prop)) { - linkProp->setScope(LinkScope::Global); - } - // fall through - case PropLinkCopyOnChangeTouched: - prop->setStatus(Property::Hidden, true); - break; - case PropLinkTransform: - case PropLinkPlacement: - case PropPlacement: - if(getLinkTransformProperty() && - getLinkPlacementProperty() && - getPlacementProperty()) - { - bool transform = getLinkTransformValue(); - getPlacementProperty()->setStatus(Property::Hidden, transform); - getLinkPlacementProperty()->setStatus(Property::Hidden, !transform); - } - break; - case PropElementList: - getElementListProperty()->setScope(LinkScope::Global); - getElementListProperty()->setStatus(Property::Hidden, true); - // fall through - case PropLinkedObject: - // Make ElementList as read-only if we are not a group (i.e. having - // LinkedObject property), because it is for holding array elements. - if(getElementListProperty()) { - getElementListProperty()->setStatus( - Property::Immutable, getLinkedObjectProperty() != nullptr); - } - if (auto linkProp = getLinkedObjectProperty()) { - linkProp->setScope(LinkScope::Global); - } - break; - case PropVisibilityList: - getVisibilityListProperty()->setStatus(Property::Immutable, true); - getVisibilityListProperty()->setStatus(Property::Hidden, true); - break; - } - - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) { - const char *propName; - if(!prop) + props[idx]->setStatus(Property::LockDynamic, true); + + switch (idx) { + case PropLinkMode: { + static const char* linkModeEnums[] = {"None", + "Auto Delete", + "Auto Link", + "Auto Unlink", + nullptr}; + auto propLinkMode = static_cast(prop); + if (!propLinkMode->hasEnums()) { + propLinkMode->setEnums(linkModeEnums); + } + break; + } + case PropLinkCopyOnChange: { + static const char* enums[] = {"Disabled", "Enabled", "Owned", "Tracking", nullptr}; + auto propEnum = static_cast(prop); + if (!propEnum->hasEnums()) { + propEnum->setEnums(enums); + } + break; + } + case PropLinkCopyOnChangeSource: + case PropLinkCopyOnChangeGroup: + if (auto linkProp = Base::freecad_dynamic_cast(prop)) { + linkProp->setScope(LinkScope::Global); + } + // fall through + case PropLinkCopyOnChangeTouched: + prop->setStatus(Property::Hidden, true); + break; + case PropLinkTransform: + case PropLinkPlacement: + case PropPlacement: + if (getLinkTransformProperty() && getLinkPlacementProperty() + && getPlacementProperty()) { + bool transform = getLinkTransformValue(); + getPlacementProperty()->setStatus(Property::Hidden, transform); + getLinkPlacementProperty()->setStatus(Property::Hidden, !transform); + } + break; + case PropElementList: + getElementListProperty()->setScope(LinkScope::Global); + getElementListProperty()->setStatus(Property::Hidden, true); + // fall through + case PropLinkedObject: + // Make ElementList as read-only if we are not a group (i.e. having + // LinkedObject property), because it is for holding array elements. + if (getElementListProperty()) { + getElementListProperty()->setStatus(Property::Immutable, + getLinkedObjectProperty() != nullptr); + } + if (auto linkProp = getLinkedObjectProperty()) { + linkProp->setScope(LinkScope::Global); + } + break; + case PropVisibilityList: + getVisibilityListProperty()->setStatus(Property::Immutable, true); + getVisibilityListProperty()->setStatus(Property::Hidden, true); + break; + } + + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) { + const char* propName; + if (!prop) { propName = ""; - else if(prop->getContainer()) + } + else if (prop->getContainer()) { propName = prop->getName(); - else + } + else { propName = extensionGetPropertyName(prop); - if(!Property::isValidName(propName)) + } + if (!Property::isValidName(propName)) { propName = "?"; + } FC_TRACE("set property " << infos[idx].name << ": " << propName); } } static const char _GroupPrefix[] = "Configuration ("; -App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { +App::DocumentObjectExecReturn* LinkBaseExtension::extensionExecute() +{ // The actual value of LinkTouched is not important, just to notify view // provider that the link (in fact, its dependents, i.e. linked ones) have // recomputed. _LinkTouched.touch(); - if(getLinkedObjectProperty()) { - DocumentObject *linked = getTrueLinkedObject(true); - if(!linked) { + if (getLinkedObjectProperty()) { + DocumentObject* linked = getTrueLinkedObject(true); + if (!linked) { std::ostringstream ss; ss << "Link broken!"; - auto xlink = Base::freecad_dynamic_cast( - getLinkedObjectProperty()); + auto xlink = Base::freecad_dynamic_cast(getLinkedObjectProperty()); if (xlink) { - const char *objname = xlink->getObjectName(); - if (objname && objname[0]) + const char* objname = xlink->getObjectName(); + if (objname && objname[0]) { ss << "\nObject: " << objname; - const char *filename = xlink->getFilePath(); - if (filename && filename[0]) + } + const char* filename = xlink->getFilePath(); + if (filename && filename[0]) { ss << "\nFile: " << filename; + } } return new App::DocumentObjectExecReturn(ss.str().c_str()); } - App::DocumentObject *container = getContainer(); + App::DocumentObject* container = getContainer(); auto source = getLinkCopyOnChangeSourceValue(); if (source && getLinkCopyOnChangeValue() == CopyOnChangeTracking - && getLinkCopyOnChangeTouchedValue()) - { + && getLinkCopyOnChangeTouchedValue()) { syncCopyOnChange(); } // the previous linked object could be deleted by syncCopyOnChange - #12281 linked = getTrueLinkedObject(true); - if(!linked) { + if (!linked) { return new App::DocumentObjectExecReturn("Error in processing variable link"); } - PropertyPythonObject *proxy = nullptr; - if(getLinkExecuteProperty() - && !boost::iequals(getLinkExecuteValue(), "none") - && (!_LinkOwner.getValue() - || !container->getDocument()->getObjectByID(_LinkOwner.getValue()))) - { + PropertyPythonObject* proxy = nullptr; + if (getLinkExecuteProperty() && !boost::iequals(getLinkExecuteValue(), "none") + && (!_LinkOwner.getValue() + || !container->getDocument()->getObjectByID(_LinkOwner.getValue()))) { // Check if this is an element link. Do not invoke appLinkExecute() // if so, because it will be called from the link array. proxy = Base::freecad_dynamic_cast( - linked->getPropertyByName("Proxy")); + linked->getPropertyByName("Proxy")); } - if(proxy) { + if (proxy) { Base::PyGILStateLocker lock; - const char *errMsg = "Linked proxy execute failed"; + const char* errMsg = "Linked proxy execute failed"; try { Py::Tuple args(3); Py::Object proxyValue = proxy->getValue(); - const char *method = getLinkExecuteValue(); - if(!method || !method[0]) + const char* method = getLinkExecuteValue(); + if (!method || !method[0]) { method = "appLinkExecute"; - if(proxyValue.hasAttr(method)) { + } + if (proxyValue.hasAttr(method)) { Py::Object attr = proxyValue.getAttr(method); - if(attr.ptr() && attr.isCallable()) { + if (attr.ptr() && attr.isCallable()) { Py::Tuple args(4); args.setItem(0, Py::asObject(linked->getPyObject())); args.setItem(1, Py::asObject(container->getPyObject())); - if(!_getElementCountValue()) { + if (!_getElementCountValue()) { Py::Callable(attr).apply(args); - } else { - const auto &elements = _getElementListValue(); - for(int i=0; i<_getElementCountValue(); ++i) { + } + else { + const auto& elements = _getElementListValue(); + for (int i = 0; i < _getElementCountValue(); ++i) { args.setItem(2, Py::Int(i)); - if(i < (int)elements.size()) + if (i < (int)elements.size()) { args.setItem(3, Py::asObject(elements[i]->getPyObject())); - else + } + else { args.setItem(3, Py::Object()); + } Py::Callable(attr).apply(args); } } } } - } catch (Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException e; e.ReportException(); return new App::DocumentObjectExecReturn(errMsg); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); return new App::DocumentObjectExecReturn(errMsg); } @@ -387,17 +436,19 @@ App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { auto parent = getContainer(); setupCopyOnChange(parent); - if(hasCopyOnChange && getLinkCopyOnChangeValue()==CopyOnChangeDisabled) { + if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { hasCopyOnChange = false; std::vector props; parent->getPropertyList(props); - for(auto prop : props) { - if(isCopyOnChangeProperty(parent, *prop)) { + for (auto prop : props) { + if (isCopyOnChangeProperty(parent, *prop)) { try { parent->removeDynamicProperty(prop->getName()); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); - } catch (...) { + } + catch (...) { } } } @@ -406,46 +457,53 @@ App::DocumentObjectExecReturn *LinkBaseExtension::extensionExecute() { return inherited::extensionExecute(); } -short LinkBaseExtension::extensionMustExecute() { +short LinkBaseExtension::extensionMustExecute() +{ auto link = getLink(); - if(!link) + if (!link) { return 0; + } return link->mustExecute(); } std::vector -LinkBaseExtension::getOnChangeCopyObjects( - std::vector *excludes, - App::DocumentObject *src) +LinkBaseExtension::getOnChangeCopyObjects(std::vector* excludes, + App::DocumentObject* src) { auto parent = getContainer(); - if (!src) + if (!src) { src = getLinkCopyOnChangeSourceValue(); - if (!src || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) + } + if (!src || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return {}; + } auto res = Document::getDependencyList({src}, Document::DepSort); - for (auto it=res.begin(); it!=res.end();) { + for (auto it = res.begin(); it != res.end();) { auto obj = *it; if (obj == src) { ++it; continue; } - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_CopyOnChangeControl")); + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); static std::map dummy; - const auto & map = prop && prop->getContainer()==obj ? prop->getValues() : dummy; - const char *v = ""; - if (src->getDocument() != obj->getDocument()) + const auto& map = prop && prop->getContainer() == obj ? prop->getValues() : dummy; + const char* v = ""; + if (src->getDocument() != obj->getDocument()) { v = "-"; + } auto iter = map.find("*"); - if (iter != map.end()) + if (iter != map.end()) { v = iter->second.c_str(); - else if ((iter = map.find(parent->getNameInDocument())) != map.end()) + } + else if ((iter = map.find(parent->getNameInDocument())) != map.end()) { v = iter->second.c_str(); + } if (boost::equals(v, "-")) { - if (excludes) + if (excludes) { excludes->push_back(obj); + } else { it = res.erase(it); continue; @@ -456,24 +514,25 @@ LinkBaseExtension::getOnChangeCopyObjects( return res; } -void LinkBaseExtension::setOnChangeCopyObject( - App::DocumentObject *obj, OnChangeCopyOptions options) +void LinkBaseExtension::setOnChangeCopyObject(App::DocumentObject* obj, OnChangeCopyOptions options) { auto parent = getContainer(); Base::Flags flags(options); bool exclude = flags.testFlag(OnChangeCopyOptions::Exclude); bool external = parent->getDocument() != obj->getDocument(); - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_CopyOnChangeControl")); + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_CopyOnChangeControl")); - if (external == exclude && !prop) + if (external == exclude && !prop) { return; + } if (!prop) { try { prop = static_cast( - obj->addDynamicProperty("App::PropertyMap", "_CopyOnChangeControl")); - } catch (Base::Exception &e) { + obj->addDynamicProperty("App::PropertyMap", "_CopyOnChangeControl")); + } + catch (Base::Exception& e) { e.ReportException(); } if (!prop) { @@ -482,11 +541,13 @@ void LinkBaseExtension::setOnChangeCopyObject( } } - const char *key = flags.testFlag(OnChangeCopyOptions::ApplyAll) ? "*" : parent->getDagKey(); - if (external) + const char* key = flags.testFlag(OnChangeCopyOptions::ApplyAll) ? "*" : parent->getDagKey(); + if (external) { prop->setValue(key, exclude ? "" : "+"); - else + } + else { prop->setValue(key, exclude ? "-" : ""); + } } // The purpose of this function is to synchronize the mutated copy to the @@ -494,18 +555,16 @@ void LinkBaseExtension::setOnChangeCopyObject( // non-CopyOnChange property of the original object has changed. void LinkBaseExtension::syncCopyOnChange() { - if (!getLinkCopyOnChangeValue()) + if (!getLinkCopyOnChangeValue()) { return; + } auto linkProp = getLinkedObjectProperty(); auto srcProp = getLinkCopyOnChangeSourceProperty(); auto srcTouched = getLinkCopyOnChangeTouchedProperty(); - if (!linkProp - || !srcProp - || !srcTouched - || !srcProp->getValue() - || !linkProp->getValue() - || srcProp->getValue() == linkProp->getValue()) + if (!linkProp || !srcProp || !srcTouched || !srcProp->getValue() || !linkProp->getValue() + || srcProp->getValue() == linkProp->getValue()) { return; + } auto parent = getContainer(); @@ -517,7 +576,7 @@ void LinkBaseExtension::syncCopyOnChange() // CopyOnChangeGroup is a hidden dynamic property for holding a LinkGroup // for holding the mutated copy of the original linked object and all its // dependencies. - LinkGroup *copyOnChangeGroup = nullptr; + LinkGroup* copyOnChangeGroup = nullptr; if (auto prop = getLinkCopyOnChangeGroupProperty()) { copyOnChangeGroup = Base::freecad_dynamic_cast(prop->getValue()); if (!copyOnChangeGroup) { @@ -526,20 +585,24 @@ void LinkBaseExtension::syncCopyOnChange() group->LinkMode.setValue(LinkModeAutoDelete); parent->getDocument()->addObject(group, "CopyOnChangeGroup"); prop->setValue(group); - } else { + } + else { // If it exists, then obtain all copied objects. Note that we stores // the dynamic property _SourceUUID in oldObjs if possible, in order // to match the possible new copy later. objs = copyOnChangeGroup->ElementList.getValues(); for (auto obj : objs) { - if (!obj->isAttachedToDocument()) + if (!obj->isAttachedToDocument()) { continue; - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_SourceUUID")); - if (prop && prop->getContainer() == obj) + } + auto prop = + Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + if (prop && prop->getContainer() == obj) { oldObjs.emplace_back(prop); - else + } + else { oldObjs.emplace_back(obj); + } } std::sort(objs.begin(), objs.end()); } @@ -555,8 +618,9 @@ void LinkBaseExtension::syncCopyOnChange() // copyObject()) will generate a _ObjectUUID for each source object and // match it with a _SourceUUID in the copy. auto copiedObjs = parent->getDocument()->copyObject(srcObjs); - if(copiedObjs.empty()) + if (copiedObjs.empty()) { return; + } // copyObject() will return copy in order of the same order of the input, // so the last object will be the copy of the original linked object @@ -568,9 +632,9 @@ void LinkBaseExtension::syncCopyOnChange() std::vector propList; linked->getPropertyList(propList); for (auto prop : propList) { - if(!prop->testStatus(Property::CopyOnChange) - || prop->getContainer()!=linked) + if (!prop->testStatus(Property::CopyOnChange) || prop->getContainer() != linked) { continue; + } auto p = newLinked->getPropertyByName(prop->getName()); if (p && p->getTypeId() == prop->getTypeId()) { std::unique_ptr pCopy(prop->Copy()); @@ -596,53 +660,59 @@ void LinkBaseExtension::syncCopyOnChange() std::map newObjs; for (auto obj : copiedObjs) { - auto prop = Base::freecad_dynamic_cast( - obj->getPropertyByName("_SourceUUID")); - if (prop) + auto prop = Base::freecad_dynamic_cast(obj->getPropertyByName("_SourceUUID")); + if (prop) { newObjs.insert(std::make_pair(prop->getValue(), obj)); + } } - std::vector > replacements; - for (const auto &objT : oldObjs) { + std::vector> replacements; + for (const auto& objT : oldObjs) { auto prop = Base::freecad_dynamic_cast(objT.getProperty()); - if (!prop) + if (!prop) { continue; + } auto it = newObjs.find(prop->getValue()); - if (it == newObjs.end()) + if (it == newObjs.end()) { continue; + } auto oldObj = objT.getObject(); auto newObj = it->second.getObject(); - if (oldObj && newObj) + if (oldObj && newObj) { replacements.emplace_back(oldObj, newObj); + } } - std::vector > > propChanges; + std::vector>> propChanges; if (!replacements.empty()) { std::sort(copiedObjs.begin(), copiedObjs.end()); // Global search for links affected by the replacement. We accumulate // the changes in propChanges without applying, in order to avoid any // side effect of changing while searching. - for(auto doc : App::GetApplication().getDocuments()) { - for(auto o : doc->getObjects()) { - if (o == parent - || std::binary_search(objs.begin(), objs.end(), o) - || std::binary_search(copiedObjs.begin(), copiedObjs.end(), o)) + for (auto doc : App::GetApplication().getDocuments()) { + for (auto o : doc->getObjects()) { + if (o == parent || std::binary_search(objs.begin(), objs.end(), o) + || std::binary_search(copiedObjs.begin(), copiedObjs.end(), o)) { continue; + } propList.clear(); o->getPropertyList(propList); - for(auto prop : propList) { - if (prop->getContainer() != o) + for (auto prop : propList) { + if (prop->getContainer() != o) { continue; + } auto linkProp = Base::freecad_dynamic_cast(prop); - if(!linkProp) + if (!linkProp) { continue; - for (const auto &v : replacements) { + } + for (const auto& v : replacements) { std::unique_ptr copy( - linkProp->CopyOnLinkReplace(parent,v.first,v.second)); - if(!copy) + linkProp->CopyOnLinkReplace(parent, v.first, v.second)); + if (!copy) { continue; - propChanges.emplace_back(App::DocumentObjectT(prop),std::move(copy)); + } + propChanges.emplace_back(App::DocumentObjectT(prop), std::move(copy)); } } } @@ -655,20 +725,22 @@ void LinkBaseExtension::syncCopyOnChange() srcTouched->setValue(false); // Apply the global link changes. - for(const auto &v : propChanges) { + for (const auto& v : propChanges) { auto prop = v.first.getProperty(); - if(prop) + if (prop) { prop->Paste(*v.second.get()); + } } // Finally, remove all old copies. oldObjs stores type of DocumentObjectT // which stores the object name. Before removing, we need to make sure the // object exists, and it is not some new object with the same name, by // checking objs which stores DocumentObject pointer. - for (const auto &objT : oldObjs) { + for (const auto& objT : oldObjs) { auto obj = objT.getObject(); - if (obj && std::binary_search(objs.begin(), objs.end(), obj)) + if (obj && std::binary_search(objs.begin(), objs.end(), obj)) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } @@ -678,101 +750,113 @@ bool LinkBaseExtension::isLinkedToConfigurableObject() const std::vector propList; linked->getPropertyList(propList); for (auto prop : propList) { - if(prop->testStatus(Property::CopyOnChange) - && prop->getContainer()==linked) + if (prop->testStatus(Property::CopyOnChange) && prop->getContainer() == linked) { return true; + } } } return false; } -bool LinkBaseExtension::isCopyOnChangeProperty(DocumentObject *obj, const App::Property &prop) { - if(obj!=prop.getContainer() || !prop.testStatus(App::Property::PropDynamic)) +bool LinkBaseExtension::isCopyOnChangeProperty(DocumentObject* obj, const App::Property& prop) +{ + if (obj != prop.getContainer() || !prop.testStatus(App::Property::PropDynamic)) { return false; + } auto group = prop.getGroup(); - return group && boost::starts_with(group,_GroupPrefix); + return group && boost::starts_with(group, _GroupPrefix); } -void LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, bool checkSource) { +void LinkBaseExtension::setupCopyOnChange(DocumentObject* parent, bool checkSource) +{ copyOnChangeConns.clear(); copyOnChangeSrcConns.clear(); auto linked = getTrueLinkedObject(false); - if(!linked || getLinkCopyOnChangeValue()==CopyOnChangeDisabled) + if (!linked || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; + } if (checkSource && !pauseCopyOnChange) { - PropertyLink *source = getLinkCopyOnChangeSourceProperty(); + PropertyLink* source = getLinkCopyOnChangeSourceProperty(); if (source) { source->setValue(linked); - if (auto touched = getLinkCopyOnChangeTouchedProperty()) + if (auto touched = getLinkCopyOnChangeTouchedProperty()) { touched->setValue(false); + } } } - hasCopyOnChange = setupCopyOnChange(parent,linked,©OnChangeConns,hasCopyOnChange); - if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeOwned - && getLinkedObjectValue() - && getLinkedObjectValue() == getLinkCopyOnChangeSourceValue()) - { + hasCopyOnChange = setupCopyOnChange(parent, linked, ©OnChangeConns, hasCopyOnChange); + if (hasCopyOnChange && getLinkCopyOnChangeValue() == CopyOnChangeOwned && getLinkedObjectValue() + && getLinkedObjectValue() == getLinkCopyOnChangeSourceValue()) { makeCopyOnChange(); } } -bool LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, DocumentObject *linked, - std::vector *copyOnChangeConns, bool checkExisting) +bool LinkBaseExtension::setupCopyOnChange( + DocumentObject* parent, + DocumentObject* linked, + std::vector* copyOnChangeConns, + bool checkExisting) { - if(!parent || !linked) + if (!parent || !linked) { return false; + } bool res = false; std::unordered_map newProps; std::vector props; linked->getPropertyList(props); - for(auto prop : props) { - if(!prop->testStatus(Property::CopyOnChange) - || prop->getContainer()!=linked) + for (auto prop : props) { + if (!prop->testStatus(Property::CopyOnChange) || prop->getContainer() != linked) { continue; + } res = true; const char* linkedGroupName = prop->getGroup(); - if(!linkedGroupName || !linkedGroupName[0]) + if (!linkedGroupName || !linkedGroupName[0]) { linkedGroupName = "Base"; + } std::string groupName; groupName = _GroupPrefix; - if(boost::starts_with(linkedGroupName,_GroupPrefix)) - groupName += linkedGroupName + sizeof(_GroupPrefix)-1; + if (boost::starts_with(linkedGroupName, _GroupPrefix)) { + groupName += linkedGroupName + sizeof(_GroupPrefix) - 1; + } else { groupName += linkedGroupName; groupName += ")"; } auto p = parent->getPropertyByName(prop->getName()); - if(p) { - if(p->getContainer()!=parent) + if (p) { + if (p->getContainer() != parent) { p = nullptr; + } else { const char* otherGroupName = p->getGroup(); - if(!otherGroupName || !boost::starts_with(otherGroupName, _GroupPrefix)) { - FC_WARN(p->getFullName() << " shadows another CopyOnChange property " - << prop->getFullName()); + if (!otherGroupName || !boost::starts_with(otherGroupName, _GroupPrefix)) { + FC_WARN(p->getFullName() + << " shadows another CopyOnChange property " << prop->getFullName()); continue; } - if(p->getTypeId() != prop->getTypeId() || groupName != otherGroupName) { + if (p->getTypeId() != prop->getTypeId() || groupName != otherGroupName) { parent->removeDynamicProperty(p->getName()); p = nullptr; } } } - if(!p) { + if (!p) { p = parent->addDynamicProperty(prop->getTypeId().getName(), - prop->getName(), groupName.c_str(), prop->getDocumentation()); + prop->getName(), + groupName.c_str(), + prop->getDocumentation()); std::unique_ptr pcopy(prop->Copy()); - Base::ObjectStatusLocker guard(Property::User3, p); - if(pcopy) { + Base::ObjectStatusLocker guard(Property::User3, p); + if (pcopy) { p->Paste(*pcopy); } p->setStatusValue(prop->getStatus()); @@ -780,99 +864,112 @@ bool LinkBaseExtension::setupCopyOnChange(DocumentObject *parent, DocumentObject newProps[p] = prop; } - if(checkExisting) { + if (checkExisting) { props.clear(); parent->getPropertyList(props); - for(auto prop : props) { - if(prop->getContainer()!=parent) + for (auto prop : props) { + if (prop->getContainer() != parent) { continue; + } auto gname = prop->getGroup(); - if(!gname || !boost::starts_with(gname, _GroupPrefix)) + if (!gname || !boost::starts_with(gname, _GroupPrefix)) { continue; - if(!newProps.count(prop)) + } + if (!newProps.count(prop)) { parent->removeDynamicProperty(prop->getName()); + } } } - if(!copyOnChangeConns) + if (!copyOnChangeConns) { return res; + } - for(const auto &v : newProps) { + for (const auto& v : newProps) { // sync configuration properties - copyOnChangeConns->push_back(v.second->signalChanged.connect([parent](const Property &prop) { - if(!prop.testStatus(Property::CopyOnChange)) - return; - auto p = parent->getPropertyByName(prop.getName()); - if(p && p->getTypeId()==prop.getTypeId()) { - std::unique_ptr pcopy(prop.Copy()); - // temperoray set Output to prevent touching - p->setStatus(Property::Output, true); - // temperoray block copy on change - Base::ObjectStatusLocker guard(Property::User3, p); - if(pcopy) - p->Paste(*pcopy); - p->setStatusValue(prop.getStatus()); - } - })); + copyOnChangeConns->push_back( + v.second->signalChanged.connect([parent](const Property& prop) { + if (!prop.testStatus(Property::CopyOnChange)) { + return; + } + auto p = parent->getPropertyByName(prop.getName()); + if (p && p->getTypeId() == prop.getTypeId()) { + std::unique_ptr pcopy(prop.Copy()); + // temperoray set Output to prevent touching + p->setStatus(Property::Output, true); + // temperoray block copy on change + Base::ObjectStatusLocker guard(Property::User3, p); + if (pcopy) { + p->Paste(*pcopy); + } + p->setStatusValue(prop.getStatus()); + } + })); } return res; } -void LinkBaseExtension::checkCopyOnChange(App::DocumentObject *parent, const App::Property &prop) +void LinkBaseExtension::checkCopyOnChange(App::DocumentObject* parent, const App::Property& prop) { - if(!parent || !parent->getDocument() - || parent->getDocument()->isPerformingTransaction()) + if (!parent || !parent->getDocument() || parent->getDocument()->isPerformingTransaction()) { return; + } auto linked = getLinkedObjectValue(); - if(!linked || getLinkCopyOnChangeValue()==CopyOnChangeDisabled - || !isCopyOnChangeProperty(parent,prop)) + if (!linked || getLinkCopyOnChangeValue() == CopyOnChangeDisabled + || !isCopyOnChangeProperty(parent, prop)) { return; + } - if(getLinkCopyOnChangeValue() == CopyOnChangeOwned || - (getLinkCopyOnChangeValue() == CopyOnChangeTracking - && linked != getLinkCopyOnChangeSourceValue())) - { + if (getLinkCopyOnChangeValue() == CopyOnChangeOwned + || (getLinkCopyOnChangeValue() == CopyOnChangeTracking + && linked != getLinkCopyOnChangeSourceValue())) { auto p = linked->getPropertyByName(prop.getName()); - if(p && p->getTypeId()==prop.getTypeId()) { + if (p && p->getTypeId() == prop.getTypeId()) { std::unique_ptr pcopy(prop.Copy()); - if(pcopy) + if (pcopy) { p->Paste(*pcopy); + } } return; } auto linkedProp = linked->getPropertyByName(prop.getName()); - if(!linkedProp || linkedProp->getTypeId()!=prop.getTypeId() || linkedProp->isSame(prop)) + if (!linkedProp || linkedProp->getTypeId() != prop.getTypeId() || linkedProp->isSame(prop)) { return; + } auto copied = makeCopyOnChange(); if (copied) { linkedProp = copied->getPropertyByName(prop.getName()); - if(linkedProp && linkedProp->getTypeId()==prop.getTypeId()) { + if (linkedProp && linkedProp->getTypeId() == prop.getTypeId()) { std::unique_ptr pcopy(prop.Copy()); - if(pcopy) + if (pcopy) { linkedProp->Paste(*pcopy); + } } } } -App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { +App::DocumentObject* LinkBaseExtension::makeCopyOnChange() +{ auto linked = getLinkedObjectValue(); - if (pauseCopyOnChange || !linked) + if (pauseCopyOnChange || !linked) { return nullptr; + } auto parent = getContainer(); auto srcobjs = getOnChangeCopyObjects(nullptr, linked); for (auto obj : srcobjs) { if (obj->testStatus(App::PartialObject)) { - FC_THROWM(Base::RuntimeError, "Cannot copy partial loaded object: " - << obj->getFullName()); + FC_THROWM(Base::RuntimeError, + "Cannot copy partial loaded object: " << obj->getFullName()); } } auto objs = parent->getDocument()->copyObject(srcobjs); - if(objs.empty()) + if (objs.empty()) { return nullptr; + } monitorOnChangeCopyObjects(srcobjs); @@ -881,13 +978,15 @@ App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { Base::StateLocker guard(pauseCopyOnChange); getLinkedObjectProperty()->setValue(linked); - if (getLinkCopyOnChangeValue() == CopyOnChangeEnabled) + if (getLinkCopyOnChangeValue() == CopyOnChangeEnabled) { getLinkCopyOnChangeProperty()->setValue(CopyOnChangeOwned); + } if (auto prop = getLinkCopyOnChangeGroupProperty()) { if (auto obj = prop->getValue()) { - if (obj->isAttachedToDocument() && obj->getDocument()) + if (obj->isAttachedToDocument() && obj->getDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } auto group = new LinkGroup; group->LinkMode.setValue(LinkModeAutoDelete); @@ -905,328 +1004,410 @@ App::DocumentObject *LinkBaseExtension::makeCopyOnChange() { return linked; } -void LinkBaseExtension::monitorOnChangeCopyObjects( - const std::vector &objs) +void LinkBaseExtension::monitorOnChangeCopyObjects(const std::vector& objs) { copyOnChangeSrcConns.clear(); - if (getLinkCopyOnChangeValue() == CopyOnChangeDisabled) + if (getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; - for(auto obj : objs) { + } + for (auto obj : objs) { obj->setStatus(App::ObjectStatus::TouchOnColorChange, true); - copyOnChangeSrcConns.emplace_back(obj->signalChanged.connect( - [this](const DocumentObject &, const Property &) { + copyOnChangeSrcConns.emplace_back( + obj->signalChanged.connect([this](const DocumentObject&, const Property&) { if (auto prop = this->getLinkCopyOnChangeTouchedProperty()) { - if (this->getLinkCopyOnChangeValue() != CopyOnChangeDisabled) + if (this->getLinkCopyOnChangeValue() != CopyOnChangeDisabled) { prop->setValue(true); + } } })); } } -App::GroupExtension *LinkBaseExtension::linkedPlainGroup() const { - if(!mySubElements.empty() && !mySubElements[0].empty()) +App::GroupExtension* LinkBaseExtension::linkedPlainGroup() const +{ + if (!mySubElements.empty() && !mySubElements[0].empty()) { return nullptr; + } auto linked = getTrueLinkedObject(false); - if(!linked) + if (!linked) { return nullptr; - return linked->getExtensionByType(true,false); + } + return linked->getExtensionByType(true, false); } -App::PropertyLinkList *LinkBaseExtension::_getElementListProperty() const { +App::PropertyLinkList* LinkBaseExtension::_getElementListProperty() const +{ auto group = linkedPlainGroup(); - if(group) + if (group) { return &group->Group; + } return const_cast(getElementListProperty()); } -const std::vector &LinkBaseExtension::_getElementListValue() const { - if(_ChildCache.getSize()) +const std::vector& LinkBaseExtension::_getElementListValue() const +{ + if (_ChildCache.getSize()) { return _ChildCache.getValues(); - if(getElementListProperty()) + } + if (getElementListProperty()) { return getElementListProperty()->getValues(); + } static const std::vector empty; return empty; } -App::PropertyBool *LinkBaseExtension::_getShowElementProperty() const { +App::PropertyBool* LinkBaseExtension::_getShowElementProperty() const +{ auto prop = getShowElementProperty(); - if(prop && !linkedPlainGroup()) + if (prop && !linkedPlainGroup()) { return const_cast(prop); + } return nullptr; } -bool LinkBaseExtension::_getShowElementValue() const { +bool LinkBaseExtension::_getShowElementValue() const +{ auto prop = _getShowElementProperty(); - if(prop) + if (prop) { return prop->getValue(); + } return true; } -App::PropertyInteger *LinkBaseExtension::_getElementCountProperty() const { +App::PropertyInteger* LinkBaseExtension::_getElementCountProperty() const +{ auto prop = getElementCountProperty(); - if(prop && !linkedPlainGroup()) + if (prop && !linkedPlainGroup()) { return const_cast(prop); + } return nullptr; } -int LinkBaseExtension::_getElementCountValue() const { +int LinkBaseExtension::_getElementCountValue() const +{ auto prop = _getElementCountProperty(); - if(prop) + if (prop) { return prop->getValue(); + } return 0; } -bool LinkBaseExtension::extensionHasChildElement() const { - if(!_getElementListValue().empty() - || (_getElementCountValue() && _getShowElementValue())) +bool LinkBaseExtension::extensionHasChildElement() const +{ + if (!_getElementListValue().empty() || (_getElementCountValue() && _getShowElementValue())) { return true; - if (getLinkClaimChildValue()) + } + if (getLinkClaimChildValue()) { return false; - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) { - if(linked->hasChildElement()) + } + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { + if (linked->hasChildElement()) { return true; + } } return false; } -int LinkBaseExtension::extensionSetElementVisible(const char *element, bool visible) { - int index = _getShowElementValue()?getElementIndex(element):getArrayIndex(element); - if(index>=0) { +int LinkBaseExtension::extensionSetElementVisible(const char* element, bool visible) +{ + int index = _getShowElementValue() ? getElementIndex(element) : getArrayIndex(element); + if (index >= 0) { auto propElementVis = getVisibilityListProperty(); - if(!propElementVis || !element || !element[0]) + if (!propElementVis || !element || !element[0]) { return -1; - if(propElementVis->getSize()<=index) { - if(visible) + } + if (propElementVis->getSize() <= index) { + if (visible) { return 1; - propElementVis->setSize(index+1, true); - } - propElementVis->setStatus(Property::User3,true); - propElementVis->set1Value(index,visible); - propElementVis->setStatus(Property::User3,false); - const auto &elements = _getElementListValue(); - if(index<(int)elements.size()) { - if(!visible) + } + propElementVis->setSize(index + 1, true); + } + propElementVis->setStatus(Property::User3, true); + propElementVis->set1Value(index, visible); + propElementVis->setStatus(Property::User3, false); + const auto& elements = _getElementListValue(); + if (index < (int)elements.size()) { + if (!visible) { myHiddenElements.insert(elements[index]); - else + } + else { myHiddenElements.erase(elements[index]); + } } return 1; } - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) - return linked->setElementVisible(element,visible); + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { + return linked->setElementVisible(element, visible); + } return -1; } -int LinkBaseExtension::extensionIsElementVisible(const char *element) { - int index = _getShowElementValue()?getElementIndex(element):getArrayIndex(element); - if(index>=0) { +int LinkBaseExtension::extensionIsElementVisible(const char* element) +{ + int index = _getShowElementValue() ? getElementIndex(element) : getArrayIndex(element); + if (index >= 0) { auto propElementVis = getVisibilityListProperty(); - if(propElementVis) { - if(propElementVis->getSize()<=index || propElementVis->getValues()[index]) + if (propElementVis) { + if (propElementVis->getSize() <= index || propElementVis->getValues()[index]) { return 1; + } return 0; } return -1; } - DocumentObject *linked = getTrueLinkedObject(false); - if(linked) + DocumentObject* linked = getTrueLinkedObject(false); + if (linked) { return linked->isElementVisible(element); + } return -1; } -const DocumentObject *LinkBaseExtension::getContainer() const { +const DocumentObject* LinkBaseExtension::getContainer() const +{ auto ext = getExtendedContainer(); - if(!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) - LINK_THROW(Base::RuntimeError,"Link: container not derived from document object"); - return static_cast(ext); + if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); + } + return static_cast(ext); } -DocumentObject *LinkBaseExtension::getContainer(){ +DocumentObject* LinkBaseExtension::getContainer() +{ auto ext = getExtendedContainer(); - if(!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) - LINK_THROW(Base::RuntimeError,"Link: container not derived from document object"); - return static_cast(ext); + if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); + } + return static_cast(ext); } -DocumentObject *LinkBaseExtension::getLink(int depth) const{ - if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) +DocumentObject* LinkBaseExtension::getLink(int depth) const +{ + if (!GetApplication().checkLinkDepth(depth, MessageOption::Error)) { return nullptr; - if(getLinkedObjectProperty()) + } + if (getLinkedObjectProperty()) { return getLinkedObjectValue(); + } return nullptr; } -int LinkBaseExtension::getArrayIndex(const char *subname, const char **psubname) { - if(!subname || Data::isMappedElement(subname)) +int LinkBaseExtension::getArrayIndex(const char* subname, const char** psubname) +{ + if (!subname || Data::isMappedElement(subname)) { return -1; - const char *dot = strchr(subname,'.'); - if(!dot) dot= subname+strlen(subname); - if(dot == subname) + } + const char* dot = strchr(subname, '.'); + if (!dot) { + dot = subname + strlen(subname); + } + if (dot == subname) { return -1; + } int idx = 0; - for(const char *c=subname;c!=dot;++c) { - if(!isdigit(*c)) + for (const char* c = subname; c != dot; ++c) { + if (!isdigit(*c)) { return -1; - idx = idx*10 + *c -'0'; + } + idx = idx * 10 + *c - '0'; } - if(psubname) { - if(*dot) - *psubname = dot+1; - else + if (psubname) { + if (*dot) { + *psubname = dot + 1; + } + else { *psubname = dot; + } } return idx; } -int LinkBaseExtension::getElementIndex(const char *subname, const char **psubname) const { - if(!subname || Data::isMappedElement(subname)) +int LinkBaseExtension::getElementIndex(const char* subname, const char** psubname) const +{ + if (!subname || Data::isMappedElement(subname)) { return -1; + } int idx = -1; - const char *dot = strchr(subname,'.'); - if(!dot) dot= subname+strlen(subname); + const char* dot = strchr(subname, '.'); + if (!dot) { + dot = subname + strlen(subname); + } - if(isdigit(subname[0])) { + if (isdigit(subname[0])) { // If the name start with digits, treat as index reference - idx = getArrayIndex(subname,nullptr); - if(idx<0) + idx = getArrayIndex(subname, nullptr); + if (idx < 0) { return -1; - if(_getElementCountProperty()) { - if(idx>=_getElementCountValue()) + } + if (_getElementCountProperty()) { + if (idx >= _getElementCountValue()) { return -1; - }else if(idx>=(int)_getElementListValue().size()) + } + } + else if (idx >= (int)_getElementListValue().size()) { return -1; - }else if(!_getShowElementValue() && _getElementCountValue()) { + } + } + else if (!_getShowElementValue() && _getElementCountValue()) { // If elements are collapsed, we check first for LinkElement naming // pattern, which is the owner object name + "_i" + index - const char *name = subname[0]=='$'?subname+1:subname; + const char* name = subname[0] == '$' ? subname + 1 : subname; auto owner = getContainer(); - if(owner && owner->isAttachedToDocument()) { + if (owner && owner->isAttachedToDocument()) { std::string ownerName(owner->getNameInDocument()); ownerName += '_'; - if(boost::algorithm::starts_with(name,ownerName.c_str())) { - for(const char *txt=dot-1;txt>=name+ownerName.size();--txt) { - if(*txt == 'i') { - idx = getArrayIndex(txt+1,nullptr); - if(idx<0 || idx>=_getElementCountValue()) + if (boost::algorithm::starts_with(name, ownerName.c_str())) { + for (const char* txt = dot - 1; txt >= name + ownerName.size(); --txt) { + if (*txt == 'i') { + idx = getArrayIndex(txt + 1, nullptr); + if (idx < 0 || idx >= _getElementCountValue()) { idx = -1; + } break; } - if(!isdigit(*txt)) + if (!isdigit(*txt)) { break; + } } } } - if(idx<0) { + if (idx < 0) { // Then check for the actual linked object's name or label, and // redirect that reference to the first array element auto linked = getTrueLinkedObject(false); - if(!linked || !linked->isAttachedToDocument()) + if (!linked || !linked->isAttachedToDocument()) { return -1; - if(subname[0]=='$') { - CharRange sub(subname+1, dot); - if (boost::equals(sub, linked->Label.getValue())) + } + if (subname[0] == '$') { + CharRange sub(subname + 1, dot); + if (boost::equals(sub, linked->Label.getValue())) { idx = 0; - } else { + } + } + else { CharRange sub(subname, dot); - if (boost::equals(sub, linked->getNameInDocument())) + if (boost::equals(sub, linked->getNameInDocument())) { idx = 0; + } } - if(idx<0) { + if (idx < 0) { // Lastly, try to get sub object directly from the linked object - auto sobj = linked->getSubObject(std::string(subname, dot-subname+1).c_str()); - if(!sobj) + auto sobj = linked->getSubObject(std::string(subname, dot - subname + 1).c_str()); + if (!sobj) { return -1; - if(psubname) + } + if (psubname) { *psubname = subname; + } return 0; } } - }else if(subname[0]!='$') { + } + else if (subname[0] != '$') { // Try search by element objects' name - std::string name(subname,dot); - if(_ChildCache.getSize()) { - auto obj=_ChildCache.findUsingMap(name,&idx); - if(obj) { - auto group = obj->getExtensionByType(true,false); - if(group) { - int nidx = getElementIndex(dot+1,psubname); - if(nidx >= 0) + std::string name(subname, dot); + if (_ChildCache.getSize()) { + auto obj = _ChildCache.findUsingMap(name, &idx); + if (obj) { + auto group = obj->getExtensionByType(true, false); + if (group) { + int nidx = getElementIndex(dot + 1, psubname); + if (nidx >= 0) { return nidx; + } } } - } else if(getElementListProperty()) - getElementListProperty()->find(name.c_str(),&idx); - if(idx<0) + } + else if (getElementListProperty()) { + getElementListProperty()->find(name.c_str(), &idx); + } + if (idx < 0) { return -1; - }else { + } + } + else { // Try search by label if the reference name start with '$' ++subname; - std::string name(subname,dot-subname); - const auto &elements = _getElementListValue(); - if(enableLabelCache) { - if(myLabelCache.empty()) + std::string name(subname, dot - subname); + const auto& elements = _getElementListValue(); + if (enableLabelCache) { + if (myLabelCache.empty()) { cacheChildLabel(1); + } auto it = myLabelCache.find(name); - if(it == myLabelCache.end()) + if (it == myLabelCache.end()) { return -1; + } idx = it->second; - }else{ + } + else { idx = 0; - for(auto element : elements) { - if(element->Label.getStrValue() == name) + for (auto element : elements) { + if (element->Label.getStrValue() == name) { break; + } ++idx; } } - if(idx<0 || idx>=(int)elements.size()) + if (idx < 0 || idx >= (int)elements.size()) { return -1; + } auto obj = elements[idx]; - if(obj && _ChildCache.getSize()) { - auto group = obj->getExtensionByType(true,false); - if(group) { - int nidx = getElementIndex(dot+1,psubname); - if(nidx >= 0) + if (obj && _ChildCache.getSize()) { + auto group = obj->getExtensionByType(true, false); + if (group) { + int nidx = getElementIndex(dot + 1, psubname); + if (nidx >= 0) { return nidx; + } } } } - if(psubname) - *psubname = dot[0]?dot+1:dot; + if (psubname) { + *psubname = dot[0] ? dot + 1 : dot; + } return idx; } -void LinkBaseExtension::elementNameFromIndex(int idx, std::ostream &ss) const { - const auto &elements = _getElementListValue(); - if(idx < 0 || idx >= (int)elements.size()) +void LinkBaseExtension::elementNameFromIndex(int idx, std::ostream& ss) const +{ + const auto& elements = _getElementListValue(); + if (idx < 0 || idx >= (int)elements.size()) { return; + } auto obj = elements[idx]; - if(_ChildCache.getSize()) { + if (_ChildCache.getSize()) { auto group = GroupExtension::getGroupOfObject(obj); - if(group && _ChildCache.find(group->getNameInDocument(),&idx)) - elementNameFromIndex(idx,ss); + if (group && _ChildCache.find(group->getNameInDocument(), &idx)) { + elementNameFromIndex(idx, ss); + } } ss << obj->getNameInDocument() << '.'; } -Base::Vector3d LinkBaseExtension::getScaleVector() const { - if(getScaleVectorProperty()) +Base::Vector3d LinkBaseExtension::getScaleVector() const +{ + if (getScaleVectorProperty()) { return getScaleVectorValue(); + } double s = getScaleValue(); - return Base::Vector3d(s,s,s); + return Base::Vector3d(s, s, s); } -Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const { +Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const +{ Base::Matrix4D mat; - if(transform) { - if(getLinkPlacementProperty()) + if (transform) { + if (getLinkPlacementProperty()) { mat = getLinkPlacementValue().toMatrix(); - else if(getPlacementProperty()) + } + else if (getPlacementProperty()) { mat = getPlacementValue().toMatrix(); + } } - if(getScaleProperty() || getScaleVectorProperty()) { + if (getScaleProperty() || getScaleVectorProperty()) { Base::Matrix4D s; s.scale(getScaleVector()); mat *= s; @@ -1234,45 +1415,52 @@ Base::Matrix4D LinkBaseExtension::getTransform(bool transform) const { return mat; } -bool LinkBaseExtension::extensionGetSubObjects(std::vector &ret, int reason) const { - if(!getLinkedObjectProperty() && getElementListProperty()) { - for(auto obj : getElementListProperty()->getValues()) { - if(obj && obj->isAttachedToDocument()) { +bool LinkBaseExtension::extensionGetSubObjects(std::vector& ret, int reason) const +{ + if (!getLinkedObjectProperty() && getElementListProperty()) { + for (auto obj : getElementListProperty()->getValues()) { + if (obj && obj->isAttachedToDocument()) { std::string name(obj->getNameInDocument()); - name+='.'; + name += '.'; ret.push_back(name); } } return true; } - if(mySubElements.empty() || mySubElements[0].empty()) { - DocumentObject *linked = getTrueLinkedObject(true); - if(linked) { - if(!_getElementCountValue()) + if (mySubElements.empty() || mySubElements[0].empty()) { + DocumentObject* linked = getTrueLinkedObject(true); + if (linked) { + if (!_getElementCountValue()) { ret = linked->getSubObjects(reason); - else{ + } + else { char index[30]; - for(int i=0,count=_getElementCountValue();i1) { + } + else if (mySubElements.size() > 1) { ret = mySubElements; } return true; } -bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj, Base::Matrix4D *mat, bool transform, int depth) const +bool LinkBaseExtension::extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj, + Base::Matrix4D* mat, + bool transform, + int depth) const { ret = nullptr; auto obj = getContainer(); - if(!subname || !subname[0]) { + if (!subname || !subname[0]) { ret = const_cast(obj); Base::Matrix4D _mat; - if(mat) { + if (mat) { // 'mat' here is used as an output to return the accumulated // transformation up until this object. Since 'subname' is empty // here, it means the we are at the end of the hierarchy. We shall @@ -1281,61 +1469,73 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // Think of it this way, the transformation along object hierarchy // is public, while transformation through linkage is private to // link itself. - if(transform) { - if(getLinkPlacementProperty()) + if (transform) { + if (getLinkPlacementProperty()) { *mat *= getLinkPlacementValue().toMatrix(); - else if(getPlacementProperty()) + } + else if (getPlacementProperty()) { *mat *= getPlacementValue().toMatrix(); + } } _mat = *mat; } - if(pyObj && !_getElementCountValue() - && _getElementListValue().empty() && mySubElements.size()<=1) - { + if (pyObj && !_getElementCountValue() && _getElementListValue().empty() + && mySubElements.size() <= 1) { // Scale will be included here - if(getScaleProperty() || getScaleVectorProperty()) { + if (getScaleProperty() || getScaleVectorProperty()) { Base::Matrix4D s; s.scale(getScaleVector()); _mat *= s; } - auto linked = getTrueLinkedObject(false,&_mat,depth); - if(linked && linked!=obj) { - linked->getSubObject(mySubElements.empty()?nullptr:mySubElements.front().c_str(), - pyObj,&_mat,false,depth+1); - checkGeoElementMap(obj,linked,pyObj,nullptr); + auto linked = getTrueLinkedObject(false, &_mat, depth); + if (linked && linked != obj) { + linked->getSubObject(mySubElements.empty() ? nullptr + : mySubElements.front().c_str(), + pyObj, + &_mat, + false, + depth + 1); + checkGeoElementMap(obj, linked, pyObj, nullptr); } } return true; } - if(mat) *mat *= getTransform(transform); + if (mat) { + *mat *= getTransform(transform); + } - //DocumentObject *element = 0; + // DocumentObject *element = 0; bool isElement = false; - int idx = getElementIndex(subname,&subname); - if(idx>=0) { - const auto &elements = _getElementListValue(); - if(!elements.empty()) { - if(idx>=(int)elements.size() || !elements[idx] || !elements[idx]->isAttachedToDocument()) + int idx = getElementIndex(subname, &subname); + if (idx >= 0) { + const auto& elements = _getElementListValue(); + if (!elements.empty()) { + if (idx >= (int)elements.size() || !elements[idx] + || !elements[idx]->isAttachedToDocument()) { return true; - ret = elements[idx]->getSubObject(subname,pyObj,mat,true,depth+1); + } + ret = elements[idx]->getSubObject(subname, pyObj, mat, true, depth + 1); // do not resolve the link if this element is the last referenced object - if(!subname || Data::isMappedElement(subname) || !strchr(subname,'.')) + if (!subname || Data::isMappedElement(subname) || !strchr(subname, '.')) { ret = elements[idx]; + } return true; } int elementCount = _getElementCountValue(); - if(idx>=elementCount) + if (idx >= elementCount) { return true; + } isElement = true; - if(mat) { + if (mat) { auto placementList = getPlacementListProperty(); - if(placementList && placementList->getSize()>idx) + if (placementList && placementList->getSize() > idx) { *mat *= (*placementList)[idx].toMatrix(); + } auto scaleList = getScaleListProperty(); - if(scaleList && scaleList->getSize()>idx) { + if (scaleList && scaleList->getSize() > idx) { Base::Matrix4D s; s.scale((*scaleList)[idx]); *mat *= s; @@ -1343,9 +1543,10 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * } } - auto linked = getTrueLinkedObject(false,mat,depth); - if(!linked || linked==obj) + auto linked = getTrueLinkedObject(false, mat, depth); + if (!linked || linked == obj) { return true; + } Base::Matrix4D matNext; @@ -1353,20 +1554,25 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // claimed as the first child. Regardless of the current value of // LinkClaimChild, we must accept sub-object path that contains the linked // object, because other link property may store such reference. - if (const char* dot=strchr(subname,'.')) { + if (const char* dot = strchr(subname, '.')) { auto group = getLinkCopyOnChangeGroupValue(); if (subname[0] == '$') { - CharRange sub(subname+1,dot); - if (group && boost::equals(sub, group->Label.getValue())) + CharRange sub(subname + 1, dot); + if (group && boost::equals(sub, group->Label.getValue())) { linked = group; - else if(!boost::equals(sub, linked->Label.getValue())) + } + else if (!boost::equals(sub, linked->Label.getValue())) { dot = nullptr; - } else { - CharRange sub(subname,dot); - if (group && boost::equals(sub, group->getNameInDocument())) + } + } + else { + CharRange sub(subname, dot); + if (group && boost::equals(sub, group->getNameInDocument())) { linked = group; - else if (!boost::equals(sub, linked->getNameInDocument())) + } + else if (!boost::equals(sub, linked->getNameInDocument())) { dot = nullptr; + } } if (dot) { // Because of external linked object, It is possible for and @@ -1374,127 +1580,153 @@ bool LinkBaseExtension::extensionGetSubObject(DocumentObject *&ret, const char * // as the parent object. To resolve this potential ambiguity, // try assuming the current subname is referring to the parent // (i.e. the linked object), and if it fails, try again below. - if(mat) matNext = *mat; - ret = linked->getSubObject(dot+1,pyObj,mat?&matNext:nullptr,false,depth+1); - if (ret && dot[1]) - subname = dot+1; + if (mat) { + matNext = *mat; + } + ret = linked->getSubObject(dot + 1, pyObj, mat ? &matNext : nullptr, false, depth + 1); + if (ret && dot[1]) { + subname = dot + 1; + } } } if (!ret) { - if(mat) matNext = *mat; - ret = linked->getSubObject(subname,pyObj,mat?&matNext:nullptr,false,depth+1); + if (mat) { + matNext = *mat; + } + ret = linked->getSubObject(subname, pyObj, mat ? &matNext : nullptr, false, depth + 1); } std::string postfix; - if(ret) { + if (ret) { // do not resolve the link if we are the last referenced object - if(subname && !Data::isMappedElement(subname) && strchr(subname,'.')) { - if(mat) + if (subname && !Data::isMappedElement(subname) && strchr(subname, '.')) { + if (mat) { *mat = matNext; + } } // This is a useless check as 'element' is never set to a value other than null - //else if(element) { + // else if(element) { // ret = element; //} - else if(!isElement) { + else if (!isElement) { ret = const_cast(obj); } else { - if(idx) { + if (idx) { postfix = Data::POSTFIX_INDEX; postfix += std::to_string(idx); } - if(mat) + if (mat) { *mat = matNext; + } } } - checkGeoElementMap(obj,linked,pyObj,!postfix.empty()?postfix.c_str():nullptr); + checkGeoElementMap(obj, linked, pyObj, !postfix.empty() ? postfix.c_str() : nullptr); return true; } -void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject *obj, - const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const +void LinkBaseExtension::checkGeoElementMap(const App::DocumentObject* obj, + const App::DocumentObject* linked, + PyObject** pyObj, + const char* postfix) const { - if(!pyObj || !*pyObj || (!postfix && obj->getDocument()==linked->getDocument()) || - !PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type)) + if (!pyObj || !*pyObj || (!postfix && obj->getDocument() == linked->getDocument()) + || !PyObject_TypeCheck(*pyObj, &Data::ComplexGeoDataPy::Type)) { return; + } -// auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); -// geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix); + // auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); + // geoData->reTagElementMap(obj->getID(),obj->getDocument()->Hasher,postfix); auto geoData = static_cast(*pyObj)->getComplexGeoDataPtr(); std::string _postfix; if (linked && obj && linked->getDocument() != obj->getDocument()) { _postfix = Data::POSTFIX_EXTERNAL_TAG; if (postfix) { - if (!boost::starts_with(postfix, Data::ComplexGeoData::elementMapPrefix())) + if (!boost::starts_with(postfix, Data::ComplexGeoData::elementMapPrefix())) { _postfix += Data::ComplexGeoData::elementMapPrefix(); + } _postfix += postfix; } postfix = _postfix.c_str(); } - geoData->reTagElementMap(obj->getID(),obj->getDocument()->getStringHasher(),postfix); - + geoData->reTagElementMap(obj->getID(), obj->getDocument()->getStringHasher(), postfix); } -void LinkBaseExtension::onExtendedUnsetupObject() { - if(!getElementListProperty()) +void LinkBaseExtension::onExtendedUnsetupObject() +{ + if (!getElementListProperty()) { return; + } detachElements(); if (auto obj = getLinkCopyOnChangeGroupValue()) { - if(obj->isAttachedToDocument() && !obj->isRemoving()) + if (obj->isAttachedToDocument() && !obj->isRemoving()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } -DocumentObject *LinkBaseExtension::getTrueLinkedObject( - bool recurse, Base::Matrix4D *mat, int depth, bool noElement) const +DocumentObject* LinkBaseExtension::getTrueLinkedObject(bool recurse, + Base::Matrix4D* mat, + int depth, + bool noElement) const { - if(noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId()) - && !static_cast(this)->canDelete()) - { + if (noElement && extensionIsDerivedFrom(LinkElement::getExtensionClassTypeId()) + && !static_cast(this)->canDelete()) { return nullptr; } auto ret = getLink(depth); - if(!ret) + if (!ret) { return nullptr; + } bool transform = linkTransform(); - const char *subname = getSubName(); - if(subname || (mat && transform)) { - ret = ret->getSubObject(subname,nullptr,mat,transform,depth+1); + const char* subname = getSubName(); + if (subname || (mat && transform)) { + ret = ret->getSubObject(subname, nullptr, mat, transform, depth + 1); transform = false; } - if(ret && recurse) - ret = ret->getLinkedObject(recurse,mat,transform,depth+1); - if(ret && !ret->isAttachedToDocument()) + if (ret && recurse) { + ret = ret->getLinkedObject(recurse, mat, transform, depth + 1); + } + if (ret && !ret->isAttachedToDocument()) { return nullptr; + } return ret; } -bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject *&ret, - bool recurse, Base::Matrix4D *mat, bool transform, int depth) const +bool LinkBaseExtension::extensionGetLinkedObject(DocumentObject*& ret, + bool recurse, + Base::Matrix4D* mat, + bool transform, + int depth) const { - if(mat) + if (mat) { *mat *= getTransform(transform); + } ret = nullptr; - if(!_getElementCountValue()) - ret = getTrueLinkedObject(recurse,mat,depth); - if(!ret) + if (!_getElementCountValue()) { + ret = getTrueLinkedObject(recurse, mat, depth); + } + if (!ret) { ret = const_cast(getContainer()); + } // always return true to indicate we've handled getLinkObject() call return true; } -void LinkBaseExtension::extensionOnChanged(const Property *prop) { +void LinkBaseExtension::extensionOnChanged(const Property* prop) +{ auto parent = getContainer(); - if(parent && !parent->isRestoring() && prop && !prop->testStatus(Property::User3)) - update(parent,prop); + if (parent && !parent->isRestoring() && prop && !prop->testStatus(Property::User3)) { + update(parent, prop); + } inherited::extensionOnChanged(prop); } -void LinkBaseExtension::parseSubName() const { +void LinkBaseExtension::parseSubName() const +{ // If user has ever linked to some sub-element, the Link shall always accept // sub-element linking in the future, which affects how ViewProviderLink // dropObjectEx() behave. So we will push an empty string later even if no @@ -1503,132 +1735,153 @@ void LinkBaseExtension::parseSubName() const { mySubElements.clear(); mySubName.clear(); auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); - if(!xlink || xlink->getSubValues().empty()) { - if(hasSubElement) + if (!xlink || xlink->getSubValues().empty()) { + if (hasSubElement) { mySubElements.emplace_back(""); + } return; } - const auto &subs = xlink->getSubValues(); + const auto& subs = xlink->getSubValues(); auto subname = subs.front().c_str(); auto element = Data::findElementName(subname); - if(!element || !element[0]) { + if (!element || !element[0]) { mySubName = subs[0]; - if(hasSubElement) + if (hasSubElement) { mySubElements.emplace_back(""); + } return; } mySubElements.emplace_back(element); - mySubName = std::string(subname,element-subname); - for(std::size_t i=1;i(true,false); - if(group && &prop == &group->Group) +void LinkBaseExtension::slotChangedPlainGroup(const App::DocumentObject& obj, + const App::Property& prop) +{ + auto group = obj.getExtensionByType(true, false); + if (group && &prop == &group->Group) { updateGroup(); + } } -void LinkBaseExtension::updateGroup() { +void LinkBaseExtension::updateGroup() +{ std::vector groups; std::unordered_set groupSet; auto group = linkedPlainGroup(); - if(group) { + if (group) { groups.push_back(group); groupSet.insert(group->getExtendedObject()); - }else{ - for(auto o : getElementListProperty()->getValues()) { - if(!o || !o->isAttachedToDocument()) + } + else { + for (auto o : getElementListProperty()->getValues()) { + if (!o || !o->isAttachedToDocument()) { continue; - auto ext = o->getExtensionByType(true,false); - if(ext) { + } + auto ext = o->getExtensionByType(true, false); + if (ext) { groups.push_back(ext); groupSet.insert(o); } } } std::vector children; - if(!groups.empty()) { + if (!groups.empty()) { children = getElementListValue(); - std::set childSet(children.begin(),children.end()); - for(auto ext : groups) { + std::set childSet(children.begin(), children.end()); + for (auto ext : groups) { auto group = ext->getExtendedObject(); - auto &conn = plainGroupConns[group]; - if(!conn.connected()) { - FC_LOG("new group connection " << getExtendedObject()->getFullName() - << " -> " << group->getFullName()); - //NOLINTBEGIN + auto& conn = plainGroupConns[group]; + if (!conn.connected()) { + FC_LOG("new group connection " << getExtendedObject()->getFullName() << " -> " + << group->getFullName()); + // NOLINTBEGIN conn = group->signalChanged.connect( - std::bind(&LinkBaseExtension::slotChangedPlainGroup,this,sp::_1,sp::_2)); - //NOLINTEND + std::bind(&LinkBaseExtension::slotChangedPlainGroup, this, sp::_1, sp::_2)); + // NOLINTEND } std::size_t count = children.size(); - ext->getAllChildren(children,childSet); - for(;countgetAllChildren(children, childSet); + for (; count < children.size(); ++count) { auto child = children[count]; - if(!child->getExtensionByType(true,false)) + if (!child->getExtensionByType(true, false)) { continue; + } groupSet.insert(child); - auto &conn = plainGroupConns[child]; - if(!conn.connected()) { - FC_LOG("new group connection " << getExtendedObject()->getFullName() - << " -> " << child->getFullName()); - //NOLINTBEGIN + auto& conn = plainGroupConns[child]; + if (!conn.connected()) { + FC_LOG("new group connection " << getExtendedObject()->getFullName() << " -> " + << child->getFullName()); + // NOLINTBEGIN conn = child->signalChanged.connect( - std::bind(&LinkBaseExtension::slotChangedPlainGroup,this,sp::_1,sp::_2)); - //NOLINTEND + std::bind(&LinkBaseExtension::slotChangedPlainGroup, this, sp::_1, sp::_2)); + // NOLINTEND } } } } - for(auto it=plainGroupConns.begin();it!=plainGroupConns.end();) { - if(!groupSet.count(it->first)) + for (auto it = plainGroupConns.begin(); it != plainGroupConns.end();) { + if (!groupSet.count(it->first)) { it = plainGroupConns.erase(it); - else + } + else { ++it; + } } - if(children != _ChildCache.getValues()) + if (children != _ChildCache.getValues()) { _ChildCache.setValue(children); + } } -void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop) { - if(!prop) +void LinkBaseExtension::update(App::DocumentObject* parent, const Property* prop) +{ + if (!prop) { return; + } - if(prop == getLinkPlacementProperty() || prop == getPlacementProperty()) { + if (prop == getLinkPlacementProperty() || prop == getPlacementProperty()) { auto src = getLinkPlacementProperty(); auto dst = getPlacementProperty(); - if(src!=prop) std::swap(src,dst); - if(src && dst) { - dst->setStatus(Property::User3,true); + if (src != prop) { + std::swap(src, dst); + } + if (src && dst) { + dst->setStatus(Property::User3, true); dst->setValue(src->getValue()); - dst->setStatus(Property::User3,false); + dst->setStatus(Property::User3, false); } - }else if(prop == getScaleProperty()) { - if(!prop->testStatus(Property::User3) && getScaleVectorProperty()) { + } + else if (prop == getScaleProperty()) { + if (!prop->testStatus(Property::User3) && getScaleVectorProperty()) { auto s = getScaleValue(); auto p = getScaleVectorProperty(); - p->setStatus(Property::User3,true); - p->setValue(s,s,s); - p->setStatus(Property::User3,false); - } - }else if(prop == getScaleVectorProperty()) { - if(!prop->testStatus(Property::User3) && getScaleProperty()) { - const auto &v = getScaleVectorValue(); - if(v.x == v.y && v.x == v.z) { + p->setStatus(Property::User3, true); + p->setValue(s, s, s); + p->setStatus(Property::User3, false); + } + } + else if (prop == getScaleVectorProperty()) { + if (!prop->testStatus(Property::User3) && getScaleProperty()) { + const auto& v = getScaleVectorValue(); + if (v.x == v.y && v.x == v.z) { auto p = getScaleProperty(); - p->setStatus(Property::User3,true); + p->setStatus(Property::User3, true); p->setValue(v.x); - p->setStatus(Property::User3,false); + p->setStatus(Property::User3, false); } } - }else if(prop == _getShowElementProperty()) { - if(_getShowElementValue()) - update(parent,_getElementCountProperty()); + } + else if (prop == _getShowElementProperty()) { + if (_getShowElementValue()) { + update(parent, _getElementCountProperty()); + } else { auto objs = getElementListValue(); @@ -1637,14 +1890,15 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop placements.reserve(objs.size()); std::vector scales; scales.reserve(objs.size()); - for(auto obj : objs) { + for (auto obj : objs) { auto element = freecad_dynamic_cast(obj); - if(element) { + if (element) { placements.push_back(element->Placement.getValue()); scales.push_back(element->getScaleVector()); - }else{ + } + else { placements.emplace_back(); - scales.emplace_back(1,1,1); + scales.emplace_back(1, 1, 1); } } // touch the property again to make sure view provider has been @@ -1655,65 +1909,76 @@ void LinkBaseExtension::update(App::DocumentObject *parent, const Property *prop getElementListProperty()->setValues(std::vector()); - if(getPlacementListProperty()) { - getPlacementListProperty()->setStatus(Property::User3, getScaleListProperty() != nullptr); + if (getPlacementListProperty()) { + getPlacementListProperty()->setStatus(Property::User3, + getScaleListProperty() != nullptr); getPlacementListProperty()->setValue(placements); getPlacementListProperty()->setStatus(Property::User3, false); } - if(getScaleListProperty()) + if (getScaleListProperty()) { getScaleListProperty()->setValue(scales); + } - for(auto obj : objs) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : objs) { + if (obj && obj->isAttachedToDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } - }else if(prop == _getElementCountProperty()) { - size_t elementCount = getElementCountValue()<0?0:(size_t)getElementCountValue(); + } + else if (prop == _getElementCountProperty()) { + size_t elementCount = getElementCountValue() < 0 ? 0 : (size_t)getElementCountValue(); auto propVis = getVisibilityListProperty(); - if(propVis) { - if(propVis->getSize()>(int)elementCount) - propVis->setSize(getElementCountValue(),true); + if (propVis) { + if (propVis->getSize() > (int)elementCount) { + propVis->setSize(getElementCountValue(), true); + } } - if(!_getShowElementValue()) { - if(getScaleListProperty()) { + if (!_getShowElementValue()) { + if (getScaleListProperty()) { auto scales = getScaleListValue(); - scales.resize(elementCount,Base::Vector3d(1,1,1)); - getScaleListProperty()->setStatus(Property::User3,true); + scales.resize(elementCount, Base::Vector3d(1, 1, 1)); + getScaleListProperty()->setStatus(Property::User3, true); getScaleListProperty()->setValue(scales); - getScaleListProperty()->setStatus(Property::User3,false); + getScaleListProperty()->setStatus(Property::User3, false); } - if(getPlacementListProperty()) { + if (getPlacementListProperty()) { auto placements = getPlacementListValue(); - if(placements.size()setStatus(Property::User3,true); + } + getPlacementListProperty()->setStatus(Property::User3, true); getPlacementListProperty()->setValue(placements); - getPlacementListProperty()->setStatus(Property::User3,false); + getPlacementListProperty()->setStatus(Property::User3, false); } - }else if(getElementListProperty()) { + } + else if (getElementListProperty()) { auto objs = getElementListValue(); - if(elementCount>objs.size()) { + if (elementCount > objs.size()) { std::string name = parent->getNameInDocument(); auto doc = parent->getDocument(); name += "_i"; name = doc->getUniqueObjectName(name.c_str()); - if(name[name.size()-1] != 'i') + if (name[name.size() - 1] != 'i') { name += "_i"; + } auto offset = name.size(); auto placementProp = getPlacementListProperty(); auto scaleProp = getScaleListProperty(); - const auto &vis = getVisibilityListValue(); + const auto& vis = getVisibilityListValue(); auto owner = getContainer(); - long ownerID = owner?owner->getID():0; + long ownerID = owner ? owner->getID() : 0; - for(size_t i=objs.size();i(doc->getObject(name.c_str())); - if(obj && (!obj->_LinkOwner.getValue() || obj->_LinkOwner.getValue()==ownerID)) { + if (obj + && (!obj->_LinkOwner.getValue() || obj->_LinkOwner.getValue() == ownerID)) { obj->Visibility.setValue(false); - } else { + } + else { obj = new LinkElement; - parent->getDocument()->addObject(obj,name.c_str()); + parent->getDocument()->addObject(obj, name.c_str()); } - if(vis.size()>i && !vis[i]) + if (vis.size() > i && !vis[i]) { myHiddenElements.insert(obj); + } - if(placementProp && placementProp->getSize()>(int)i) + if (placementProp && placementProp->getSize() > (int)i) { obj->Placement.setValue(placementProp->getValues()[i]); - else{ - Base::Placement pla(Base::Vector3d(i%10,(i/10)%10,i/100),Base::Rotation()); + } + else { + Base::Placement pla(Base::Vector3d(i % 10, (i / 10) % 10, i / 100), + Base::Rotation()); obj->Placement.setValue(pla); } - if(scaleProp && scaleProp->getSize()>(int)i) + if (scaleProp && scaleProp->getSize() > (int)i) { obj->Scale.setValue(scaleProp->getValues()[i].x); - else + } + else { obj->Scale.setValue(1); + } objs.push_back(obj); } - if(getPlacementListProperty()) + if (getPlacementListProperty()) { getPlacementListProperty()->setSize(0); - if(getScaleListProperty()) + } + if (getScaleListProperty()) { getScaleListProperty()->setSize(0); + } getElementListProperty()->setValue(objs); - - }else if(elementCount tmpObjs; auto owner = getContainer(); - long ownerID = owner?owner->getID():0; - while(objs.size()>elementCount) { + long ownerID = owner ? owner->getID() : 0; + while (objs.size() > elementCount) { auto element = freecad_dynamic_cast(objs.back()); - if(element && element->_LinkOwner.getValue()==ownerID) + if (element && element->_LinkOwner.getValue() == ownerID) { tmpObjs.push_back(objs.back()); + } objs.pop_back(); } getElementListProperty()->setValue(objs); - for(auto obj : tmpObjs) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : tmpObjs) { + if (obj && obj->isAttachedToDocument()) { obj->getDocument()->removeObject(obj->getNameInDocument()); + } } } } - }else if(prop == getVisibilityListProperty()) { - if(_getShowElementValue()) { - const auto &elements = _getElementListValue(); - const auto &vis = getVisibilityListValue(); + } + else if (prop == getVisibilityListProperty()) { + if (_getShowElementValue()) { + const auto& elements = _getElementListValue(); + const auto& vis = getVisibilityListValue(); myHiddenElements.clear(); - for(size_t i=0;i=elements.size()) + for (size_t i = 0; i < vis.size(); ++i) { + if (i >= elements.size()) { break; - if(!vis[i]) + } + if (!vis[i]) { myHiddenElements.insert(elements[i]); + } } } - }else if(prop == getElementListProperty() || prop == &_ChildCache) { + } + else if (prop == getElementListProperty() || prop == &_ChildCache) { - if(prop == getElementListProperty()) { - _ChildCache.setStatus(Property::User3,true); + if (prop == getElementListProperty()) { + _ChildCache.setStatus(Property::User3, true); updateGroup(); - _ChildCache.setStatus(Property::User3,false); + _ChildCache.setStatus(Property::User3, false); } - const auto &elements = _getElementListValue(); + const auto& elements = _getElementListValue(); - if(enableLabelCache) + if (enableLabelCache) { myLabelCache.clear(); + } // Element list changed, we need to sychrnoize VisibilityList. - if(_getShowElementValue() && getVisibilityListProperty()) { - if(parent->getDocument()->isPerformingTransaction()) { - update(parent,getVisibilityListProperty()); - }else{ + if (_getShowElementValue() && getVisibilityListProperty()) { + if (parent->getDocument()->isPerformingTransaction()) { + update(parent, getVisibilityListProperty()); + } + else { boost::dynamic_bitset<> vis; - vis.resize(elements.size(),true); - std::unordered_set hiddenElements; - for(size_t i=0;i hiddenElements; + for (size_t i = 0; i < elements.size(); ++i) { + if (myHiddenElements.find(elements[i]) != myHiddenElements.end()) { hiddenElements.insert(elements[i]); vis[i] = false; } } myHiddenElements.swap(hiddenElements); - if(vis != getVisibilityListValue()) { + if (vis != getVisibilityListValue()) { auto propVis = getVisibilityListProperty(); - propVis->setStatus(Property::User3,true); + propVis->setStatus(Property::User3, true); propVis->setValue(vis); - propVis->setStatus(Property::User3,false); + propVis->setStatus(Property::User3, false); } } } syncElementList(); - if(_getShowElementValue() - && _getElementCountProperty() - && getElementListProperty() - && getElementCountValue()!=getElementListProperty()->getSize()) - { - getElementCountProperty()->setValue( - getElementListProperty()->getSize()); - } - }else if(prop == getLinkedObjectProperty()) { + if (_getShowElementValue() && _getElementCountProperty() && getElementListProperty() + && getElementCountValue() != getElementListProperty()->getSize()) { + getElementCountProperty()->setValue(getElementListProperty()->getSize()); + } + } + else if (prop == getLinkedObjectProperty()) { auto group = linkedPlainGroup(); - if(getShowElementProperty()) + if (getShowElementProperty()) { getShowElementProperty()->setStatus(Property::Hidden, !!group); - if(getElementCountProperty()) + } + if (getElementCountProperty()) { getElementCountProperty()->setStatus(Property::Hidden, !!group); - if(group) + } + if (group) { updateGroup(); - else if(_ChildCache.getSize()) + } + else if (_ChildCache.getSize()) { _ChildCache.setValue(); + } parseSubName(); syncElementList(); - if(getLinkCopyOnChangeValue()==CopyOnChangeOwned - && !pauseCopyOnChange - && !parent->getDocument()->isPerformingTransaction()) + if (getLinkCopyOnChangeValue() == CopyOnChangeOwned && !pauseCopyOnChange + && !parent->getDocument()->isPerformingTransaction()) { getLinkCopyOnChangeProperty()->setValue(CopyOnChangeEnabled); - else + } + else { setupCopyOnChange(parent, true); - - }else if(prop == getLinkCopyOnChangeProperty()) { + } + } + else if (prop == getLinkCopyOnChangeProperty()) { setupCopyOnChange(parent, getLinkCopyOnChangeSourceValue() == nullptr); - } else if (prop == getLinkCopyOnChangeSourceProperty()) { + } + else if (prop == getLinkCopyOnChangeSourceProperty()) { if (auto source = getLinkCopyOnChangeSourceValue()) { this->connCopyOnChangeSource = source->signalChanged.connect( - [this](const DocumentObject & obj, const Property &prop) { + [this](const DocumentObject& obj, const Property& prop) { auto src = getLinkCopyOnChangeSourceValue(); - if (src != &obj || getLinkCopyOnChangeValue()==CopyOnChangeDisabled) + if (src != &obj || getLinkCopyOnChangeValue() == CopyOnChangeDisabled) { return; - if (App::Document::isAnyRestoring() - || obj.testStatus(ObjectStatus::NoTouch) - || (prop.getType() & Prop_Output) - || prop.testStatus(Property::Output)) + } + if (App::Document::isAnyRestoring() || obj.testStatus(ObjectStatus::NoTouch) + || (prop.getType() & Prop_Output) || prop.testStatus(Property::Output)) { return; - if (auto propTouch = getLinkCopyOnChangeTouchedProperty()) + } + if (auto propTouch = getLinkCopyOnChangeTouchedProperty()) { propTouch->setValue(true); + } }); - } else + } + else { this->connCopyOnChangeSource.disconnect(); - - }else if(prop == getLinkTransformProperty()) { + } + } + else if (prop == getLinkTransformProperty()) { auto linkPlacement = getLinkPlacementProperty(); auto placement = getPlacementProperty(); - if(linkPlacement && placement) { + if (linkPlacement && placement) { bool transform = getLinkTransformValue(); - placement->setStatus(Property::Hidden,transform); - linkPlacement->setStatus(Property::Hidden,!transform); + placement->setStatus(Property::Hidden, transform); + linkPlacement->setStatus(Property::Hidden, !transform); } syncElementList(); - - } else { + } + else { checkCopyOnChange(parent, *prop); } } -void LinkBaseExtension::cacheChildLabel(int enable) const { - enableLabelCache = enable?true:false; +void LinkBaseExtension::cacheChildLabel(int enable) const +{ + enableLabelCache = enable ? true : false; myLabelCache.clear(); - if(enable<=0) + if (enable <= 0) { return; + } int idx = 0; - for(auto child : _getElementListValue()) { - if(child && child->isAttachedToDocument()) + for (auto child : _getElementListValue()) { + if (child && child->isAttachedToDocument()) { myLabelCache[child->Label.getStrValue()] = idx; + } ++idx; } } -bool LinkBaseExtension::linkTransform() const { - if(!getLinkTransformProperty() && - !getLinkPlacementProperty() && - !getPlacementProperty()) +bool LinkBaseExtension::linkTransform() const +{ + if (!getLinkTransformProperty() && !getLinkPlacementProperty() && !getPlacementProperty()) { return true; + } return getLinkTransformValue(); } -void LinkBaseExtension::syncElementList() { +void LinkBaseExtension::syncElementList() +{ auto transform = getLinkTransformProperty(); auto link = getLinkedObjectProperty(); auto xlink = freecad_dynamic_cast(link); auto owner = getContainer(); - auto ownerID = owner?owner->getID():0; + auto ownerID = owner ? owner->getID() : 0; auto elements = getElementListValue(); for (auto i : elements) { auto element = freecad_dynamic_cast(i); if (!element - || (element->_LinkOwner.getValue() - && element->_LinkOwner.getValue() != ownerID)) + || (element->_LinkOwner.getValue() && element->_LinkOwner.getValue() != ownerID)) { continue; + } element->_LinkOwner.setValue(ownerID); element->LinkTransform.setStatus(Property::Hidden, transform != nullptr); element->LinkTransform.setStatus(Property::Immutable, transform != nullptr); - if (transform && element->LinkTransform.getValue() != transform->getValue()) + if (transform && element->LinkTransform.getValue() != transform->getValue()) { element->LinkTransform.setValue(transform->getValue()); + } element->LinkedObject.setStatus(Property::Hidden, link != nullptr); element->LinkedObject.setStatus(Property::Immutable, link != nullptr); - if (element->LinkCopyOnChange.getValue() == 2) + if (element->LinkCopyOnChange.getValue() == 2) { continue; + } if (xlink) { if (element->LinkedObject.getValue() != xlink->getValue() || element->LinkedObject.getSubValues() != xlink->getSubValues()) { @@ -1940,87 +2234,100 @@ void LinkBaseExtension::syncElementList() { } } -void LinkBaseExtension::onExtendedDocumentRestored() { +void LinkBaseExtension::onExtendedDocumentRestored() +{ inherited::onExtendedDocumentRestored(); myHiddenElements.clear(); auto parent = getContainer(); - if(!parent) + if (!parent) { return; - if(hasOldSubElement) { + } + if (hasOldSubElement) { hasOldSubElement = false; // SubElements was stored as a PropertyStringList. It is now migrated to be // stored inside PropertyXLink. auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); - if(!xlink) + if (!xlink) { FC_ERR("Failed to restore SubElements for " << parent->getFullName()); - else if(!xlink->getValue()) + } + else if (!xlink->getValue()) { FC_ERR("Discard SubElements of " << parent->getFullName() << " due to null link"); - else if(xlink->getSubValues().size() > 1) + } + else if (xlink->getSubValues().size() > 1) { FC_ERR("Failed to restore SubElements for " << parent->getFullName() - << " due to conflict subnames"); - else if(xlink->getSubValues().empty()) { + << " due to conflict subnames"); + } + else if (xlink->getSubValues().empty()) { auto subs = xlink->getSubValues(); xlink->setSubValues(std::move(subs)); - } else { - std::set subset(mySubElements.begin(),mySubElements.end()); + } + else { + std::set subset(mySubElements.begin(), mySubElements.end()); auto sub = xlink->getSubValues().front(); auto element = Data::findElementName(sub.c_str()); - if(element && element[0]) { + if (element && element[0]) { subset.insert(element); sub.resize(element - sub.c_str()); } std::vector subs; - for(const auto &s : subset) + for (const auto& s : subset) { subs.push_back(sub + s); + } xlink->setSubValues(std::move(subs)); } } - if(getScaleVectorProperty() && getScaleProperty()) { + if (getScaleVectorProperty() && getScaleProperty()) { // Scale vector is added later. The code here is for migration. - const auto &v = getScaleVectorValue(); + const auto& v = getScaleVectorValue(); double s = getScaleValue(); - if(v.x == v.y && v.x == v.z && v.x != s) - getScaleVectorProperty()->setValue(s,s,s); + if (v.x == v.y && v.x == v.z && v.x != s) { + getScaleVectorProperty()->setValue(s, s, s); + } } - update(parent,getVisibilityListProperty()); + update(parent, getVisibilityListProperty()); if (auto prop = getLinkedObjectProperty()) { Base::StateLocker guard(pauseCopyOnChange); - update(parent,prop); + update(parent, prop); } - update(parent,getLinkCopyOnChangeSourceProperty()); - update(parent,getElementListProperty()); - if (getLinkCopyOnChangeValue() != CopyOnChangeDisabled) + update(parent, getLinkCopyOnChangeSourceProperty()); + update(parent, getElementListProperty()); + if (getLinkCopyOnChangeValue() != CopyOnChangeDisabled) { monitorOnChangeCopyObjects(getOnChangeCopyObjects()); + } } -void LinkBaseExtension::_handleChangedPropertyName( - Base::XMLReader &reader, const char * TypeName, const char *PropName) +void LinkBaseExtension::_handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) { - if(strcmp(PropName,"SubElements")==0 - && strcmp(TypeName,PropertyStringList::getClassTypeId().getName())==0) - { + if (strcmp(PropName, "SubElements") == 0 + && strcmp(TypeName, PropertyStringList::getClassTypeId().getName()) == 0) { PropertyStringList prop; prop.setContainer(getContainer()); prop.Restore(reader); - if(prop.getSize()) { + if (prop.getSize()) { mySubElements = prop.getValues(); hasOldSubElement = true; } } } -void LinkBaseExtension::setLink(int index, DocumentObject *obj, - const char *subname, const std::vector &subElements) +void LinkBaseExtension::setLink(int index, + DocumentObject* obj, + const char* subname, + const std::vector& subElements) { auto parent = getContainer(); - if(!parent) - LINK_THROW(Base::RuntimeError,"No parent container"); + if (!parent) { + LINK_THROW(Base::RuntimeError, "No parent container"); + } - if(obj && !App::Document::isAnyRestoring()) { + if (obj && !App::Document::isAnyRestoring()) { auto inSet = parent->getInListEx(true); inSet.insert(parent); - if(inSet.find(obj)!=inSet.end()) - LINK_THROW(Base::RuntimeError,"Cyclic dependency"); + if (inSet.find(obj) != inSet.end()) { + LINK_THROW(Base::RuntimeError, "Cyclic dependency"); + } } auto linkProp = getLinkedObjectProperty(); @@ -2028,73 +2335,84 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj, // If we are a group (i.e. no LinkObject property), and the index is // negative with a non-zero 'obj' assignment, we treat this as group // expansion by changing the index to one pass the existing group size - if(index<0 && obj && !linkProp && getElementListProperty()) + if (index < 0 && obj && !linkProp && getElementListProperty()) { index = getElementListProperty()->getSize(); + } - if(index>=0) { + if (index >= 0) { // LinkGroup assignment - if(linkProp || !getElementListProperty()) - LINK_THROW(Base::RuntimeError,"Cannot set link element"); + if (linkProp || !getElementListProperty()) { + LINK_THROW(Base::RuntimeError, "Cannot set link element"); + } - DocumentObject *old = nullptr; - const auto &elements = getElementListProperty()->getValues(); - if(!obj) { - if(index>=(int)elements.size()) - LINK_THROW(Base::ValueError,"Link element index out of bound"); + DocumentObject* old = nullptr; + const auto& elements = getElementListProperty()->getValues(); + if (!obj) { + if (index >= (int)elements.size()) { + LINK_THROW(Base::ValueError, "Link element index out of bound"); + } std::vector objs; old = elements[index]; - for(int i=0;i<(int)elements.size();++i) { - if(i!=index) + for (int i = 0; i < (int)elements.size(); ++i) { + if (i != index) { objs.push_back(elements[i]); + } } getElementListProperty()->setValue(objs); - }else if(!obj->isAttachedToDocument()) - LINK_THROW(Base::ValueError,"Invalid object"); - else{ - if(index>(int)elements.size()) - LINK_THROW(Base::ValueError,"Link element index out of bound"); + } + else if (!obj->isAttachedToDocument()) { + LINK_THROW(Base::ValueError, "Invalid object"); + } + else { + if (index > (int)elements.size()) { + LINK_THROW(Base::ValueError, "Link element index out of bound"); + } - if(index < (int)elements.size()) + if (index < (int)elements.size()) { old = elements[index]; + } int idx = -1; - if(getLinkModeValue()>=LinkModeAutoLink || - (subname && subname[0]) || - !subElements.empty() || - obj->getDocument()!=parent->getDocument() || - (getElementListProperty()->find(obj->getNameInDocument(),&idx) && idx!=index)) - { + if (getLinkModeValue() >= LinkModeAutoLink || (subname && subname[0]) + || !subElements.empty() || obj->getDocument() != parent->getDocument() + || (getElementListProperty()->find(obj->getNameInDocument(), &idx) + && idx != index)) { std::string name = parent->getDocument()->getUniqueObjectName("Link"); auto link = new Link; link->_LinkOwner.setValue(parent->getID()); - parent->getDocument()->addObject(link,name.c_str()); - link->setLink(-1,obj,subname,subElements); + parent->getDocument()->addObject(link, name.c_str()); + link->setLink(-1, obj, subname, subElements); auto linked = link->getTrueLinkedObject(true); - if(linked) + if (linked) { link->Label.setValue(linked->Label.getValue()); - auto pla = freecad_dynamic_cast(obj->getPropertyByName("Placement")); - if(pla) + } + auto pla = + freecad_dynamic_cast(obj->getPropertyByName("Placement")); + if (pla) { link->Placement.setValue(pla->getValue()); + } link->Visibility.setValue(false); obj = link; } - if(old == obj) + if (old == obj) { return; + } - getElementListProperty()->set1Value(index,obj); + getElementListProperty()->set1Value(index, obj); } detachElement(old); return; } - if(!linkProp) { + if (!linkProp) { // Reaching here means, we are group (i.e. no LinkedObject), and // index<0, and 'obj' is zero. We shall clear the whole group - if(obj || !getElementListProperty()) - LINK_THROW(Base::RuntimeError,"No PropertyLink or PropertyLinkList configured"); + if (obj || !getElementListProperty()) { + LINK_THROW(Base::RuntimeError, "No PropertyLink or PropertyLinkList configured"); + } detachElements(); return; } @@ -2102,127 +2420,157 @@ void LinkBaseExtension::setLink(int index, DocumentObject *obj, // Here means we are assigning a Link auto xlink = freecad_dynamic_cast(linkProp); - if(obj) { - if(!obj->isAttachedToDocument()) - LINK_THROW(Base::ValueError,"Invalid document object"); - if(!xlink) { - if(parent && obj->getDocument()!=parent->getDocument()) - LINK_THROW(Base::ValueError,"Cannot link to external object without PropertyXLink"); + if (obj) { + if (!obj->isAttachedToDocument()) { + LINK_THROW(Base::ValueError, "Invalid document object"); + } + if (!xlink) { + if (parent && obj->getDocument() != parent->getDocument()) { + LINK_THROW(Base::ValueError, + "Cannot link to external object without PropertyXLink"); + } } } - if(!xlink) { - if(!subElements.empty() || (subname && subname[0])) - LINK_THROW(Base::RuntimeError,"SubName/SubElement link requires PropertyXLink"); + if (!xlink) { + if (!subElements.empty() || (subname && subname[0])) { + LINK_THROW(Base::RuntimeError, "SubName/SubElement link requires PropertyXLink"); + } linkProp->setValue(obj); return; } std::vector subs; - if(!subElements.empty()) { + if (!subElements.empty()) { subs.reserve(subElements.size()); - for(const auto &s : subElements) { - subs.emplace_back(subname?subname:""); + for (const auto& s : subElements) { + subs.emplace_back(subname ? subname : ""); subs.back() += s; } - } else if(subname && subname[0]) + } + else if (subname && subname[0]) { subs.emplace_back(subname); - xlink->setValue(obj,std::move(subs)); + } + xlink->setValue(obj, std::move(subs)); } void LinkBaseExtension::detachElements() { std::vector objs; - for (auto obj : getElementListValue()) + for (auto obj : getElementListValue()) { objs.emplace_back(obj); + } getElementListProperty()->setValue(); - for(const auto &objT : objs) + for (const auto& objT : objs) { detachElement(objT.getObject()); + } } -void LinkBaseExtension::detachElement(DocumentObject *obj) { - if(!obj || !obj->isAttachedToDocument() || obj->isRemoving()) +void LinkBaseExtension::detachElement(DocumentObject* obj) +{ + if (!obj || !obj->isAttachedToDocument() || obj->isRemoving()) { return; + } auto ext = obj->getExtensionByType(true); auto owner = getContainer(); - long ownerID = owner?owner->getID():0; - if(getLinkModeValue()==LinkModeAutoUnlink) { - if(!ext || ext->_LinkOwner.getValue()!=ownerID) + long ownerID = owner ? owner->getID() : 0; + if (getLinkModeValue() == LinkModeAutoUnlink) { + if (!ext || ext->_LinkOwner.getValue() != ownerID) { return; - }else if(getLinkModeValue()!=LinkModeAutoDelete) { - if(ext && ext->_LinkOwner.getValue()==ownerID) + } + } + else if (getLinkModeValue() != LinkModeAutoDelete) { + if (ext && ext->_LinkOwner.getValue() == ownerID) { ext->_LinkOwner.setValue(0); + } return; } obj->getDocument()->removeObject(obj->getNameInDocument()); } -std::vector LinkBaseExtension::getLinkedChildren(bool filter) const{ - if(!filter) +std::vector LinkBaseExtension::getLinkedChildren(bool filter) const +{ + if (!filter) { return _getElementListValue(); + } std::vector ret; - for(auto o : _getElementListValue()) { - if(!o->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) + for (auto o : _getElementListValue()) { + if (!o->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { ret.push_back(o); + } } return ret; } -const char *LinkBaseExtension::flattenSubname(const char *subname) const { - if(subname && _ChildCache.getSize()) { - const char *sub = subname; +const char* LinkBaseExtension::flattenSubname(const char* subname) const +{ + if (subname && _ChildCache.getSize()) { + const char* sub = subname; std::string s; - for(const char* dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { - DocumentObject *obj = nullptr; + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { + DocumentObject* obj = nullptr; s.clear(); - s.append(sub,dot+1); - extensionGetSubObject(obj,s.c_str()); - if(!obj) + s.append(sub, dot + 1); + extensionGetSubObject(obj, s.c_str()); + if (!obj) { break; - if(!obj->hasExtension(GroupExtension::getExtensionClassTypeId(),false)) + } + if (!obj->hasExtension(GroupExtension::getExtensionClassTypeId(), false)) { return sub; + } } } return subname; } -void LinkBaseExtension::expandSubname(std::string &subname) const { - if(!_ChildCache.getSize()) +void LinkBaseExtension::expandSubname(std::string& subname) const +{ + if (!_ChildCache.getSize()) { return; + } - const char *pos = nullptr; - int index = getElementIndex(subname.c_str(),&pos); - if(index<0) + const char* pos = nullptr; + int index = getElementIndex(subname.c_str(), &pos); + if (index < 0) { return; + } std::ostringstream ss; - elementNameFromIndex(index,ss); + elementNameFromIndex(index, ss); ss << pos; subname = ss.str(); } -static bool isExcludedProperties(const char *name) { -#define CHECK_EXCLUDE_PROP(_name) if(strcmp(name,#_name)==0) return true; +static bool isExcludedProperties(const char* name) +{ +#define CHECK_EXCLUDE_PROP(_name) \ + if (strcmp(name, #_name) == 0) \ + return true; CHECK_EXCLUDE_PROP(Shape); CHECK_EXCLUDE_PROP(Proxy); CHECK_EXCLUDE_PROP(Placement); return false; } -Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const { - if (checkingProperty) +Property* LinkBaseExtension::extensionGetPropertyByName(const char* name) const +{ + if (checkingProperty) { return inherited::extensionGetPropertyByName(name); + } Base::StateLocker guard(checkingProperty); - if(isExcludedProperties(name)) + if (isExcludedProperties(name)) { return nullptr; + } auto owner = getContainer(); if (owner) { - App::Property *prop = owner->getPropertyByName(name); - if(prop) + App::Property* prop = owner->getPropertyByName(name); + if (prop) { return prop; - if(owner->canLinkProperties()) { + } + if (owner->canLinkProperties()) { auto linked = getTrueLinkedObject(true); - if(linked) + if (linked) { return linked->getPropertyByName(name); + } } } return nullptr; @@ -2230,21 +2578,21 @@ Property *LinkBaseExtension::extensionGetPropertyByName(const char* name) const bool LinkBaseExtension::isLinkMutated() const { - return getLinkCopyOnChangeValue() != CopyOnChangeDisabled - && getLinkedObjectValue() + return getLinkCopyOnChangeValue() != CopyOnChangeDisabled && getLinkedObjectValue() && (!getLinkCopyOnChangeSourceValue() || (getLinkedObjectValue() != getLinkCopyOnChangeSourceValue())); } /////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::LinkBaseExtensionPython, App::LinkBaseExtension) // explicit template instantiation template class AppExport ExtensionPythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////// @@ -2259,26 +2607,29 @@ LinkExtension::LinkExtension() /////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::LinkExtensionPython, App::LinkExtension) // explicit template instantiation template class AppExport ExtensionPythonT; -} +} // namespace App /////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::Link, App::DocumentObject) -Link::Link() { +Link::Link() +{ LINK_PROPS_ADD(LINK_PARAMS_LINK); LinkExtension::initExtension(this); - static const PropertyIntegerConstraint::Constraints s_constraints = {0,INT_MAX,1}; + static const PropertyIntegerConstraint::Constraints s_constraints = {0, INT_MAX, 1}; ElementCount.setConstraints(&s_constraints); } -bool Link::canLinkProperties() const { +bool Link::canLinkProperties() const +{ return true; } @@ -2294,26 +2645,32 @@ bool Link::isLinkGroup() const ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkPython, App::Link) -template<> const char* App::LinkPython::getViewProviderName() const { +template<> +const char* App::LinkPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::LinkElement, App::DocumentObject) -LinkElement::LinkElement() { +LinkElement::LinkElement() +{ LINK_PROPS_ADD(LINK_PARAMS_ELEMENT); LinkBaseExtension::initExtension(this); } -bool LinkElement::canDelete() const { - if(!_LinkOwner.getValue()) +bool LinkElement::canDelete() const +{ + if (!_LinkOwner.getValue()) { return true; + } auto owner = getContainer(); return !owner || !owner->getDocument()->getObjectByID(_LinkOwner.getValue()); @@ -2344,34 +2701,40 @@ App::Link* LinkElement::getLinkGroup() const ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkElementPython, App::LinkElement) -template<> const char* App::LinkElementPython::getViewProviderName() const { +template<> +const char* App::LinkElementPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App ////////////////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE_WITH_EXTENSIONS(App::LinkGroup, App::DocumentObject) -LinkGroup::LinkGroup() { +LinkGroup::LinkGroup() +{ LINK_PROPS_ADD(LINK_PARAMS_GROUP); LinkBaseExtension::initExtension(this); } ////////////////////////////////////////////////////////////////////////////////////////// -namespace App { +namespace App +{ PROPERTY_SOURCE_TEMPLATE(App::LinkGroupPython, App::LinkGroup) -template<> const char* App::LinkGroupPython::getViewProviderName() const { +template<> +const char* App::LinkGroupPython::getViewProviderName() const +{ return "Gui::ViewProviderLinkPython"; } template class AppExport FeaturePythonT; -} +} // namespace App #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif - diff --git a/src/App/Link.h b/src/App/Link.h index 7cb879f75a31..2fbfeea8a0a3 100644 --- a/src/App/Link.h +++ b/src/App/Link.h @@ -33,22 +33,23 @@ #include "PropertyLinks.h" -//FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro +// FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #endif -#define LINK_THROW(_type,_msg) do{\ - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))\ - FC_ERR(_msg);\ - throw _type(_msg);\ -}while(0) +#define LINK_THROW(_type, _msg) \ + do { \ + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) \ + FC_ERR(_msg); \ + throw _type(_msg); \ + } while (0) namespace App { -class AppExport LinkBaseExtension : public App::DocumentObjectExtension +class AppExport LinkBaseExtension: public App::DocumentObjectExtension { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension); using inherited = App::DocumentObjectExtension; @@ -59,9 +60,10 @@ class AppExport LinkBaseExtension : public App::DocumentObjectExtension PropertyBool _LinkTouched; PropertyInteger _LinkOwner; - PropertyLinkList _ChildCache; // cache for plain group expansion + PropertyLinkList _ChildCache; // cache for plain group expansion - enum { + enum + { LinkModeNone, LinkModeAutoDelete, LinkModeAutoLink, @@ -76,267 +78,365 @@ class AppExport LinkBaseExtension : public App::DocumentObjectExtension */ //@{ -#define LINK_PARAM_LINK_PLACEMENT(...) \ - (LinkPlacement, Base::Placement, App::PropertyPlacement, Base::Placement(), "Link placement", ##__VA_ARGS__) - -#define LINK_PARAM_PLACEMENT(...) \ - (Placement, Base::Placement, App::PropertyPlacement, Base::Placement(), \ - "Alias to LinkPlacement to make the link object compatibale with other objects", ##__VA_ARGS__) - -#define LINK_PARAM_OBJECT(...) \ +#define LINK_PARAM_LINK_PLACEMENT(...) \ + (LinkPlacement, \ + Base::Placement, \ + App::PropertyPlacement, \ + Base::Placement(), \ + "Link placement", \ + ##__VA_ARGS__) + +#define LINK_PARAM_PLACEMENT(...) \ + (Placement, \ + Base::Placement, \ + App::PropertyPlacement, \ + Base::Placement(), \ + "Alias to LinkPlacement to make the link object compatibale with other objects", \ + ##__VA_ARGS__) + +#define LINK_PARAM_OBJECT(...) \ (LinkedObject, App::DocumentObject*, App::PropertyLink, 0, "Linked object", ##__VA_ARGS__) -#define LINK_PARAM_TRANSFORM(...) \ - (LinkTransform, bool, App::PropertyBool, false, \ - "Set to false to override linked object's placement", ##__VA_ARGS__) - -#define LINK_PARAM_CLAIM_CHILD(...) \ - (LinkClaimChild, bool, App::PropertyBool, false, \ - "Claim the linked object as a child", ##__VA_ARGS__) - -#define LINK_PARAM_COPY_ON_CHANGE(...) \ - (LinkCopyOnChange, long, App::PropertyEnumeration, ((long)0), \ - "Disabled: disable copy on change\n"\ - "Enabled: enable copy linked object on change of any of its properties marked as CopyOnChange\n"\ - "Owned: indicate the linked object has been copied and is own owned by the link. And the\n"\ - " the link will try to sync any change of the original linked object back to the copy.",\ - ##__VA_ARGS__) - -#define LINK_PARAM_COPY_ON_CHANGE_SOURCE(...) \ - (LinkCopyOnChangeSource, App::DocumentObject*, App::PropertyLink, 0, "The copy on change source object", ##__VA_ARGS__) - -#define LINK_PARAM_COPY_ON_CHANGE_GROUP(...) \ - (LinkCopyOnChangeGroup, App::DocumentObject*, App::PropertyLink, 0, \ - "Linked to a internal group object for holding on change copies", ##__VA_ARGS__) - -#define LINK_PARAM_COPY_ON_CHANGE_TOUCHED(...) \ - (LinkCopyOnChangeTouched, bool, App::PropertyBool, 0, "Indicating the copy on change source object has been changed", ##__VA_ARGS__) - -#define LINK_PARAM_SCALE(...) \ +#define LINK_PARAM_TRANSFORM(...) \ + (LinkTransform, \ + bool, \ + App::PropertyBool, \ + false, \ + "Set to false to override linked object's placement", \ + ##__VA_ARGS__) + +#define LINK_PARAM_CLAIM_CHILD(...) \ + (LinkClaimChild, \ + bool, \ + App::PropertyBool, \ + false, \ + "Claim the linked object as a child", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COPY_ON_CHANGE(...) \ + (LinkCopyOnChange, \ + long, \ + App::PropertyEnumeration, \ + ((long)0), \ + "Disabled: disable copy on change\n" \ + "Enabled: enable copy linked object on change of any of its properties marked as " \ + "CopyOnChange\n" \ + "Owned: indicate the linked object has been copied and is own owned by the link. And the\n" \ + " the link will try to sync any change of the original linked object back to the " \ + "copy.", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COPY_ON_CHANGE_SOURCE(...) \ + (LinkCopyOnChangeSource, \ + App::DocumentObject*, \ + App::PropertyLink, \ + 0, \ + "The copy on change source object", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COPY_ON_CHANGE_GROUP(...) \ + (LinkCopyOnChangeGroup, \ + App::DocumentObject*, \ + App::PropertyLink, \ + 0, \ + "Linked to a internal group object for holding on change copies", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COPY_ON_CHANGE_TOUCHED(...) \ + (LinkCopyOnChangeTouched, \ + bool, \ + App::PropertyBool, \ + 0, \ + "Indicating the copy on change source object has been changed", \ + ##__VA_ARGS__) + +#define LINK_PARAM_SCALE(...) \ (Scale, double, App::PropertyFloat, 1.0, "Scale factor", ##__VA_ARGS__) -#define LINK_PARAM_SCALE_VECTOR(...) \ - (ScaleVector, Base::Vector3d, App::PropertyVector, Base::Vector3d(1,1,1), "Scale factors", ##__VA_ARGS__) - -#define LINK_PARAM_PLACEMENTS(...) \ - (PlacementList, std::vector, App::PropertyPlacementList, std::vector(),\ - "The placement for each link element", ##__VA_ARGS__) - -#define LINK_PARAM_SCALES(...) \ - (ScaleList, std::vector, App::PropertyVectorList, std::vector(),\ - "The scale factors for each link element", ##__VA_ARGS__) - -#define LINK_PARAM_VISIBILITIES(...) \ - (VisibilityList, boost::dynamic_bitset<>, App::PropertyBoolList, boost::dynamic_bitset<>(),\ - "The visibility state of each link element", ##__VA_ARGS__) - -#define LINK_PARAM_COUNT(...) \ +#define LINK_PARAM_SCALE_VECTOR(...) \ + (ScaleVector, \ + Base::Vector3d, \ + App::PropertyVector, \ + Base::Vector3d(1, 1, 1), \ + "Scale factors", \ + ##__VA_ARGS__) + +#define LINK_PARAM_PLACEMENTS(...) \ + (PlacementList, \ + std::vector, \ + App::PropertyPlacementList, \ + std::vector(), \ + "The placement for each link element", \ + ##__VA_ARGS__) + +#define LINK_PARAM_SCALES(...) \ + (ScaleList, \ + std::vector, \ + App::PropertyVectorList, \ + std::vector(), \ + "The scale factors for each link element", \ + ##__VA_ARGS__) + +#define LINK_PARAM_VISIBILITIES(...) \ + (VisibilityList, \ + boost::dynamic_bitset<>, \ + App::PropertyBoolList, \ + boost::dynamic_bitset<>(), \ + "The visibility state of each link element", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COUNT(...) \ (ElementCount, int, App::PropertyInteger, 0, "Link element count", ##__VA_ARGS__) -#define LINK_PARAM_ELEMENTS(...) \ - (ElementList, std::vector, App::PropertyLinkList, std::vector(),\ - "The link element object list", ##__VA_ARGS__) +#define LINK_PARAM_ELEMENTS(...) \ + (ElementList, \ + std::vector, \ + App::PropertyLinkList, \ + std::vector(), \ + "The link element object list", \ + ##__VA_ARGS__) -#define LINK_PARAM_SHOW_ELEMENT(...) \ +#define LINK_PARAM_SHOW_ELEMENT(...) \ (ShowElement, bool, App::PropertyBool, true, "Enable link element list", ##__VA_ARGS__) -#define LINK_PARAM_MODE(...) \ +#define LINK_PARAM_MODE(...) \ (LinkMode, long, App::PropertyEnumeration, ((long)0), "Link group mode", ##__VA_ARGS__) -#define LINK_PARAM_LINK_EXECUTE(...) \ - (LinkExecute, const char*, App::PropertyString, (""),\ - "Link execute function. Default to 'appLinkExecute'. 'None' to disable.", ##__VA_ARGS__) - -#define LINK_PARAM_COLORED_ELEMENTS(...) \ - (ColoredElements, App::DocumentObject*, App::PropertyLinkSubHidden, \ - 0, "Link colored elements", ##__VA_ARGS__) +#define LINK_PARAM_LINK_EXECUTE(...) \ + (LinkExecute, \ + const char*, \ + App::PropertyString, \ + (""), \ + "Link execute function. Default to 'appLinkExecute'. 'None' to disable.", \ + ##__VA_ARGS__) + +#define LINK_PARAM_COLORED_ELEMENTS(...) \ + (ColoredElements, \ + App::DocumentObject*, \ + App::PropertyLinkSubHidden, \ + 0, \ + "Link colored elements", \ + ##__VA_ARGS__) #define LINK_PARAM(_param) (LINK_PARAM_##_param()) -#define LINK_PNAME(_param) BOOST_PP_TUPLE_ELEM(0,_param) -#define LINK_PTYPE(_param) BOOST_PP_TUPLE_ELEM(1,_param) -#define LINK_PPTYPE(_param) BOOST_PP_TUPLE_ELEM(2,_param) -#define LINK_PDEF(_param) BOOST_PP_TUPLE_ELEM(3,_param) -#define LINK_PDOC(_param) BOOST_PP_TUPLE_ELEM(4,_param) +#define LINK_PNAME(_param) BOOST_PP_TUPLE_ELEM(0, _param) +#define LINK_PTYPE(_param) BOOST_PP_TUPLE_ELEM(1, _param) +#define LINK_PPTYPE(_param) BOOST_PP_TUPLE_ELEM(2, _param) +#define LINK_PDEF(_param) BOOST_PP_TUPLE_ELEM(3, _param) +#define LINK_PDOC(_param) BOOST_PP_TUPLE_ELEM(4, _param) -#define LINK_PINDEX(_param) BOOST_PP_CAT(Prop,LINK_PNAME(_param)) +#define LINK_PINDEX(_param) BOOST_PP_CAT(Prop, LINK_PNAME(_param)) //@} -#define LINK_PARAMS \ - LINK_PARAM(PLACEMENT)\ - LINK_PARAM(LINK_PLACEMENT)\ - LINK_PARAM(OBJECT)\ - LINK_PARAM(CLAIM_CHILD)\ - LINK_PARAM(TRANSFORM)\ - LINK_PARAM(SCALE)\ - LINK_PARAM(SCALE_VECTOR)\ - LINK_PARAM(PLACEMENTS)\ - LINK_PARAM(SCALES)\ - LINK_PARAM(VISIBILITIES)\ - LINK_PARAM(COUNT)\ - LINK_PARAM(ELEMENTS)\ - LINK_PARAM(SHOW_ELEMENT)\ - LINK_PARAM(MODE)\ - LINK_PARAM(LINK_EXECUTE)\ - LINK_PARAM(COLORED_ELEMENTS)\ - LINK_PARAM(COPY_ON_CHANGE)\ - LINK_PARAM(COPY_ON_CHANGE_SOURCE)\ - LINK_PARAM(COPY_ON_CHANGE_GROUP)\ - LINK_PARAM(COPY_ON_CHANGE_TOUCHED)\ - - enum PropIndex { -#define LINK_PINDEX_DEFINE(_1,_2,_param) LINK_PINDEX(_param), +#define LINK_PARAMS \ + LINK_PARAM(PLACEMENT) \ + LINK_PARAM(LINK_PLACEMENT) \ + LINK_PARAM(OBJECT) \ + LINK_PARAM(CLAIM_CHILD) \ + LINK_PARAM(TRANSFORM) \ + LINK_PARAM(SCALE) \ + LINK_PARAM(SCALE_VECTOR) \ + LINK_PARAM(PLACEMENTS) \ + LINK_PARAM(SCALES) \ + LINK_PARAM(VISIBILITIES) \ + LINK_PARAM(COUNT) \ + LINK_PARAM(ELEMENTS) \ + LINK_PARAM(SHOW_ELEMENT) \ + LINK_PARAM(MODE) \ + LINK_PARAM(LINK_EXECUTE) \ + LINK_PARAM(COLORED_ELEMENTS) \ + LINK_PARAM(COPY_ON_CHANGE) \ + LINK_PARAM(COPY_ON_CHANGE_SOURCE) \ + LINK_PARAM(COPY_ON_CHANGE_GROUP) \ + LINK_PARAM(COPY_ON_CHANGE_TOUCHED) + + enum PropIndex + { +#define LINK_PINDEX_DEFINE(_1, _2, _param) LINK_PINDEX(_param), // defines Prop##Name enumeration value - BOOST_PP_SEQ_FOR_EACH(LINK_PINDEX_DEFINE,_,LINK_PARAMS) - PropMax + BOOST_PP_SEQ_FOR_EACH(LINK_PINDEX_DEFINE, _, LINK_PARAMS) PropMax }; - virtual void setProperty(int idx, Property *prop); - Property *getProperty(int idx); - Property *getProperty(const char *); + virtual void setProperty(int idx, Property* prop); + Property* getProperty(int idx); + Property* getProperty(const char*); - struct PropInfo { + struct PropInfo + { int index; - const char *name; + const char* name; Base::Type type; - const char *doc; + const char* doc; - PropInfo(int index, const char *name,Base::Type type,const char *doc) - : index(index), name(name), type(type), doc(doc) + PropInfo(int index, const char* name, Base::Type type, const char* doc) + : index(index) + , name(name) + , type(type) + , doc(doc) {} - PropInfo() : index(0), name(nullptr), doc(nullptr) {} + PropInfo() + : index(0) + , name(nullptr) + , doc(nullptr) + {} }; -#define LINK_PROP_INFO(_1,_var,_param) \ - _var.push_back(PropInfo(BOOST_PP_CAT(Prop,LINK_PNAME(_param)),\ - BOOST_PP_STRINGIZE(LINK_PNAME(_param)),\ - LINK_PPTYPE(_param)::getClassTypeId(), \ - LINK_PDOC(_param))); +#define LINK_PROP_INFO(_1, _var, _param) \ + _var.push_back(PropInfo(BOOST_PP_CAT(Prop, LINK_PNAME(_param)), \ + BOOST_PP_STRINGIZE(LINK_PNAME(_param)), \ + LINK_PPTYPE(_param)::getClassTypeId(), \ + LINK_PDOC(_param))); - virtual const std::vector &getPropertyInfo() const; + virtual const std::vector& getPropertyInfo() const; using PropInfoMap = std::map; - virtual const PropInfoMap &getPropertyInfoMap() const; + virtual const PropInfoMap& getPropertyInfoMap() const; - enum LinkCopyOnChangeType { + enum LinkCopyOnChangeType + { CopyOnChangeDisabled = 0, CopyOnChangeEnabled = 1, CopyOnChangeOwned = 2, CopyOnChangeTracking = 3 }; -#define LINK_PROP_GET(_1,_2,_param) \ - LINK_PTYPE(_param) BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Value)) () const {\ - auto prop = props[LINK_PINDEX(_param)];\ - if(!prop) return LINK_PDEF(_param);\ - return static_cast(prop)->getValue();\ - }\ - const LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () const {\ - auto prop = props[LINK_PINDEX(_param)];\ - return static_cast(prop);\ - }\ - LINK_PPTYPE(_param) *BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property)) () {\ - auto prop = props[LINK_PINDEX(_param)];\ - return static_cast(prop);\ - }\ +#define LINK_PROP_GET(_1, _2, _param) \ + LINK_PTYPE(_param) BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Value))() const \ + { \ + auto prop = props[LINK_PINDEX(_param)]; \ + if (!prop) \ + return LINK_PDEF(_param); \ + return static_cast(prop)->getValue(); \ + } \ + const LINK_PPTYPE(_param) * BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property))() const \ + { \ + auto prop = props[LINK_PINDEX(_param)]; \ + return static_cast(prop); \ + } \ + LINK_PPTYPE(_param) * BOOST_PP_SEQ_CAT((get)(LINK_PNAME(_param))(Property))() \ + { \ + auto prop = props[LINK_PINDEX(_param)]; \ + return static_cast(prop); \ + } // defines get##Name##Property() and get##Name##Value() accessor - BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET,_,LINK_PARAMS) + BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET, _, LINK_PARAMS) - PropertyLinkList *_getElementListProperty() const; - const std::vector &_getElementListValue() const; + PropertyLinkList* _getElementListProperty() const; + const std::vector& _getElementListValue() const; - PropertyBool *_getShowElementProperty() const; + PropertyBool* _getShowElementProperty() const; bool _getShowElementValue() const; - PropertyInteger *_getElementCountProperty() const; + PropertyInteger* _getElementCountProperty() const; int _getElementCountValue() const; - std::vector getLinkedChildren(bool filter=true) const; + std::vector getLinkedChildren(bool filter = true) const; - const char *flattenSubname(const char *subname) const; - void expandSubname(std::string &subname) const; + const char* flattenSubname(const char* subname) const; + void expandSubname(std::string& subname) const; - DocumentObject *getLink(int depth=0) const; + DocumentObject* getLink(int depth = 0) const; Base::Matrix4D getTransform(bool transform) const; Base::Vector3d getScaleVector() const; - App::GroupExtension *linkedPlainGroup() const; + App::GroupExtension* linkedPlainGroup() const; bool linkTransform() const; - const char *getSubName() const { + const char* getSubName() const + { parseSubName(); - return !mySubName.empty()?mySubName.c_str():nullptr; + return !mySubName.empty() ? mySubName.c_str() : nullptr; } - const std::vector &getSubElements() const { + const std::vector& getSubElements() const + { parseSubName(); return mySubElements; } - bool extensionGetSubObject(DocumentObject *&ret, const char *subname, - PyObject **pyObj=nullptr, Base::Matrix4D *mat=nullptr, bool transform=false, int depth=0) const override; + bool extensionGetSubObject(DocumentObject*& ret, + const char* subname, + PyObject** pyObj = nullptr, + Base::Matrix4D* mat = nullptr, + bool transform = false, + int depth = 0) const override; - bool extensionGetSubObjects(std::vector&ret, int reason) const override; + bool extensionGetSubObjects(std::vector& ret, int reason) const override; - bool extensionGetLinkedObject(DocumentObject *&ret, - bool recurse, Base::Matrix4D *mat, bool transform, int depth) const override; + bool extensionGetLinkedObject(DocumentObject*& ret, + bool recurse, + Base::Matrix4D* mat, + bool transform, + int depth) const override; - App::DocumentObjectExecReturn *extensionExecute() override; + App::DocumentObjectExecReturn* extensionExecute() override; short extensionMustExecute() override; void extensionOnChanged(const Property* p) override; - void onExtendedUnsetupObject () override; + void onExtendedUnsetupObject() override; void onExtendedDocumentRestored() override; - int extensionSetElementVisible(const char *, bool) override; - int extensionIsElementVisible(const char *) override; + int extensionSetElementVisible(const char*, bool) override; + int extensionIsElementVisible(const char*) override; bool extensionHasChildElement() const override; PyObject* getExtensionPyObject() override; - Property *extensionGetPropertyByName(const char* name) const override; + Property* extensionGetPropertyByName(const char* name) const override; - static int getArrayIndex(const char *subname, const char **psubname=nullptr); - int getElementIndex(const char *subname, const char **psubname=nullptr) const; - void elementNameFromIndex(int idx, std::ostream &ss) const; + static int getArrayIndex(const char* subname, const char** psubname = nullptr); + int getElementIndex(const char* subname, const char** psubname = nullptr) const; + void elementNameFromIndex(int idx, std::ostream& ss) const; - DocumentObject *getContainer(); - const DocumentObject *getContainer() const; + DocumentObject* getContainer(); + const DocumentObject* getContainer() const; - void setLink(int index, DocumentObject *obj, const char *subname=nullptr, - const std::vector &subs = std::vector()); + void setLink(int index, + DocumentObject* obj, + const char* subname = nullptr, + const std::vector& subs = std::vector()); - DocumentObject *getTrueLinkedObject(bool recurse, - Base::Matrix4D *mat=nullptr,int depth=0, bool noElement=false) const; + DocumentObject* getTrueLinkedObject(bool recurse, + Base::Matrix4D* mat = nullptr, + int depth = 0, + bool noElement = false) const; - using LinkPropMap = std::map >; + using LinkPropMap = std::map>; - bool hasPlacement() const { + bool hasPlacement() const + { return getLinkPlacementProperty() || getPlacementProperty(); } - void cacheChildLabel(int enable=-1) const; + void cacheChildLabel(int enable = -1) const; - static bool setupCopyOnChange(App::DocumentObject *obj, App::DocumentObject *linked, - std::vector *copyOnChangeConns, bool checkExisting); + static bool + setupCopyOnChange(App::DocumentObject* obj, + App::DocumentObject* linked, + std::vector* copyOnChangeConns, + bool checkExisting); - static bool isCopyOnChangeProperty(App::DocumentObject *obj, const Property &prop); + static bool isCopyOnChangeProperty(App::DocumentObject* obj, const Property& prop); void syncCopyOnChange(); /** Options used in setOnChangeCopyObject() * Multiple options can be combined by bitwise or operator */ - enum class OnChangeCopyOptions { + enum class OnChangeCopyOptions + { /// No options set None = 0, - /// If set, then exclude the input from object list to copy on change, or else, include the input object. + /// If set, then exclude the input from object list to copy on change, or else, include the + /// input object. Exclude = 1, - /// If set , then apply the setting to all links to the input object, or else, apply only to this link. + /// If set , then apply the setting to all links to the input object, or else, apply only to + /// this link. ApplyAll = 2, }; @@ -344,53 +444,55 @@ class AppExport LinkBaseExtension : public App::DocumentObjectExtension * @param obj: input object * @param options: control options. @sa OnChangeCopyOptions. */ - void setOnChangeCopyObject(App::DocumentObject *obj, OnChangeCopyOptions options); + void setOnChangeCopyObject(App::DocumentObject* obj, OnChangeCopyOptions options); - std::vector getOnChangeCopyObjects( - std::vector *excludes = nullptr, - App::DocumentObject *src = nullptr); + std::vector + getOnChangeCopyObjects(std::vector* excludes = nullptr, + App::DocumentObject* src = nullptr); bool isLinkedToConfigurableObject() const; - void monitorOnChangeCopyObjects(const std::vector &objs); + void monitorOnChangeCopyObjects(const std::vector& objs); /// Check if the linked object is a copy on change bool isLinkMutated() const; protected: - void _handleChangedPropertyName(Base::XMLReader &reader, - const char * TypeName, const char *PropName); + void + _handleChangedPropertyName(Base::XMLReader& reader, const char* TypeName, const char* PropName); void parseSubName() const; - void update(App::DocumentObject *parent, const Property *prop); - void checkCopyOnChange(App::DocumentObject *parent, const App::Property &prop); - void setupCopyOnChange(App::DocumentObject *parent, bool checkSource = false); - App::DocumentObject *makeCopyOnChange(); + void update(App::DocumentObject* parent, const Property* prop); + void checkCopyOnChange(App::DocumentObject* parent, const App::Property& prop); + void setupCopyOnChange(App::DocumentObject* parent, bool checkSource = false); + App::DocumentObject* makeCopyOnChange(); void syncElementList(); - void detachElement(App::DocumentObject *obj); + void detachElement(App::DocumentObject* obj); void detachElements(); - void checkGeoElementMap(const App::DocumentObject *obj, - const App::DocumentObject *linked, PyObject **pyObj, const char *postfix) const; + void checkGeoElementMap(const App::DocumentObject* obj, + const App::DocumentObject* linked, + PyObject** pyObj, + const char* postfix) const; void updateGroup(); - void slotChangedPlainGroup(const App::DocumentObject &, const App::Property &); + void slotChangedPlainGroup(const App::DocumentObject&, const App::Property&); protected: - std::vector props; + std::vector props; std::unordered_set myHiddenElements; mutable std::vector mySubElements; mutable std::string mySubName; - std::unordered_map plainGroupConns; + std::unordered_map + plainGroupConns; long prevLinkedObjectID = 0; - mutable std::unordered_map myLabelCache; // for label based subname lookup - mutable bool enableLabelCache{false}; - bool hasOldSubElement{false}; + mutable std::unordered_map myLabelCache; // for label based subname lookup + mutable bool enableLabelCache {false}; + bool hasOldSubElement {false}; std::vector copyOnChangeConns; std::vector copyOnChangeSrcConns; - bool hasCopyOnChange{true}; + bool hasCopyOnChange {true}; mutable bool checkingProperty = false; bool pauseCopyOnChange = false; @@ -404,7 +506,7 @@ using LinkBaseExtensionPython = ExtensionPythonT; /////////////////////////////////////////////////////////////////////////// -class AppExport LinkExtension : public LinkBaseExtension +class AppExport LinkExtension: public LinkBaseExtension { EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(App::LinkExtension); using inherited = LinkBaseExtension; @@ -428,36 +530,36 @@ class AppExport LinkExtension : public LinkBaseExtension */ //@{ -#define LINK_ENAME(_param) BOOST_PP_TUPLE_ELEM(5,_param) -#define LINK_ETYPE(_param) BOOST_PP_TUPLE_ELEM(6,_param) -#define LINK_EPTYPE(_param) BOOST_PP_TUPLE_ELEM(7,_param) -#define LINK_EGROUP(_param) BOOST_PP_TUPLE_ELEM(8,_param) +#define LINK_ENAME(_param) BOOST_PP_TUPLE_ELEM(5, _param) +#define LINK_ETYPE(_param) BOOST_PP_TUPLE_ELEM(6, _param) +#define LINK_EPTYPE(_param) BOOST_PP_TUPLE_ELEM(7, _param) +#define LINK_EGROUP(_param) BOOST_PP_TUPLE_ELEM(8, _param) -#define _LINK_PROP_ADD(_add_property, _param) \ - _add_property(BOOST_PP_STRINGIZE(LINK_ENAME(_param)),LINK_ENAME(_param),\ - (LINK_PDEF(_param)),LINK_EGROUP(_param),LINK_EPTYPE(_param),LINK_PDOC(_param));\ - setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param)); +#define _LINK_PROP_ADD(_add_property, _param) \ + _add_property(BOOST_PP_STRINGIZE(LINK_ENAME(_param)), \ + LINK_ENAME(_param), \ + (LINK_PDEF(_param)), \ + LINK_EGROUP(_param), \ + LINK_EPTYPE(_param), \ + LINK_PDOC(_param)); \ + setProperty(LINK_PINDEX(_param), &LINK_ENAME(_param)); -#define LINK_PROP_ADD(_1,_2,_param) \ - _LINK_PROP_ADD(_ADD_PROPERTY_TYPE,_param); +#define LINK_PROP_ADD(_1, _2, _param) _LINK_PROP_ADD(_ADD_PROPERTY_TYPE, _param); -#define LINK_PROP_ADD_EXTENSION(_1,_2,_param) \ - _LINK_PROP_ADD(_EXTENSION_ADD_PROPERTY_TYPE,_param); +#define LINK_PROP_ADD_EXTENSION(_1, _2, _param) \ + _LINK_PROP_ADD(_EXTENSION_ADD_PROPERTY_TYPE, _param); -#define LINK_PROPS_ADD(_seq) \ - BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD,_,_seq) +#define LINK_PROPS_ADD(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD, _, _seq) -#define LINK_PROPS_ADD_EXTENSION(_seq) \ - BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD_EXTENSION,_,_seq) +#define LINK_PROPS_ADD_EXTENSION(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_ADD_EXTENSION, _, _seq) -#define _LINK_PROP_SET(_1,_2,_param) \ - setProperty(LINK_PINDEX(_param),&LINK_ENAME(_param)); +#define _LINK_PROP_SET(_1, _2, _param) setProperty(LINK_PINDEX(_param), &LINK_ENAME(_param)); -#define LINK_PROPS_SET(_seq) BOOST_PP_SEQ_FOR_EACH(_LINK_PROP_SET,_,_seq) +#define LINK_PROPS_SET(_seq) BOOST_PP_SEQ_FOR_EACH(_LINK_PROP_SET, _, _seq) /// Helper for defining default extended parameter -#define _LINK_PARAM_EXT(_name,_type,_ptype,_def,_doc,...) \ - ((_name,_type,_ptype,_def,_doc,_name,_ptype,App::Prop_None," Link")) +#define _LINK_PARAM_EXT(_name, _type, _ptype, _def, _doc, ...) \ + ((_name, _type, _ptype, _def, _doc, _name, _ptype, App::Prop_None, " Link")) /** Define default extended parameter * It simply reuses Name as Property_Name, Property_Type as @@ -466,44 +568,46 @@ class AppExport LinkExtension : public LinkBaseExtension #define LINK_PARAM_EXT(_param) BOOST_PP_EXPAND(_LINK_PARAM_EXT LINK_PARAM_##_param()) /// Helper for extended parameter with app property type -#define _LINK_PARAM_EXT_ATYPE(_name,_type,_ptype,_def,_doc,_atype) \ - ((_name,_type,_ptype,_def,_doc,_name,_ptype,_atype," Link")) +#define _LINK_PARAM_EXT_ATYPE(_name, _type, _ptype, _def, _doc, _atype) \ + ((_name, _type, _ptype, _def, _doc, _name, _ptype, _atype, " Link")) /// Define extended parameter with app property type -#define LINK_PARAM_EXT_ATYPE(_param,_atype) \ +#define LINK_PARAM_EXT_ATYPE(_param, _atype) \ BOOST_PP_EXPAND(_LINK_PARAM_EXT_ATYPE LINK_PARAM_##_param(_atype)) /// Helper for extended parameter with derived property type -#define _LINK_PARAM_EXT_TYPE(_name,_type,_ptype,_def,_doc,_dtype) \ - ((_name,_type,_ptype,_def,_doc,_name,_dtype,App::Prop_None," Link")) +#define _LINK_PARAM_EXT_TYPE(_name, _type, _ptype, _def, _doc, _dtype) \ + ((_name, _type, _ptype, _def, _doc, _name, _dtype, App::Prop_None, " Link")) /// Define extended parameter with derived property type -#define LINK_PARAM_EXT_TYPE(_param,_dtype) \ +#define LINK_PARAM_EXT_TYPE(_param, _dtype) \ BOOST_PP_EXPAND(_LINK_PARAM_EXT_TYPE LINK_PARAM_##_param(_dtype)) /// Helper for extended parameter with a different property name -#define _LINK_PARAM_EXT_NAME(_name,_type,_ptype,_def,_doc,_pname) \ - ((_name,_type,_ptype,_def,_doc,_pname,_ptype,App::Prop_None," Link")) +#define _LINK_PARAM_EXT_NAME(_name, _type, _ptype, _def, _doc, _pname) \ + ((_name, _type, _ptype, _def, _doc, _pname, _ptype, App::Prop_None, " Link")) /// Define extended parameter with a different property name -#define LINK_PARAM_EXT_NAME(_param,_pname) BOOST_PP_EXPAND(_LINK_PARAM_EXT_NAME LINK_PARAM_##_param(_pname)) +#define LINK_PARAM_EXT_NAME(_param, _pname) \ + BOOST_PP_EXPAND(_LINK_PARAM_EXT_NAME LINK_PARAM_##_param(_pname)) //@} -#define LINK_PARAMS_EXT \ - LINK_PARAM_EXT(SCALE)\ - LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\ - LINK_PARAM_EXT(SCALES)\ - LINK_PARAM_EXT(VISIBILITIES)\ - LINK_PARAM_EXT(PLACEMENTS)\ +#define LINK_PARAMS_EXT \ + LINK_PARAM_EXT(SCALE) \ + LINK_PARAM_EXT_ATYPE(SCALE_VECTOR, App::Prop_Hidden) \ + LINK_PARAM_EXT(SCALES) \ + LINK_PARAM_EXT(VISIBILITIES) \ + LINK_PARAM_EXT(PLACEMENTS) \ LINK_PARAM_EXT(ELEMENTS) -#define LINK_PROP_DEFINE(_1,_2,_param) LINK_ETYPE(_param) LINK_ENAME(_param); -#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE,_,_seq) +#define LINK_PROP_DEFINE(_1, _2, _param) LINK_ETYPE(_param) LINK_ENAME(_param); +#define LINK_PROPS_DEFINE(_seq) BOOST_PP_SEQ_FOR_EACH(LINK_PROP_DEFINE, _, _seq) // defines the actual properties LINK_PROPS_DEFINE(LINK_PARAMS_EXT) - void onExtendedDocumentRestored() override { + void onExtendedDocumentRestored() override + { LINK_PROPS_SET(LINK_PARAMS_EXT); inherited::onExtendedDocumentRestored(); } @@ -515,44 +619,47 @@ using LinkExtensionPython = ExtensionPythonT; /////////////////////////////////////////////////////////////////////////// -class AppExport Link : public App::DocumentObject, public App::LinkExtension +class AppExport Link: public App::DocumentObject, public App::LinkExtension { PROPERTY_HEADER_WITH_EXTENSIONS(App::Link); using inherited = App::DocumentObject; -public: -#define LINK_PARAMS_LINK \ - LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\ - LINK_PARAM_EXT(CLAIM_CHILD)\ - LINK_PARAM_EXT(TRANSFORM)\ - LINK_PARAM_EXT(LINK_PLACEMENT)\ - LINK_PARAM_EXT(PLACEMENT)\ - LINK_PARAM_EXT(SHOW_ELEMENT)\ - LINK_PARAM_EXT_TYPE(COUNT,App::PropertyIntegerConstraint)\ - LINK_PARAM_EXT(LINK_EXECUTE)\ - LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden)\ - LINK_PARAM_EXT(COPY_ON_CHANGE)\ - LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\ - LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\ - LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\ +public: +#define LINK_PARAMS_LINK \ + LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink) \ + LINK_PARAM_EXT(CLAIM_CHILD) \ + LINK_PARAM_EXT(TRANSFORM) \ + LINK_PARAM_EXT(LINK_PLACEMENT) \ + LINK_PARAM_EXT(PLACEMENT) \ + LINK_PARAM_EXT(SHOW_ELEMENT) \ + LINK_PARAM_EXT_TYPE(COUNT, App::PropertyIntegerConstraint) \ + LINK_PARAM_EXT(LINK_EXECUTE) \ + LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS, App::Prop_Hidden) \ + LINK_PARAM_EXT(COPY_ON_CHANGE) \ + LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink) \ + LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP) \ + LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED) LINK_PROPS_DEFINE(LINK_PARAMS_LINK) Link(); - const char* getViewProviderName() const override{ + const char* getViewProviderName() const override + { return "Gui::ViewProviderLink"; } - void onDocumentRestored() override { + void onDocumentRestored() override + { LINK_PROPS_SET(LINK_PARAMS_LINK); inherited::onDocumentRestored(); } - void handleChangedPropertyName(Base::XMLReader &reader, - const char * TypeName, const char *PropName) override + void handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) override { - _handleChangedPropertyName(reader,TypeName,PropName); + _handleChangedPropertyName(reader, TypeName, PropName); } bool canLinkProperties() const override; @@ -566,42 +673,46 @@ using LinkPython = App::FeaturePythonT; /////////////////////////////////////////////////////////////////////////// -class AppExport LinkElement : public App::DocumentObject, public App::LinkBaseExtension { +class AppExport LinkElement: public App::DocumentObject, public App::LinkBaseExtension +{ PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkElement); using inherited = App::DocumentObject; -public: -#define LINK_PARAMS_ELEMENT \ - LINK_PARAM_EXT(SCALE)\ - LINK_PARAM_EXT_ATYPE(SCALE_VECTOR,App::Prop_Hidden)\ - LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink)\ - LINK_PARAM_EXT(TRANSFORM) \ - LINK_PARAM_EXT(LINK_PLACEMENT)\ - LINK_PARAM_EXT(PLACEMENT)\ - LINK_PARAM_EXT(COPY_ON_CHANGE)\ - LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink)\ - LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP)\ - LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED)\ +public: +#define LINK_PARAMS_ELEMENT \ + LINK_PARAM_EXT(SCALE) \ + LINK_PARAM_EXT_ATYPE(SCALE_VECTOR, App::Prop_Hidden) \ + LINK_PARAM_EXT_TYPE(OBJECT, App::PropertyXLink) \ + LINK_PARAM_EXT(TRANSFORM) \ + LINK_PARAM_EXT(LINK_PLACEMENT) \ + LINK_PARAM_EXT(PLACEMENT) \ + LINK_PARAM_EXT(COPY_ON_CHANGE) \ + LINK_PARAM_EXT_TYPE(COPY_ON_CHANGE_SOURCE, App::PropertyXLink) \ + LINK_PARAM_EXT(COPY_ON_CHANGE_GROUP) \ + LINK_PARAM_EXT(COPY_ON_CHANGE_TOUCHED) // defines the actual properties LINK_PROPS_DEFINE(LINK_PARAMS_ELEMENT) LinkElement(); - const char* getViewProviderName() const override{ + const char* getViewProviderName() const override + { return "Gui::ViewProviderLink"; } - void onDocumentRestored() override { + void onDocumentRestored() override + { LINK_PROPS_SET(LINK_PARAMS_ELEMENT); inherited::onDocumentRestored(); } bool canDelete() const; - void handleChangedPropertyName(Base::XMLReader &reader, - const char * TypeName, const char *PropName) override + void handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) override { - _handleChangedPropertyName(reader,TypeName,PropName); + _handleChangedPropertyName(reader, TypeName, PropName); } bool isLink() const override; @@ -613,28 +724,31 @@ using LinkElementPython = App::FeaturePythonT; /////////////////////////////////////////////////////////////////////////// -class AppExport LinkGroup : public App::DocumentObject, public App::LinkBaseExtension { +class AppExport LinkGroup: public App::DocumentObject, public App::LinkBaseExtension +{ PROPERTY_HEADER_WITH_EXTENSIONS(App::LinkGroup); using inherited = App::DocumentObject; -public: -#define LINK_PARAMS_GROUP \ - LINK_PARAM_EXT(ELEMENTS)\ - LINK_PARAM_EXT(PLACEMENT)\ - LINK_PARAM_EXT(VISIBILITIES)\ - LINK_PARAM_EXT(MODE)\ - LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS,App::Prop_Hidden) +public: +#define LINK_PARAMS_GROUP \ + LINK_PARAM_EXT(ELEMENTS) \ + LINK_PARAM_EXT(PLACEMENT) \ + LINK_PARAM_EXT(VISIBILITIES) \ + LINK_PARAM_EXT(MODE) \ + LINK_PARAM_EXT_ATYPE(COLORED_ELEMENTS, App::Prop_Hidden) // defines the actual properties LINK_PROPS_DEFINE(LINK_PARAMS_GROUP) LinkGroup(); - const char* getViewProviderName() const override{ + const char* getViewProviderName() const override + { return "Gui::ViewProviderLink"; } - void onDocumentRestored() override { + void onDocumentRestored() override + { LINK_PROPS_SET(LINK_PARAMS_GROUP); inherited::onDocumentRestored(); } @@ -642,7 +756,7 @@ class AppExport LinkGroup : public App::DocumentObject, public App::LinkBaseExte using LinkGroupPython = App::FeaturePythonT; -} //namespace App +} // namespace App ENABLE_BITMASK_OPERATORS(App::Link::OnChangeCopyOptions) @@ -651,7 +765,8 @@ import LinkParams LinkParams.declare() ]]]*/ -namespace App { +namespace App +{ /** Convenient class to obtain App::Link related parameters * The parameters are under group "User parameter:BaseApp/Preferences/Link" @@ -682,7 +797,8 @@ namespace App { * void LinkParams:onChanged() * @endcode */ -class AppExport LinkParams { +class AppExport LinkParams +{ public: static ParameterGrp::handle getHandle(); @@ -691,21 +807,21 @@ class AppExport LinkParams { /// /// Stores the last user choice of whether to apply CopyOnChange setup to all link /// that links to the same configurable object - static const bool & getCopyOnChangeApplyToAll(); - static const bool & defaultCopyOnChangeApplyToAll(); + static const bool& getCopyOnChangeApplyToAll(); + static const bool& defaultCopyOnChangeApplyToAll(); static void removeCopyOnChangeApplyToAll(); - static void setCopyOnChangeApplyToAll(const bool &v); - static const char *docCopyOnChangeApplyToAll(); + static void setCopyOnChangeApplyToAll(const bool& v); + static const char* docCopyOnChangeApplyToAll(); //@} // Auto generated code. See class document of LinkParams. }; -} // namespace App +} // namespace App //[[[end]]] #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif -#endif // APP_LINK_H +#endif // APP_LINK_H diff --git a/src/App/LinkBaseExtensionPyImp.cpp b/src/App/LinkBaseExtensionPyImp.cpp index 10819f290103..5cf44fea82d4 100644 --- a/src/App/LinkBaseExtensionPyImp.cpp +++ b/src/App/LinkBaseExtensionPyImp.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "DocumentObjectPy.h" @@ -40,155 +40,167 @@ std::string LinkBaseExtensionPy::representation() const return str.str(); } -using PropTmpMap = std::map >; +using PropTmpMap = std::map>; using PropMap = std::map; -static bool getProperty(PropTmpMap &props, const LinkBaseExtension::PropInfoMap &infoMap, - const PropMap &propMap, PyObject *key, PyObject *value) +static bool getProperty(PropTmpMap& props, + const LinkBaseExtension::PropInfoMap& infoMap, + const PropMap& propMap, + PyObject* key, + PyObject* value) { std::ostringstream str; - if(!PyUnicode_Check(key)) { + if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "key must be a unicode string"); return false; } - const char *keyStr = PyUnicode_AsUTF8(key); + const char* keyStr = PyUnicode_AsUTF8(key); auto it = infoMap.find(keyStr); - if(it == infoMap.end()){ + if (it == infoMap.end()) { str << "unknown key '" << keyStr << "'"; PyErr_SetString(PyExc_KeyError, str.str().c_str()); return false; } - const char *valStr = nullptr; - if(key == value) + const char* valStr = nullptr; + if (key == value) { valStr = keyStr; - else if (value!=Py_None) { - if(!PyUnicode_Check(value)) { + } + else if (value != Py_None) { + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "value must be unicode string"); return false; } valStr = PyUnicode_AsUTF8(value); } - App::Property *prop = nullptr; - auto &info = it->second; - if(valStr) { + App::Property* prop = nullptr; + auto& info = it->second; + if (valStr) { auto pIt = propMap.find(valStr); - if(pIt == propMap.end()) { + if (pIt == propMap.end()) { str << "cannot find property '" << valStr << "'"; PyErr_SetString(PyExc_ValueError, str.str().c_str()); return false; } prop = pIt->second; - if(!prop->isDerivedFrom(info.type)) { - str << "expect property '" << keyStr << "(" << valStr - << ") to be derived from '" << info.type.getName() - << "', instead of '" << prop->getTypeId().getName() << "'"; + if (!prop->isDerivedFrom(info.type)) { + str << "expect property '" << keyStr << "(" << valStr << ") to be derived from '" + << info.type.getName() << "', instead of '" << prop->getTypeId().getName() << "'"; PyErr_SetString(PyExc_TypeError, str.str().c_str()); } } - props[keyStr] = std::make_pair(info.index,prop); + props[keyStr] = std::make_pair(info.index, prop); return true; } -PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject *args, PyObject *keywds) { +PyObject* LinkBaseExtensionPy::configLinkProperty(PyObject* args, PyObject* keywds) +{ auto ext = getLinkBaseExtensionPtr(); - const auto &info = ext->getPropertyInfoMap(); + const auto& info = ext->getPropertyInfoMap(); PropMap propMap; ext->getExtendedContainer()->getPropertyMap(propMap); PropTmpMap props; - if(args && PyTuple_Check(args)) { - for(Py_ssize_t pos=0;possetProperty(v.second.first,v.second.second); + for (auto& v : props) { + ext->setProperty(v.second.first, v.second.second); + } Py_Return; } -PyObject* LinkBaseExtensionPy::getLinkExtProperty(PyObject *args) +PyObject* LinkBaseExtensionPy::getLinkExtProperty(PyObject* args) { - const char *name; - if(!PyArg_ParseTuple(args,"s",&name)) + const char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { return nullptr; + } auto prop = getLinkBaseExtensionPtr()->getProperty(name); - if(!prop) { + if (!prop) { PyErr_SetString(PyExc_AttributeError, "unknown property name"); return nullptr; } return prop->getPyObject(); } -PyObject* LinkBaseExtensionPy::getLinkExtPropertyName(PyObject *args) { - const char *name; - if(!PyArg_ParseTuple(args,"s",&name)) +PyObject* LinkBaseExtensionPy::getLinkExtPropertyName(PyObject* args) +{ + const char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { return nullptr; + } auto prop = getLinkBaseExtensionPtr()->getProperty(name); - if(!prop) { + if (!prop) { PyErr_SetString(PyExc_AttributeError, "unknown property name"); return nullptr; } auto container = getLinkBaseExtensionPtr()->getExtendedContainer(); - if(!container) { + if (!container) { PyErr_SetString(PyExc_RuntimeError, "no extended container"); return nullptr; } name = container->getPropertyName(prop); - if(!name) { + if (!name) { PyErr_SetString(PyExc_RuntimeError, "cannot find property name"); return nullptr; } return Py::new_reference_to(Py::String(name)); } -PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args) +PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject* args) { auto ext = getLinkBaseExtensionPtr(); - const auto &infos = ext->getPropertyInfo(); + const auto& infos = ext->getPropertyInfo(); - if(PyArg_ParseTuple(args,"")) { + if (PyArg_ParseTuple(args, "")) { Py::Tuple ret(infos.size()); - int i=0; - for(const auto &info : infos) { - ret.setItem(i++,Py::TupleN(Py::String(info.name), - Py::String(info.type.getName()),Py::String(info.doc))); + int i = 0; + for (const auto& info : infos) { + ret.setItem(i++, + Py::TupleN(Py::String(info.name), + Py::String(info.type.getName()), + Py::String(info.doc))); } return Py::new_reference_to(ret); } short index = 0; - if(PyArg_ParseTuple(args,"h",&index)) { - if(index<0 || index>=(int)infos.size()) { + if (PyArg_ParseTuple(args, "h", &index)) { + if (index < 0 || index >= (int)infos.size()) { PyErr_SetString(PyExc_ValueError, "index out of range"); return nullptr; } Py::TupleN ret(Py::String(infos[index].name), - Py::String(infos[index].type.getName()),Py::String(infos[index].doc)); + Py::String(infos[index].type.getName()), + Py::String(infos[index].doc)); return Py::new_reference_to(ret); } - char *name; - if(PyArg_ParseTuple(args,"s",&name)) { - for(const auto & info : infos) { - if(strcmp(info.name,name)==0) { - Py::TupleN ret(Py::String(info.type.getName()), - Py::String(info.doc)); + char* name; + if (PyArg_ParseTuple(args, "s", &name)) { + for (const auto& info : infos) { + if (strcmp(info.name, name) == 0) { + Py::TupleN ret(Py::String(info.type.getName()), Py::String(info.doc)); return Py::new_reference_to(ret); } } @@ -200,101 +212,128 @@ PyObject* LinkBaseExtensionPy::getLinkPropertyInfo(PyObject *args) return nullptr; } -void parseLink(LinkBaseExtension *ext, int index, PyObject *value) { - App::DocumentObject *obj = nullptr; +void parseLink(LinkBaseExtension* ext, int index, PyObject* value) +{ + App::DocumentObject* obj = nullptr; PropertyStringList subs; PropertyString sub; - if(value!=Py_None) { - if(PyObject_TypeCheck(value,&DocumentObjectPy::Type)) { + if (value != Py_None) { + if (PyObject_TypeCheck(value, &DocumentObjectPy::Type)) { obj = static_cast(value)->getDocumentObjectPtr(); - }else if(!PySequence_Check(value)) + } + else if (!PySequence_Check(value)) { throw Base::TypeError("Expects type of DocumentObject or sequence"); - else{ + } + else { Py::Sequence seq(value); - if(seq[0].ptr() != Py_None) { - if(!PyObject_TypeCheck(seq[0].ptr(),&DocumentObjectPy::Type)) - throw Base::TypeError("Expects the first argument to be DocumentObject in sequence"); + if (seq[0].ptr() != Py_None) { + if (!PyObject_TypeCheck(seq[0].ptr(), &DocumentObjectPy::Type)) { + throw Base::TypeError( + "Expects the first argument to be DocumentObject in sequence"); + } obj = static_cast(seq[0].ptr())->getDocumentObjectPtr(); - if(seq.size()>1) { + if (seq.size() > 1) { sub.setPyObject(seq[1].ptr()); - if(seq.size()>2) + if (seq.size() > 2) { subs.setPyObject(seq[2].ptr()); + } } } } } - ext->setLink(index,obj,sub.getValue(),subs.getValue()); + ext->setLink(index, obj, sub.getValue(), subs.getValue()); } -PyObject* LinkBaseExtensionPy::setLink(PyObject *_args) +PyObject* LinkBaseExtensionPy::setLink(PyObject* _args) { Py::Sequence args(_args); - PY_TRY { + PY_TRY + { auto ext = getLinkBaseExtensionPtr(); - PyObject *pcObj = args.size()?args[0].ptr():Py_None; - if(pcObj == Py_None) { - ext->setLink(-1,nullptr); - }else if(PyDict_Check(pcObj)) { + PyObject* pcObj = args.size() ? args[0].ptr() : Py_None; + if (pcObj == Py_None) { + ext->setLink(-1, nullptr); + } + else if (PyDict_Check(pcObj)) { PyObject *key, *value; Py_ssize_t pos = 0; - while(PyDict_Next(pcObj, &pos, &key, &value)) - parseLink(ext,Py::Int(key),value); - }else if(PySequence_Check(pcObj)) { - ext->setLink(-1,nullptr); + while (PyDict_Next(pcObj, &pos, &key, &value)) { + parseLink(ext, Py::Int(key), value); + } + } + else if (PySequence_Check(pcObj)) { + ext->setLink(-1, nullptr); Py::Sequence seq(pcObj); - for(Py_ssize_t i=0;icacheChildLabel(Base::asBoolean(enable) ? -1 : 0); Py_Return; - }PY_CATCH; + } + PY_CATCH; } -PyObject* LinkBaseExtensionPy::flattenSubname(PyObject *args) { - const char *subname; - if(!PyArg_ParseTuple(args,"s",&subname)) +PyObject* LinkBaseExtensionPy::flattenSubname(PyObject* args) +{ + const char* subname; + if (!PyArg_ParseTuple(args, "s", &subname)) { return nullptr; - PY_TRY { - return Py::new_reference_to(Py::String( - getLinkBaseExtensionPtr()->flattenSubname(subname))); - }PY_CATCH; + } + PY_TRY + { + return Py::new_reference_to(Py::String(getLinkBaseExtensionPtr()->flattenSubname(subname))); + } + PY_CATCH; } -PyObject* LinkBaseExtensionPy::expandSubname(PyObject *args) { - const char *subname; - if(!PyArg_ParseTuple(args,"s",&subname)) +PyObject* LinkBaseExtensionPy::expandSubname(PyObject* args) +{ + const char* subname; + if (!PyArg_ParseTuple(args, "s", &subname)) { return nullptr; - PY_TRY { + } + PY_TRY + { std::string sub(subname); getLinkBaseExtensionPtr()->expandSubname(sub); return Py::new_reference_to(Py::String(sub)); - }PY_CATCH; + } + PY_CATCH; } -Py::List LinkBaseExtensionPy::getLinkedChildren() const { +Py::List LinkBaseExtensionPy::getLinkedChildren() const +{ Py::List ret; - for(auto o : getLinkBaseExtensionPtr()->getLinkedChildren(true)) + for (auto o : getLinkBaseExtensionPtr()->getLinkedChildren(true)) { ret.append(Py::asObject(o->getPyObject())); + } return ret; } -PyObject *LinkBaseExtensionPy::getCustomAttributes(const char* /*attr*/) const +PyObject* LinkBaseExtensionPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } -int LinkBaseExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject * /*obj*/) +int LinkBaseExtensionPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } diff --git a/src/App/LinkParams.py b/src/App/LinkParams.py index ec02477535e4..237315252081 100644 --- a/src/App/LinkParams.py +++ b/src/App/LinkParams.py @@ -4,27 +4,33 @@ # Actual code generation is done in Base/param_utils.py. # The following code is to import param_util.py without needing __init__.py in Base directory -sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), 'Base')) +sys.path.append(path.join(path.dirname(path.dirname(path.abspath(__file__))), "Base")) import params_utils from params_utils import ParamBool, ParamInt, ParamString, ParamUInt, ParamFloat -NameSpace = 'App' -ClassName = 'LinkParams' -ParamPath = 'User parameter:BaseApp/Preferences/Link' -ClassDoc = 'Convenient class to obtain App::Link related parameters' -HeaderFile = 'Link.h' -SourceFile = 'Link.cpp' +NameSpace = "App" +ClassName = "LinkParams" +ParamPath = "User parameter:BaseApp/Preferences/Link" +ClassDoc = "Convenient class to obtain App::Link related parameters" +HeaderFile = "Link.h" +SourceFile = "Link.cpp" Params = [ - ParamBool('CopyOnChangeApplyToAll', True, '''\ + ParamBool( + "CopyOnChangeApplyToAll", + True, + """\ Stores the last user choice of whether to apply CopyOnChange setup to all link -that links to the same configurable object'''), +that links to the same configurable object""", + ), ] + def declare(): params_utils.declare_begin(sys.modules[__name__], header=False) params_utils.declare_end(sys.modules[__name__]) + def define(): params_utils.define(sys.modules[__name__], header=False) diff --git a/src/App/Metadata.h b/src/App/Metadata.h index fa5f14717c99..868315e63861 100644 --- a/src/App/Metadata.h +++ b/src/App/Metadata.h @@ -150,17 +150,17 @@ struct AppExport Dependency explicit Dependency(std::string pkg); explicit Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem); std::string package; //< Required: must exactly match the contents of the "name" element in the - //referenced package's package.xml file. + // referenced package's package.xml file. std::string version_lt; //< Optional: The dependency to the package is restricted to versions - //less than the stated version number. + // less than the stated version number. std::string version_lte; //< Optional: The dependency to the package is restricted to versions - //less or equal than the stated version number. + // less or equal than the stated version number. std::string version_eq; //< Optional: The dependency to the package is restricted to a version - //equal than the stated version number. + // equal than the stated version number. std::string version_gte; //< Optional: The dependency to the package is restricted to versions - //greater or equal than the stated version number. + // greater or equal than the stated version number. std::string version_gt; //< Optional: The dependency to the package is restricted to versions - //greater than the stated version number. + // greater than the stated version number. std::string condition; //< Optional: Conditional expression as documented in REP149. bool optional; //< Optional: Whether this dependency is considered "optional" DependencyType dependencyType; //< Optional: defaults to "automatic" @@ -238,7 +238,7 @@ class AppExport Metadata std::vector license() const; //< Must be at least one, and most licenses require including a license file. std::vector url() const; //< Any number of URLs may be specified, but at least one - //repository URL must be included at the package level. + // repository URL must be included at the package level. std::vector author() const; //< Any number of authors may be specified, and email addresses are optional. std::vector diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index a8294d3d9aa0..92593f0a8046 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -45,7 +45,7 @@ #include "Property.h" -FC_LOG_LEVEL_INIT("Expression",true,true) +FC_LOG_LEVEL_INIT("Expression", true, true) using namespace App; using namespace Base; @@ -60,43 +60,43 @@ using namespace Base; * @return */ -std::string App::quote(const std::string &input, bool toPython) +std::string App::quote(const std::string& input, bool toPython) { std::stringstream output; std::string::const_iterator cur = input.begin(); std::string::const_iterator end = input.end(); - output << (toPython?"'":"<<"); + output << (toPython ? "'" : "<<"); while (cur != end) { switch (*cur) { - case '\t': - output << "\\t"; - break; - case '\n': - output << "\\n"; - break; - case '\r': - output << "\\r"; - break; - case '\\': - output << "\\\\"; - break; - case '\'': - output << "\\'"; - break; - case '"': - output << "\\\""; - break; - case '>': - output << (toPython?">":"\\>"); - break; - default: - output << *cur; + case '\t': + output << "\\t"; + break; + case '\n': + output << "\\n"; + break; + case '\r': + output << "\\r"; + break; + case '\\': + output << "\\\\"; + break; + case '\'': + output << "\\'"; + break; + case '"': + output << "\\\""; + break; + case '>': + output << (toPython ? ">" : "\\>"); + break; + default: + output << *cur; } ++cur; } - output << (toPython?"'":">>"); + output << (toPython ? "'" : ">>"); return output.str(); } @@ -108,8 +108,9 @@ std::string App::quote(const std::string &input, bool toPython) * @param property Name of property. */ -ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, - const std::string & property, int index) +ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, + const std::string& property, + int index) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) @@ -117,9 +118,10 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, , _hash(0) { if (_owner) { - const DocumentObject * docObj = freecad_dynamic_cast(_owner); - if (!docObj) - FC_THROWM(Base::RuntimeError,"Property must be owned by a document object."); + const DocumentObject* docObj = freecad_dynamic_cast(_owner); + if (!docObj) { + FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); + } owner = const_cast(docObj); if (!property.empty()) { @@ -128,12 +130,13 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, } if (!property.empty()) { addComponent(SimpleComponent(property)); - if(index!=INT_MAX) + if (index != INT_MAX) { addComponent(ArrayComponent(index)); + } } } -ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, bool localProperty) +ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer* _owner, bool localProperty) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) @@ -141,39 +144,44 @@ ObjectIdentifier::ObjectIdentifier(const App::PropertyContainer * _owner, bool l , _hash(0) { if (_owner) { - const DocumentObject * docObj = freecad_dynamic_cast(_owner); - if (!docObj) - FC_THROWM(Base::RuntimeError,"Property must be owned by a document object."); + const DocumentObject* docObj = freecad_dynamic_cast(_owner); + if (!docObj) { + FC_THROWM(Base::RuntimeError, "Property must be owned by a document object."); + } owner = const_cast(docObj); } } /** - * @brief Construct an ObjectIdentifier object given a property. The property is assumed to be single-valued. + * @brief Construct an ObjectIdentifier object given a property. The property is assumed to be + * single-valued. * @param prop Property to construct object identifier for. */ -ObjectIdentifier::ObjectIdentifier(const Property &prop, int index) +ObjectIdentifier::ObjectIdentifier(const Property& prop, int index) : owner(nullptr) , documentNameSet(false) , documentObjectNameSet(false) , localProperty(false) , _hash(0) { - DocumentObject * docObj = freecad_dynamic_cast(prop.getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(prop.getContainer()); - if (!docObj) + if (!docObj) { FC_THROWM(Base::TypeError, "Property must be owned by a document object."); - if (!prop.hasName()) + } + if (!prop.hasName()) { FC_THROWM(Base::RuntimeError, "Property must have a name."); + } owner = const_cast(docObj); setDocumentObjectName(docObj); addComponent(SimpleComponent(String(prop.getName()))); - if(index!=INT_MAX) + if (index != INT_MAX) { addComponent(ArrayComponent(index)); + } } /** @@ -185,7 +193,8 @@ std::string App::ObjectIdentifier::getPropertyName() const { ResolveResults result(*this); - assert(result.propertyIndex >=0 && static_cast(result.propertyIndex) < components.size()); + assert(result.propertyIndex >= 0 + && static_cast(result.propertyIndex) < components.size()); return components[result.propertyIndex].getName(); } @@ -197,41 +206,48 @@ std::string App::ObjectIdentifier::getPropertyName() const * @return A component. */ -const App::ObjectIdentifier::Component &App::ObjectIdentifier::getPropertyComponent(int i, int *idx) const +const App::ObjectIdentifier::Component& App::ObjectIdentifier::getPropertyComponent(int i, + int* idx) const { ResolveResults result(*this); i += result.propertyIndex; - if (i < 0 || i >= static_cast(components.size())) + if (i < 0 || i >= static_cast(components.size())) { FC_THROWM(Base::ValueError, "Invalid property component index"); + } - if (idx) + if (idx) { *idx = i; + } return components[i]; } -void App::ObjectIdentifier::setComponent(int idx, Component &&comp) +void App::ObjectIdentifier::setComponent(int idx, Component&& comp) { - if (idx < 0 || idx >= static_cast(components.size())) + if (idx < 0 || idx >= static_cast(components.size())) { FC_THROWM(Base::ValueError, "Invalid component index"); + } components[idx] = std::move(comp); _cache.clear(); } -void App::ObjectIdentifier::setComponent(int idx, const Component &comp) +void App::ObjectIdentifier::setComponent(int idx, const Component& comp) { setComponent(idx, Component(comp)); } -std::vector ObjectIdentifier::getPropertyComponents() const { - if(components.size()<=1 || documentObjectName.getString().empty()) +std::vector ObjectIdentifier::getPropertyComponents() const +{ + if (components.size() <= 1 || documentObjectName.getString().empty()) { return components; + } ResolveResults result(*this); - if(result.propertyIndex==0) + if (result.propertyIndex == 0) { return components; + } std::vector res; - res.insert(res.end(),components.begin()+result.propertyIndex,components.end()); + res.insert(res.end(), components.begin() + result.propertyIndex, components.end()); return res; } @@ -241,9 +257,9 @@ std::vector ObjectIdentifier::getPropertyComponents * @return true if they are equal. */ -bool ObjectIdentifier::operator ==(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator==(const ObjectIdentifier& other) const { - return owner==other.owner && toString() == other.toString(); + return owner == other.owner && toString() == other.toString(); } /** @@ -252,7 +268,7 @@ bool ObjectIdentifier::operator ==(const ObjectIdentifier &other) const * @return true if they differ from each other. */ -bool ObjectIdentifier::operator !=(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator!=(const ObjectIdentifier& other) const { return !(operator==)(other); } @@ -263,12 +279,14 @@ bool ObjectIdentifier::operator !=(const ObjectIdentifier &other) const * @return true if this object is less than the other. */ -bool ObjectIdentifier::operator <(const ObjectIdentifier &other) const +bool ObjectIdentifier::operator<(const ObjectIdentifier& other) const { - if(owner < other.owner) + if (owner < other.owner) { return true; - if(owner > other.owner) + } + if (owner > other.owner) { return false; + } return toString() < other.toString(); } @@ -294,27 +312,30 @@ int ObjectIdentifier::numSubComponents() const return components.size() - result.propertyIndex; } -bool ObjectIdentifier::verify(const App::Property &prop, bool silent) const { +bool ObjectIdentifier::verify(const App::Property& prop, bool silent) const +{ ResolveResults result(*this); - if(components.size() - result.propertyIndex != 1) { - if(silent) + if (components.size() - result.propertyIndex != 1) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: single component expected"); + } + FC_THROWM(Base::ValueError, "Invalid property path: single component expected"); } - if(!components[result.propertyIndex].isSimple()) { - if(silent) + if (!components[result.propertyIndex].isSimple()) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: simple component expected"); + } + FC_THROWM(Base::ValueError, "Invalid property path: simple component expected"); } - const std::string &name = components[result.propertyIndex].getName(); + const std::string& name = components[result.propertyIndex].getName(); CellAddress addr; bool isAddress = addr.parseAbsoluteAddress(name.c_str()); - if((isAddress && addr.toString(CellAddress::Cell::ShowRowColumn) != prop.getName()) || - (!isAddress && name!=prop.getName())) - { - if(silent) + if ((isAddress && addr.toString(CellAddress::Cell::ShowRowColumn) != prop.getName()) + || (!isAddress && name != prop.getName())) { + if (silent) { return false; - FC_THROWM(Base::ValueError,"Invalid property path: name mismatch"); + } + FC_THROWM(Base::ValueError, "Invalid property path: name mismatch"); } return true; } @@ -323,143 +344,165 @@ bool ObjectIdentifier::verify(const App::Property &prop, bool silent) const { * @brief Create a string representation of this object identifier. * * An identifier is written as document#documentobject.property.subproperty1...subpropertyN - * document# may be dropped; it is assumed to be within owner's document. If documentobject is dropped, - * the property is assumed to be owned by the owner specified in the object identifiers constructor. + * document# may be dropped; it is assumed to be within owner's document. If documentobject is + * dropped, the property is assumed to be owned by the owner specified in the object identifiers + * constructor. * * @return A string */ -const std::string &ObjectIdentifier::toString() const +const std::string& ObjectIdentifier::toString() const { - if(!_cache.empty() || !owner) + if (!_cache.empty() || !owner) { return _cache; + } std::ostringstream s; ResolveResults result(*this); - if(result.propertyIndex >= (int)components.size()) + if (result.propertyIndex >= (int)components.size()) { return _cache; + } - if(localProperty || - (result.resolvedProperty && - result.resolvedDocumentObject==owner && - components.size()>1 && - components[1].isSimple() && - result.propertyIndex==0)) - { + if (localProperty + || (result.resolvedProperty && result.resolvedDocumentObject == owner + && components.size() > 1 && components[1].isSimple() && result.propertyIndex == 0)) { s << '.'; - }else if (documentNameSet && !documentName.getString().empty()) { - if(documentObjectNameSet && !documentObjectName.getString().empty()) - s << documentName.toString() << "#" - << documentObjectName.toString() << '.'; - else if(!result.resolvedDocumentObjectName.getString().empty()) - s << documentName.toString() << "#" - << result.resolvedDocumentObjectName.toString() << '.'; - } else if (documentObjectNameSet && !documentObjectName.getString().empty()) { + } + else if (documentNameSet && !documentName.getString().empty()) { + if (documentObjectNameSet && !documentObjectName.getString().empty()) { + s << documentName.toString() << "#" << documentObjectName.toString() << '.'; + } + else if (!result.resolvedDocumentObjectName.getString().empty()) { + s << documentName.toString() << "#" << result.resolvedDocumentObjectName.toString() + << '.'; + } + } + else if (documentObjectNameSet && !documentObjectName.getString().empty()) { s << documentObjectName.toString() << '.'; - } else if (result.propertyIndex > 0) { + } + else if (result.propertyIndex > 0) { components[0].toString(s); s << '.'; } - if(!subObjectName.getString().empty()) + if (!subObjectName.getString().empty()) { s << subObjectName.toString() << '.'; + } s << components[result.propertyIndex].getName(); - getSubPathStr(s,result); + getSubPathStr(s, result); const_cast(this)->_cache = s.str(); return _cache; } -std::string ObjectIdentifier::toPersistentString() const { +std::string ObjectIdentifier::toPersistentString() const +{ - if(!owner) + if (!owner) { return {}; + } std::ostringstream s; ResolveResults result(*this); - if(result.propertyIndex >= (int)components.size()) + if (result.propertyIndex >= (int)components.size()) { return {}; + } - if(localProperty || - (result.resolvedProperty && - result.resolvedDocumentObject==owner && - components.size()>1 && - components[1].isSimple() && - result.propertyIndex==0)) - { + if (localProperty + || (result.resolvedProperty && result.resolvedDocumentObject == owner + && components.size() > 1 && components[1].isSimple() && result.propertyIndex == 0)) { s << '.'; - }else if(result.resolvedDocumentObject && - result.resolvedDocumentObject!=owner && - result.resolvedDocumentObject->isExporting()) - { + } + else if (result.resolvedDocumentObject && result.resolvedDocumentObject != owner + && result.resolvedDocumentObject->isExporting()) { s << result.resolvedDocumentObject->getExportName(true); - if(documentObjectName.isRealString()) + if (documentObjectName.isRealString()) { s << '@'; + } s << '.'; - } else if (documentNameSet && !documentName.getString().empty()) { - if(documentObjectNameSet && !documentObjectName.getString().empty()) - s << documentName.toString() << "#" - << documentObjectName.toString() << '.'; - else if(!result.resolvedDocumentObjectName.getString().empty()) - s << documentName.toString() << "#" - << result.resolvedDocumentObjectName.toString() << '.'; - } else if (documentObjectNameSet && !documentObjectName.getString().empty()) { + } + else if (documentNameSet && !documentName.getString().empty()) { + if (documentObjectNameSet && !documentObjectName.getString().empty()) { + s << documentName.toString() << "#" << documentObjectName.toString() << '.'; + } + else if (!result.resolvedDocumentObjectName.getString().empty()) { + s << documentName.toString() << "#" << result.resolvedDocumentObjectName.toString() + << '.'; + } + } + else if (documentObjectNameSet && !documentObjectName.getString().empty()) { s << documentObjectName.toString() << '.'; - } else if (result.propertyIndex > 0) { + } + else if (result.propertyIndex > 0) { components[0].toString(s); s << '.'; } - if(!subObjectName.getString().empty()) { - const char *subname = subObjectName.getString().c_str(); + if (!subObjectName.getString().empty()) { + const char* subname = subObjectName.getString().c_str(); std::string exportName; s << String(PropertyLinkBase::exportSubName(exportName, - result.resolvedDocumentObject,subname),true).toString() << '.'; + result.resolvedDocumentObject, + subname), + true) + .toString() + << '.'; } s << components[result.propertyIndex].getName(); - getSubPathStr(s,result); + getSubPathStr(s, result); return s.str(); } std::size_t ObjectIdentifier::hash() const { - if(_hash && !_cache.empty()) + if (_hash && !_cache.empty()) { return _hash; + } const_cast(this)->_hash = boost::hash_value(toString()); return _hash; } -bool ObjectIdentifier::replaceObject(ObjectIdentifier &res, const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +bool ObjectIdentifier::replaceObject(ObjectIdentifier& res, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { ResolveResults result(*this); - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return false; + } - auto r = PropertyLinkBase::tryReplaceLink(owner, result.resolvedDocumentObject, - parent, oldObj, newObj, subObjectName.getString().c_str()); + auto r = PropertyLinkBase::tryReplaceLink(owner, + result.resolvedDocumentObject, + parent, + oldObj, + newObj, + subObjectName.getString().c_str()); - if(!r.first) + if (!r.first) { return false; + } res = *this; - if(r.first != result.resolvedDocumentObject) { - if(r.first->getDocument()!=owner->getDocument()) { + if (r.first != result.resolvedDocumentObject) { + if (r.first->getDocument() != owner->getDocument()) { auto doc = r.first->getDocument(); bool useLabel = res.documentName.isRealString(); - const char *name = useLabel?doc->Label.getValue():doc->getName(); + const char* name = useLabel ? doc->Label.getValue() : doc->getName(); res.setDocumentName(String(name, useLabel), true); } - if(documentObjectName.isRealString()) - res.documentObjectName = String(r.first->Label.getValue(),true); - else - res.documentObjectName = String(r.first->getNameInDocument(),false,true); + if (documentObjectName.isRealString()) { + res.documentObjectName = String(r.first->Label.getValue(), true); + } + else { + res.documentObjectName = String(r.first->getNameInDocument(), false, true); + } } - res.subObjectName = String(r.second,true); + res.subObjectName = String(r.second, true); res._cache.clear(); res.shadowSub.newName.clear(); res.shadowSub.oldName.clear(); @@ -476,37 +519,46 @@ std::string ObjectIdentifier::toEscapedString() const return Base::Tools::escapedUnicodeFromUtf8(toString().c_str()); } -bool ObjectIdentifier::updateLabelReference( - App::DocumentObject *obj, const std::string &ref, const char *newLabel) +bool ObjectIdentifier::updateLabelReference(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) { - if(!owner) + if (!owner) { return false; + } ResolveResults result(*this); - if(!subObjectName.getString().empty() && result.resolvedDocumentObject) { - std::string sub = PropertyLinkBase::updateLabelReference( - result.resolvedDocumentObject, subObjectName.getString().c_str(), obj,ref,newLabel); - if(!sub.empty()) { - subObjectName = String(sub,true); + if (!subObjectName.getString().empty() && result.resolvedDocumentObject) { + std::string sub = PropertyLinkBase::updateLabelReference(result.resolvedDocumentObject, + subObjectName.getString().c_str(), + obj, + ref, + newLabel); + if (!sub.empty()) { + subObjectName = String(sub, true); _cache.clear(); return true; } } - if(result.resolvedDocument != obj->getDocument()) + if (result.resolvedDocument != obj->getDocument()) { return false; + } - if(!documentObjectName.getString().empty()) { - if(documentObjectName.isForceIdentifier()) + if (!documentObjectName.getString().empty()) { + if (documentObjectName.isForceIdentifier()) { return false; + } - if(!documentObjectName.isRealString() && - documentObjectName.getString()==obj->getNameInDocument()) + if (!documentObjectName.isRealString() + && documentObjectName.getString() == obj->getNameInDocument()) { return false; + } - if(documentObjectName.getString()!=obj->Label.getValue()) + if (documentObjectName.getString() != obj->Label.getValue()) { return false; + } documentObjectName = ObjectIdentifier::String(newLabel, true); @@ -514,11 +566,9 @@ bool ObjectIdentifier::updateLabelReference( return true; } - if (result.resolvedDocumentObject==obj && - result.propertyIndex == 1 && - result.resolvedDocumentObjectName.isRealString() && - result.resolvedDocumentObjectName.getString()==obj->Label.getValue()) - { + if (result.resolvedDocumentObject == obj && result.propertyIndex == 1 + && result.resolvedDocumentObjectName.isRealString() + && result.resolvedDocumentObjectName.getString() == obj->Label.getValue()) { components[0].name = ObjectIdentifier::String(newLabel, true); _cache.clear(); return true; @@ -526,7 +576,7 @@ bool ObjectIdentifier::updateLabelReference( // If object identifier uses the label then resolving the document object will fail. // So, it must be checked if using the new label will succeed - if (components.size()>1 && components[0].getName()==obj->Label.getValue()) { + if (components.size() > 1 && components[0].getName() == obj->Label.getValue()) { ObjectIdentifier id(*this); id.components[0].name.str = newLabel; @@ -542,12 +592,13 @@ bool ObjectIdentifier::updateLabelReference( return false; } -bool ObjectIdentifier::relabeledDocument(ExpressionVisitor &v, - const std::string &oldLabel, const std::string &newLabel) +bool ObjectIdentifier::relabeledDocument(ExpressionVisitor& v, + const std::string& oldLabel, + const std::string& newLabel) { - if (documentNameSet && documentName.isRealString() && documentName.getString()==oldLabel) { + if (documentNameSet && documentName.isRealString() && documentName.getString() == oldLabel) { v.aboutToChange(); - documentName = String(newLabel,true); + documentName = String(newLabel, true); _cache.clear(); return true; } @@ -559,20 +610,24 @@ bool ObjectIdentifier::relabeledDocument(ExpressionVisitor &v, * @return String representation of path. */ -void ObjectIdentifier::getSubPathStr(std::ostream &s, const ResolveResults &result, bool toPython) const +void ObjectIdentifier::getSubPathStr(std::ostream& s, + const ResolveResults& result, + bool toPython) const { std::vector::const_iterator i = components.begin() + result.propertyIndex + 1; while (i != components.end()) { - if(i->isSimple()) + if (i->isSimple()) { s << '.'; - i->toString(s,toPython); + } + i->toString(s, toPython); ++i; } } -std::string ObjectIdentifier::getSubPathStr(bool toPython) const { +std::string ObjectIdentifier::getSubPathStr(bool toPython) const +{ std::ostringstream ss; - getSubPathStr(ss,ResolveResults(*this),toPython); + getSubPathStr(ss, ResolveResults(*this), toPython); return ss.str(); } @@ -585,107 +640,143 @@ std::string ObjectIdentifier::getSubPathStr(bool toPython) const { * @param _end ending of a Range, or INT_MAX for other type. */ -ObjectIdentifier::Component::Component(const String &_name, - ObjectIdentifier::Component::typeEnum _type, int _begin, int _end, int _step) +ObjectIdentifier::Component::Component(const String& _name, + ObjectIdentifier::Component::typeEnum _type, + int _begin, + int _end, + int _step) : name(_name) , type(_type) , begin(_begin) , end(_end) , step(_step) -{ -} +{} -ObjectIdentifier::Component::Component(String &&_name, - ObjectIdentifier::Component::typeEnum _type, int _begin, int _end, int _step) +ObjectIdentifier::Component::Component(String&& _name, + ObjectIdentifier::Component::typeEnum _type, + int _begin, + int _end, + int _step) : name(std::move(_name)) , type(_type) , begin(_begin) , end(_end) , step(_step) -{ -} +{} -size_t ObjectIdentifier::Component::getIndex(size_t count) const { - if(begin>=0) { - if(begin<(int)count) +size_t ObjectIdentifier::Component::getIndex(size_t count) const +{ + if (begin >= 0) { + if (begin < (int)count) { return begin; - }else { + } + } + else { int idx = begin + (int)count; - if(idx >= 0) + if (idx >= 0) { return idx; + } } FC_THROWM(Base::IndexError, "Array out of bound: " << begin << ", " << count); } -Py::Object ObjectIdentifier::Component::get(const Py::Object &pyobj) const { +Py::Object ObjectIdentifier::Component::get(const Py::Object& pyobj) const +{ Py::Object res; - if(isSimple()) { - if(!pyobj.hasAttr(getName())) + if (isSimple()) { + if (!pyobj.hasAttr(getName())) { FC_THROWM(Base::AttributeError, "No attribute named '" << getName() << "'"); + } res = pyobj.getAttr(getName()); - } else if(isArray()) { - if(pyobj.isMapping()) + } + else if (isArray()) { + if (pyobj.isMapping()) { res = Py::Mapping(pyobj).getItem(Py::Int(begin)); - else + } + else { res = Py::Sequence(pyobj).getItem(begin); - }else if(isMap()) + } + } + else if (isMap()) { res = Py::Mapping(pyobj).getItem(getName()); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - PyObject *r = PyObject_GetItem(pyobj.ptr(),slice.ptr()); - if(!r) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + PyObject* r = PyObject_GetItem(pyobj.ptr(), slice.ptr()); + if (!r) { Base::PyException::ThrowException(); + } res = Py::asObject(r); } - if(!res.ptr()) + if (!res.ptr()) { Base::PyException::ThrowException(); - if(PyModule_Check(res.ptr()) && !ExpressionParser::isModuleImported(res.ptr())) + } + if (PyModule_Check(res.ptr()) && !ExpressionParser::isModuleImported(res.ptr())) { FC_THROWM(Base::RuntimeError, "Module '" << getName() << "' access denied."); + } return res; } -void ObjectIdentifier::Component::set(Py::Object &pyobj, const Py::Object &value) const { - if(isSimple()) { - if(PyObject_SetAttrString(*pyobj, getName().c_str(), *value ) == -1) +void ObjectIdentifier::Component::set(Py::Object& pyobj, const Py::Object& value) const +{ + if (isSimple()) { + if (PyObject_SetAttrString(*pyobj, getName().c_str(), *value) == -1) { Base::PyException::ThrowException(); - } else if(isArray()) { - if(pyobj.isMapping()) - Py::Mapping(pyobj).setItem(Py::Int(begin),value); - else - Py::Sequence(pyobj).setItem(begin,value); - }else if(isMap()) - Py::Mapping(pyobj).setItem(getName(),value); + } + } + else if (isArray()) { + if (pyobj.isMapping()) { + Py::Mapping(pyobj).setItem(Py::Int(begin), value); + } + else { + Py::Sequence(pyobj).setItem(begin, value); + } + } + else if (isMap()) { + Py::Mapping(pyobj).setItem(getName(), value); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - if(PyObject_SetItem(pyobj.ptr(),slice.ptr(),value.ptr())<0) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + if (PyObject_SetItem(pyobj.ptr(), slice.ptr(), value.ptr()) < 0) { Base::PyException::ThrowException(); + } } } -void ObjectIdentifier::Component::del(Py::Object &pyobj) const { - if(isSimple()) +void ObjectIdentifier::Component::del(Py::Object& pyobj) const +{ + if (isSimple()) { pyobj.delAttr(getName()); - else if(isArray()) { - if(pyobj.isMapping()) + } + else if (isArray()) { + if (pyobj.isMapping()) { Py::Mapping(pyobj).delItem(Py::Int(begin)); - else - PySequence_DelItem(pyobj.ptr(),begin); - } else if(isMap()) + } + else { + PySequence_DelItem(pyobj.ptr(), begin); + } + } + else if (isMap()) { Py::Mapping(pyobj).delItem(getName()); + } else { assert(isRange()); Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end!=INT_MAX?Py::Int(end).ptr():nullptr, - step!=1?Py::Int(step).ptr():nullptr),true); - if(PyObject_DelItem(pyobj.ptr(),slice.ptr())<0) + end != INT_MAX ? Py::Int(end).ptr() : nullptr, + step != 1 ? Py::Int(step).ptr() : nullptr), + true); + if (PyObject_DelItem(pyobj.ptr(), slice.ptr()) < 0) { Base::PyException::ThrowException(); + } } } @@ -695,7 +786,7 @@ void ObjectIdentifier::Component::del(Py::Object &pyobj) const { * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const char *_component) +ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const char* _component) { return Component(String(_component)); } @@ -706,12 +797,14 @@ ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const c * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(const ObjectIdentifier::String &_component) +ObjectIdentifier::Component +ObjectIdentifier::Component::SimpleComponent(const ObjectIdentifier::String& _component) { return Component(_component); } -ObjectIdentifier::Component ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String &&_component) +ObjectIdentifier::Component +ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String&& _component) { return Component(std::move(_component)); } @@ -735,12 +828,12 @@ ObjectIdentifier::Component ObjectIdentifier::Component::ArrayComponent(int _ind * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(const String & _key) +ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(const String& _key) { return Component(_key, Component::MAP); } -ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String &&_key) +ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String&& _key) { return Component(std::move(_key), Component::MAP); } @@ -753,7 +846,8 @@ ObjectIdentifier::Component ObjectIdentifier::Component::MapComponent(String &&_ * @return A new Component object. */ -ObjectIdentifier::Component ObjectIdentifier::Component::RangeComponent(int _begin, int _end, int _step) +ObjectIdentifier::Component +ObjectIdentifier::Component::RangeComponent(int _begin, int _end, int _step) { return Component(String(), Component::RANGE, _begin, _end, _step); } @@ -764,22 +858,23 @@ ObjectIdentifier::Component ObjectIdentifier::Component::RangeComponent(int _beg * @return true if they are equal, false if not. */ -bool ObjectIdentifier::Component::operator ==(const ObjectIdentifier::Component &other) const +bool ObjectIdentifier::Component::operator==(const ObjectIdentifier::Component& other) const { - if (type != other.type) + if (type != other.type) { return false; + } switch (type) { - case SIMPLE: - case MAP: - return name == other.name; - case ARRAY: - return begin == other.begin; - case RANGE: - return begin == other.begin && end == other.end && step==other.step; - default: - assert(0); - return false; + case SIMPLE: + case MAP: + return name == other.name; + case ARRAY: + return begin == other.begin; + case RANGE: + return begin == other.begin && end == other.end && step == other.step; + default: + assert(0); + return false; } } @@ -788,35 +883,39 @@ bool ObjectIdentifier::Component::operator ==(const ObjectIdentifier::Component * @return A string representing the component. */ -void ObjectIdentifier::Component::toString(std::ostream &ss, bool toPython) const +void ObjectIdentifier::Component::toString(std::ostream& ss, bool toPython) const { switch (type) { - case Component::SIMPLE: - ss << name.getString(); - break; - case Component::MAP: - ss << "[" << name.toString(toPython) << "]"; - break; - case Component::ARRAY: - ss << "[" << begin << "]"; - break; - case Component::RANGE: - ss << '['; - if(begin!=INT_MAX) - ss << begin; - ss << ':'; - if(end!=INT_MAX) - ss << end; - if(step!=1) - ss << ':' << step; - ss << ']'; - break; - default: - assert(0); - } -} - -enum ResolveFlags { + case Component::SIMPLE: + ss << name.getString(); + break; + case Component::MAP: + ss << "[" << name.toString(toPython) << "]"; + break; + case Component::ARRAY: + ss << "[" << begin << "]"; + break; + case Component::RANGE: + ss << '['; + if (begin != INT_MAX) { + ss << begin; + } + ss << ':'; + if (end != INT_MAX) { + ss << end; + } + if (step != 1) { + ss << ':' << step; + } + ss << ']'; + break; + default: + assert(0); + } +} + +enum ResolveFlags +{ ResolveByIdentifier, ResolveByLabel, ResolveAmbiguous, @@ -833,13 +932,14 @@ enum ResolveFlags { * @return Pointer to document object if a unique pointer is found, 0 otherwise. */ -App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * doc, - const String & name, std::bitset<32> &flags) +App::DocumentObject* ObjectIdentifier::getDocumentObject(const App::Document* doc, + const String& name, + std::bitset<32>& flags) { - DocumentObject * objectById = nullptr; - DocumentObject * objectByLabel = nullptr; + DocumentObject* objectById = nullptr; + DocumentObject* objectByLabel = nullptr; - if(!name.isRealString()) { + if (!name.isRealString()) { // No object found with matching label, try using name directly objectById = doc->getObject(static_cast(name)); @@ -847,40 +947,43 @@ App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * flags.set(ResolveByIdentifier); return objectById; } - if(name.isForceIdentifier()) + if (name.isForceIdentifier()) { return nullptr; + } } std::vector docObjects = doc->getObjects(); for (auto docObject : docObjects) { if (strcmp(docObject->Label.getValue(), static_cast(name)) == 0) { // Found object with matching label - if (objectByLabel) { - FC_WARN("duplicate object label " << doc->getName() << '#' << static_cast(name)); + if (objectByLabel) { + FC_WARN("duplicate object label " << doc->getName() << '#' + << static_cast(name)); return nullptr; } objectByLabel = docObject; } } - if (!objectByLabel && !objectById) // Not found at all + if (!objectByLabel && !objectById) { // Not found at all return nullptr; - else if (!objectByLabel) { // Found by name + } + else if (!objectByLabel) { // Found by name flags.set(ResolveByIdentifier); return objectById; } - else if (!objectById) { // Found by label + else if (!objectById) { // Found by label flags.set(ResolveByLabel); return objectByLabel; } - else if (objectByLabel == objectById) { // Found by both name and label, same object + else if (objectByLabel == objectById) { // Found by both name and label, same object flags.set(ResolveByIdentifier); flags.set(ResolveByLabel); return objectByLabel; } else { flags.set(ResolveAmbiguous); - return nullptr; // Found by both name and label, two different objects + return nullptr; // Found by both name and label, two different objects } } @@ -891,16 +994,17 @@ App::DocumentObject * ObjectIdentifier::getDocumentObject(const App::Document * * */ -void ObjectIdentifier::resolve(ResolveResults &results) const +void ObjectIdentifier::resolve(ResolveResults& results) const { - if(!owner) + if (!owner) { return; + } bool docAmbiguous = false; /* Document name specified? */ if (!documentName.getString().empty()) { - results.resolvedDocument = getDocument(documentName,&docAmbiguous); + results.resolvedDocument = getDocument(documentName, &docAmbiguous); results.resolvedDocumentName = documentName; } else { @@ -915,14 +1019,16 @@ void ObjectIdentifier::resolve(ResolveResults &results) const // Assume document name and object name from owner if not found if (!results.resolvedDocument) { if (!documentName.getString().empty()) { - if(docAmbiguous) + if (docAmbiguous) { results.flags.set(ResolveAmbiguous); + } return; } results.resolvedDocument = owner->getDocument(); - if (!results.resolvedDocument) + if (!results.resolvedDocument) { return; + } } results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); @@ -930,24 +1036,27 @@ void ObjectIdentifier::resolve(ResolveResults &results) const /* Document object name specified? */ if (!documentObjectName.getString().empty()) { results.resolvedDocumentObjectName = documentObjectName; - results.resolvedDocumentObject = getDocumentObject( - results.resolvedDocument, documentObjectName, results.flags); - if (!results.resolvedDocumentObject) + results.resolvedDocumentObject = + getDocumentObject(results.resolvedDocument, documentObjectName, results.flags); + if (!results.resolvedDocumentObject) { return; + } - if (components.empty()) + if (components.empty()) { return; + } - results.propertyName = components[ 0 ].name.getString(); + results.propertyName = components[0].name.getString(); results.propertyIndex = 0; - results.getProperty( *this ); + results.getProperty(*this); } else { /* Document object name not specified, resolve from path */ /* One component? */ - if (components.size() == 1 || (components.size()>1 && !components[0].isSimple())) { - /* Yes -- then this must be a property, so we get the document object's name from the owner */ + if (components.size() == 1 || (components.size() > 1 && !components[0].isSimple())) { + /* Yes -- then this must be a property, so we get the document object's name from the + * owner */ results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); results.resolvedDocumentObject = owner; results.propertyName = components[0].name.getString(); @@ -956,36 +1065,39 @@ void ObjectIdentifier::resolve(ResolveResults &results) const } else if (components.size() >= 2) { /* No -- */ - if (!components[0].isSimple()) + if (!components[0].isSimple()) { return; + } - results.resolvedDocumentObject = getDocumentObject( - results.resolvedDocument, components[0].name, results.flags); + results.resolvedDocumentObject = + getDocumentObject(results.resolvedDocument, components[0].name, results.flags); /* Possible to resolve component to a document object? */ if (results.resolvedDocumentObject) { /* Yes */ - results.resolvedDocumentObjectName = String { - components[0].name.getString(), - false, - results.flags.test(ResolveByIdentifier)}; + results.resolvedDocumentObjectName = + String {components[0].name.getString(), + false, + results.flags.test(ResolveByIdentifier)}; results.propertyName = components[1].name.getString(); results.propertyIndex = 1; results.getProperty(*this); - if(!results.resolvedProperty) { + if (!results.resolvedProperty) { // If the second component is not a property name, try to // interpret the first component as the property name. - DocumentObject *sobj = nullptr; - results.resolvedProperty = resolveProperty( - owner, - components[0].name.toString().c_str(), - sobj, - results.propertyType); - if(results.resolvedProperty) { + DocumentObject* sobj = nullptr; + results.resolvedProperty = + resolveProperty(owner, + components[0].name.toString().c_str(), + sobj, + results.propertyType); + if (results.resolvedProperty) { results.propertyName = components[0].name.getString(); results.resolvedDocument = owner->getDocument(); - results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); - results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); + results.resolvedDocumentName = + String(results.resolvedDocument->getName(), false, true); + results.resolvedDocumentObjectName = + String(owner->getNameInDocument(), false, true); results.resolvedDocumentObject = owner; results.resolvedSubObject = sobj; results.propertyIndex = 0; @@ -995,16 +1107,20 @@ void ObjectIdentifier::resolve(ResolveResults &results) const else if (documentName.getString().empty()) { /* No, assume component is a property, and get document object's name from owner */ results.resolvedDocument = owner->getDocument(); - results.resolvedDocumentName = String(results.resolvedDocument->getName(), false, true); - results.resolvedDocumentObjectName = String(owner->getNameInDocument(), false, true); - results.resolvedDocumentObject = owner->getDocument()->getObject(owner->getNameInDocument()); + results.resolvedDocumentName = + String(results.resolvedDocument->getName(), false, true); + results.resolvedDocumentObjectName = + String(owner->getNameInDocument(), false, true); + results.resolvedDocumentObject = + owner->getDocument()->getObject(owner->getNameInDocument()); results.propertyIndex = 0; results.propertyName = components[results.propertyIndex].name.getString(); results.getProperty(*this); } } - else + else { return; + } } } @@ -1014,27 +1130,31 @@ void ObjectIdentifier::resolve(ResolveResults &results) const * @return Pointer to document, or 0 if it is not found or not uniquely defined by name. */ -Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const +Document* ObjectIdentifier::getDocument(String name, bool* ambiguous) const { - if (name.getString().empty()) + if (name.getString().empty()) { name = getDocumentName(); + } - App::Document * docById = nullptr; + App::Document* docById = nullptr; - if(!name.isRealString()) { + if (!name.isRealString()) { docById = App::GetApplication().getDocument(name.toString().c_str()); - if (name.isForceIdentifier()) + if (name.isForceIdentifier()) { return docById; + } } - App::Document * docByLabel = nullptr; + App::Document* docByLabel = nullptr; const std::vector docs = App::GetApplication().getDocuments(); for (auto doc : docs) { if (doc->Label.getValue() == name.getString()) { /* Multiple hits for same label? */ if (docByLabel) { - if(ambiguous) *ambiguous = true; + if (ambiguous) { + *ambiguous = true; + } return nullptr; } docByLabel = doc; @@ -1042,18 +1162,22 @@ Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const } /* Not found on id? */ - if (!docById) - return docByLabel; // Either not found at all, or on label + if (!docById) { + return docByLabel; // Either not found at all, or on label + } else { /* Not found on label? */ - if (!docByLabel) /* Then return doc by id */ + if (!docByLabel) { /* Then return doc by id */ return docById; + } /* docByLabel and docById could be equal; that is ok */ - if (docByLabel == docById) + if (docByLabel == docById) { return docById; - if (ambiguous) + } + if (ambiguous) { *ambiguous = true; + } return nullptr; } } @@ -1063,13 +1187,14 @@ Document * ObjectIdentifier::getDocument(String name, bool *ambiguous) const * @return Pointer to document object, or 0 if not found or uniquely defined. */ -DocumentObject *ObjectIdentifier::getDocumentObject() const +DocumentObject* ObjectIdentifier::getDocumentObject() const { - const App::Document * doc = getDocument(); + const App::Document* doc = getDocument(); std::bitset<32> dummy; - if (!doc) + if (!doc) { return nullptr; + } ResolveResults result(*this); @@ -1077,7 +1202,8 @@ DocumentObject *ObjectIdentifier::getDocumentObject() const } -enum PseudoPropertyType { +enum PseudoPropertyType +{ PseudoNone, PseudoShape, PseudoPlacement, @@ -1095,47 +1221,57 @@ enum PseudoPropertyType { PseudoCadquery, }; -void ObjectIdentifier::getDepLabels(std::vector &labels) const { - getDepLabels(ResolveResults(*this),labels); +void ObjectIdentifier::getDepLabels(std::vector& labels) const +{ + getDepLabels(ResolveResults(*this), labels); } -void ObjectIdentifier::getDepLabels( - const ResolveResults &result, std::vector &labels) const +void ObjectIdentifier::getDepLabels(const ResolveResults& result, + std::vector& labels) const { - if(!documentObjectName.getString().empty()) { - if(documentObjectName.isRealString()) + if (!documentObjectName.getString().empty()) { + if (documentObjectName.isRealString()) { labels.push_back(documentObjectName.getString()); - } else if(result.propertyIndex == 1) + } + } + else if (result.propertyIndex == 1) { labels.push_back(components[0].name.getString()); - if(!subObjectName.getString().empty()) - PropertyLinkBase::getLabelReferences(labels,subObjectName.getString().c_str()); + } + if (!subObjectName.getString().empty()) { + PropertyLinkBase::getLabelReferences(labels, subObjectName.getString().c_str()); + } } -ObjectIdentifier::Dependencies -ObjectIdentifier::getDep(bool needProps, std::vector *labels) const +ObjectIdentifier::Dependencies ObjectIdentifier::getDep(bool needProps, + std::vector* labels) const { Dependencies deps; - getDep(deps,needProps,labels); + getDep(deps, needProps, labels); return deps; } -void ObjectIdentifier::getDep(Dependencies &deps, bool needProps, std::vector *labels) const +void ObjectIdentifier::getDep(Dependencies& deps, + bool needProps, + std::vector* labels) const { ResolveResults result(*this); - if(labels) - getDepLabels(result,*labels); + if (labels) { + getDepLabels(result, *labels); + } - if(!result.resolvedDocumentObject) - return; + if (!result.resolvedDocumentObject) { + return; + } - if(!needProps) { + if (!needProps) { deps[result.resolvedDocumentObject]; return; } - if(!result.resolvedProperty) { - if(!result.propertyName.empty()) + if (!result.resolvedProperty) { + if (!result.propertyName.empty()) { deps[result.resolvedDocumentObject].insert(result.propertyName); + } return; } @@ -1146,7 +1282,7 @@ void ObjectIdentifier::getDep(Dependencies &deps, bool needProps, std::vector ObjectIdentifier::getStringList() const std::vector l; ResolveResults result(*this); - if(!result.resolvedProperty || result.resolvedDocumentObject != owner) { - if (documentNameSet) + if (!result.resolvedProperty || result.resolvedDocumentObject != owner) { + if (documentNameSet) { l.push_back(documentName.toString()); + } - if (documentObjectNameSet) + if (documentObjectNameSet) { l.push_back(documentObjectName.toString()); + } } - if(!subObjectName.getString().empty()) { + if (!subObjectName.getString().empty()) { l.back() += subObjectName.toString(); } std::vector::const_iterator i = components.begin(); @@ -1187,20 +1325,24 @@ std::vector ObjectIdentifier::getStringList() const * @return A new simplified object identifier. */ -ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier &other) const +ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier& other) const { ObjectIdentifier result(other.getOwner()); ResolveResults thisresult(*this); ResolveResults otherresult(other); - if (otherresult.resolvedDocument != thisresult.resolvedDocument) + if (otherresult.resolvedDocument != thisresult.resolvedDocument) { result.setDocumentName(std::move(thisresult.resolvedDocumentName), true); - if (otherresult.resolvedDocumentObject != thisresult.resolvedDocumentObject) - result.setDocumentObjectName( - std::move(thisresult.resolvedDocumentObjectName), true, String(subObjectName)); + } + if (otherresult.resolvedDocumentObject != thisresult.resolvedDocumentObject) { + result.setDocumentObjectName(std::move(thisresult.resolvedDocumentObjectName), + true, + String(subObjectName)); + } - for (std::size_t i = thisresult.propertyIndex; i < components.size(); ++i) + for (std::size_t i = thisresult.propertyIndex; i < components.size(); ++i) { result << components[i]; + } return result; } @@ -1215,15 +1357,17 @@ ObjectIdentifier ObjectIdentifier::relativeTo(const ObjectIdentifier &other) con * @return A new object identifier. */ -ObjectIdentifier ObjectIdentifier::parse(const DocumentObject *docObj, const std::string &str) +ObjectIdentifier ObjectIdentifier::parse(const DocumentObject* docObj, const std::string& str) { std::unique_ptr expr(ExpressionParser::parse(docObj, str.c_str())); - VariableExpression * v = freecad_dynamic_cast(expr.get()); + VariableExpression* v = freecad_dynamic_cast(expr.get()); - if (v) + if (v) { return v->getPath(); - else - FC_THROWM(Base::RuntimeError,"Invalid property specification."); + } + else { + FC_THROWM(Base::RuntimeError, "Invalid property specification."); + } } std::string ObjectIdentifier::resolveErrorString() const @@ -1239,14 +1383,14 @@ std::string ObjectIdentifier::resolveErrorString() const * @return Reference to itself. */ -ObjectIdentifier &ObjectIdentifier::operator <<(const ObjectIdentifier::Component &value) +ObjectIdentifier& ObjectIdentifier::operator<<(const ObjectIdentifier::Component& value) { components.push_back(value); _cache.clear(); return *this; } -ObjectIdentifier &ObjectIdentifier::operator <<(ObjectIdentifier::Component &&value) +ObjectIdentifier& ObjectIdentifier::operator<<(ObjectIdentifier::Component&& value) { components.push_back(std::move(value)); _cache.clear(); @@ -1259,59 +1403,61 @@ ObjectIdentifier &ObjectIdentifier::operator <<(ObjectIdentifier::Component &&va * @return Point to property if it is uniquely defined, or 0 otherwise. */ -Property *ObjectIdentifier::getProperty(int *ptype) const +Property* ObjectIdentifier::getProperty(int* ptype) const { ResolveResults result(*this); - if(ptype) + if (ptype) { *ptype = result.propertyType; + } return result.resolvedProperty; } -Property *ObjectIdentifier::resolveProperty(const App::DocumentObject *obj, - const char *propertyName, App::DocumentObject *&sobj, int &ptype) const +Property* ObjectIdentifier::resolveProperty(const App::DocumentObject* obj, + const char* propertyName, + App::DocumentObject*& sobj, + int& ptype) const { - if(obj && !subObjectName.getString().empty()) { + if (obj && !subObjectName.getString().empty()) { sobj = obj->getSubObject(subObjectName.toString().c_str()); obj = sobj; } - if(!obj) + if (!obj) { return nullptr; + } - static std::unordered_map _props = { - {"_shape",PseudoShape}, - {"_pla",PseudoPlacement}, - {"_matrix",PseudoMatrix}, - {"__pla",PseudoLinkPlacement}, - {"__matrix",PseudoLinkMatrix}, - {"_self",PseudoSelf}, - {"_app",PseudoApp}, - {"_part",PseudoPart}, - {"_re",PseudoRegex}, + static std::unordered_map _props = { + {"_shape", PseudoShape}, + {"_pla", PseudoPlacement}, + {"_matrix", PseudoMatrix}, + {"__pla", PseudoLinkPlacement}, + {"__matrix", PseudoLinkMatrix}, + {"_self", PseudoSelf}, + {"_app", PseudoApp}, + {"_part", PseudoPart}, + {"_re", PseudoRegex}, {"_py", PseudoBuiltins}, {"_math", PseudoMath}, {"_coll", PseudoCollections}, - {"_gui",PseudoGui}, - {"_cq",PseudoCadquery}, + {"_gui", PseudoGui}, + {"_cq", PseudoCadquery}, }; auto it = _props.find(propertyName); - if(it == _props.end()) + if (it == _props.end()) { ptype = PseudoNone; + } else { ptype = it->second; - if(ptype != PseudoShape && - !subObjectName.getString().empty() && - !boost::ends_with(subObjectName.getString(),".")) - { + if (ptype != PseudoShape && !subObjectName.getString().empty() + && !boost::ends_with(subObjectName.getString(), ".")) { return nullptr; } - return &const_cast(obj)->Label; //fake the property + return &const_cast(obj)->Label; // fake the property } return obj->getPropertyByName(propertyName); } - /** * @brief Create a canonical representation of an object identifier. * @@ -1325,18 +1471,19 @@ ObjectIdentifier ObjectIdentifier::canonicalPath() const { ObjectIdentifier res(*this); ResolveResults result(res); - if(result.resolvedDocumentObject && result.resolvedDocumentObject!=owner) { + if (result.resolvedDocumentObject && result.resolvedDocumentObject != owner) { res.owner = result.resolvedDocumentObject; res._cache.clear(); } res.resolveAmbiguity(result); - if(!result.resolvedProperty || result.propertyType!=PseudoNone) + if (!result.resolvedProperty || result.propertyType != PseudoNone) { return res; + } return result.resolvedProperty->canonicalPath(res); } -static const std::map *_DocumentMap; -ObjectIdentifier::DocumentMapper::DocumentMapper(const std::map &map) +static const std::map* _DocumentMap; +ObjectIdentifier::DocumentMapper::DocumentMapper(const std::map& map) { assert(!_DocumentMap); _DocumentMap = ↦ @@ -1356,23 +1503,25 @@ ObjectIdentifier::DocumentMapper::~DocumentMapper() * @param force Force name to be set */ -void ObjectIdentifier::setDocumentName(ObjectIdentifier::String &&name, bool force) +void ObjectIdentifier::setDocumentName(ObjectIdentifier::String&& name, bool force) { - if(name.getString().empty()) + if (name.getString().empty()) { force = false; + } documentNameSet = force; _cache.clear(); - if(!name.getString().empty() && _DocumentMap) { - if(name.isRealString()) { + if (!name.getString().empty() && _DocumentMap) { + if (name.isRealString()) { auto iter = _DocumentMap->find(name.toString()); - if(iter!=_DocumentMap->end()) { - documentName = String(iter->second,true); + if (iter != _DocumentMap->end()) { + documentName = String(iter->second, true); return; } - }else{ + } + else { auto iter = _DocumentMap->find(name.getString()); - if(iter!=_DocumentMap->end()) { - documentName = String(iter->second,false,true); + if (iter != _DocumentMap->end()) { + documentName = String(iter->second, false, true); return; } } @@ -1403,12 +1552,14 @@ ObjectIdentifier::String ObjectIdentifier::getDocumentName() const * @param force Force name to be set. */ -void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String &&name, bool force, - ObjectIdentifier::String &&subname, bool checkImport) +void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String&& name, + bool force, + ObjectIdentifier::String&& subname, + bool checkImport) { - if(checkImport) { + if (checkImport) { name.checkImport(owner); - subname.checkImport(owner,nullptr,&name); + subname.checkImport(owner, nullptr, &name); } documentObjectName = std::move(name); @@ -1418,35 +1569,46 @@ void ObjectIdentifier::setDocumentObjectName(ObjectIdentifier::String &&name, bo _cache.clear(); } -void ObjectIdentifier::setDocumentObjectName(const App::DocumentObject *obj, bool force, - ObjectIdentifier::String &&subname, bool checkImport) +void ObjectIdentifier::setDocumentObjectName(const App::DocumentObject* obj, + bool force, + ObjectIdentifier::String&& subname, + bool checkImport) { - if(!owner || !obj || !obj->isAttachedToDocument() || !obj->getDocument()) - FC_THROWM(Base::RuntimeError,"invalid object"); + if (!owner || !obj || !obj->isAttachedToDocument() || !obj->getDocument()) { + FC_THROWM(Base::RuntimeError, "invalid object"); + } - if(checkImport) - subname.checkImport(owner,obj); + if (checkImport) { + subname.checkImport(owner, obj); + } - if(obj == owner) + if (obj == owner) { force = false; - else + } + else { localProperty = false; - if(obj->getDocument() == owner->getDocument()) + } + if (obj->getDocument() == owner->getDocument()) { setDocumentName(String()); - else if(!documentNameSet) { - if(obj->getDocument() == owner->getDocument()) + } + else if (!documentNameSet) { + if (obj->getDocument() == owner->getDocument()) { setDocumentName(String()); + } else { documentNameSet = true; - documentName = String(obj->getDocument()->getName(),false,true); + documentName = String(obj->getDocument()->getName(), false, true); } - }else if(documentName.isRealString()) - documentName = String(obj->getDocument()->Label.getStrValue(),true); - else - documentName = String(obj->getDocument()->getName(),false,true); + } + else if (documentName.isRealString()) { + documentName = String(obj->getDocument()->Label.getStrValue(), true); + } + else { + documentName = String(obj->getDocument()->getName(), false, true); + } documentObjectNameSet = force; - documentObjectName = String(obj->getNameInDocument(),false,true); + documentObjectName = String(obj->getNameInDocument(), false, true); subObjectName = std::move(subname); _cache.clear(); @@ -1465,7 +1627,8 @@ ObjectIdentifier::String ObjectIdentifier::getDocumentObjectName() const return result.resolvedDocumentObjectName; } -bool ObjectIdentifier::hasDocumentObjectName(bool forced) const { +bool ObjectIdentifier::hasDocumentObjectName(bool forced) const +{ return !documentObjectName.getString().empty() && (!forced || documentObjectNameSet); } @@ -1476,40 +1639,43 @@ bool ObjectIdentifier::hasDocumentObjectName(bool forced) const { std::string ObjectIdentifier::String::toString(bool toPython) const { - if (isRealString()) - return quote(str,toPython); - else + if (isRealString()) { + return quote(str, toPython); + } + else { return str; + } } -void ObjectIdentifier::String::checkImport(const App::DocumentObject *owner, - const App::DocumentObject *obj, String *objName) +void ObjectIdentifier::String::checkImport(const App::DocumentObject* owner, + const App::DocumentObject* obj, + String* objName) { - if(owner && owner->getDocument() && !str.empty() && - ExpressionParser::ExpressionImporter::reader()) { + if (owner && owner->getDocument() && !str.empty() + && ExpressionParser::ExpressionImporter::reader()) { auto reader = ExpressionParser::ExpressionImporter::reader(); if (obj || objName) { bool restoreLabel = false; - str = PropertyLinkBase::importSubName(*reader,str.c_str(),restoreLabel); + str = PropertyLinkBase::importSubName(*reader, str.c_str(), restoreLabel); if (restoreLabel) { if (!obj) { std::bitset<32> flags; - obj = getDocumentObject(owner->getDocument(),*objName,flags); + obj = getDocumentObject(owner->getDocument(), *objName, flags); if (!obj) { FC_ERR("Cannot find object " << objName->toString()); } } if (obj) { - PropertyLinkBase::restoreLabelReference(obj,str); + PropertyLinkBase::restoreLabelReference(obj, str); } } } - else if (str.back()!='@') { + else if (str.back() != '@') { str = reader->getName(str.c_str()); } else { - str.resize(str.size()-1); + str.resize(str.size() - 1); auto mapped = reader->getName(str.c_str()); auto objForMapped = owner->getDocument()->getObject(mapped); if (!objForMapped) { @@ -1524,14 +1690,12 @@ void ObjectIdentifier::String::checkImport(const App::DocumentObject *owner, } } -Py::Object ObjectIdentifier::access(const ResolveResults &result, - Py::Object *value, Dependencies *deps) const +Py::Object +ObjectIdentifier::access(const ResolveResults& result, Py::Object* value, Dependencies* deps) const { - if(!result.resolvedDocumentObject || !result.resolvedProperty || - (!subObjectName.getString().empty() && !result.resolvedSubObject)) - { - FC_THROWM(Base::RuntimeError, result.resolveErrorString() - << " in '" << toString() << "'"); + if (!result.resolvedDocumentObject || !result.resolvedProperty + || (!subObjectName.getString().empty() && !result.resolvedSubObject)) { + FC_THROWM(Base::RuntimeError, result.resolveErrorString() << " in '" << toString() << "'"); } Py::Object pyobj; @@ -1540,153 +1704,166 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, // NOTE! We do not keep reference of the imported module, assuming once // imported they'll live (because of sys.modules) till the application // dies. -#define GET_MODULE(_name) do {\ - static PyObject *pymod;\ - if(!pymod) {\ - pymod = PyImport_ImportModule(#_name);\ - if(!pymod)\ - Base::PyException::ThrowException();\ - else\ - Py_DECREF(pymod);\ - }\ - pyobj = Py::Object(pymod);\ - }while(0) - - size_t idx = result.propertyIndex+1; - switch(ptype) { - case PseudoApp: - GET_MODULE(FreeCAD); - break; - case PseudoGui: - GET_MODULE(FreeCADGui); - break; - case PseudoPart: - GET_MODULE(Part); - break; - case PseudoCadquery: - GET_MODULE(freecad.fc_cadquery); - break; - case PseudoRegex: - GET_MODULE(re); - break; - case PseudoBuiltins: - GET_MODULE(builtins); - break; - case PseudoMath: - GET_MODULE(math); - break; - case PseudoCollections: - GET_MODULE(collections); - break; - case PseudoShape: { - GET_MODULE(Part); - Py::Callable func(pyobj.getAttr("getShape")); - Py::Tuple tuple(1); - tuple.setItem(0,Py::Object(result.resolvedDocumentObject->getPyObject(),true)); - if(result.subObjectName.getString().empty()) - pyobj = func.apply(tuple); - else{ - Py::Dict dict; - dict.setItem("subname",Py::String(result.subObjectName.getString())); - dict.setItem("needSubElement",Py::True()); - pyobj = func.apply(tuple,dict); - } - break; - } default: { - Base::Matrix4D mat; - auto obj = result.resolvedDocumentObject; - switch(ptype) { - case PseudoPlacement: - case PseudoMatrix: - case PseudoLinkPlacement: - case PseudoLinkMatrix: - obj->getSubObject(result.subObjectName.getString().c_str(),nullptr,&mat); +#define GET_MODULE(_name) \ + do { \ + static PyObject* pymod; \ + if (!pymod) { \ + pymod = PyImport_ImportModule(#_name); \ + if (!pymod) \ + Base::PyException::ThrowException(); \ + else \ + Py_DECREF(pymod); \ + } \ + pyobj = Py::Object(pymod); \ + } while (0) + + size_t idx = result.propertyIndex + 1; + switch (ptype) { + case PseudoApp: + GET_MODULE(FreeCAD); break; - default: + case PseudoGui: + GET_MODULE(FreeCADGui); break; - } - if(result.resolvedSubObject) - obj = result.resolvedSubObject; - switch(ptype) { - case PseudoPlacement: - pyobj = Py::Placement(Base::Placement(mat)); + case PseudoPart: + GET_MODULE(Part); + break; + case PseudoCadquery: + GET_MODULE(freecad.fc_cadquery); + break; + case PseudoRegex: + GET_MODULE(re); + break; + case PseudoBuiltins: + GET_MODULE(builtins); break; - case PseudoMatrix: - pyobj = Py::Matrix(mat); + case PseudoMath: + GET_MODULE(math); break; - case PseudoLinkPlacement: - case PseudoLinkMatrix: { - auto linked = obj->getLinkedObject(true,&mat,false); - if(!linked || linked==obj) { - auto ext = obj->getExtensionByType(true); - if(ext) - ext->getTrueLinkedObject(true,&mat); + case PseudoCollections: + GET_MODULE(collections); + break; + case PseudoShape: { + GET_MODULE(Part); + Py::Callable func(pyobj.getAttr("getShape")); + Py::Tuple tuple(1); + tuple.setItem(0, Py::Object(result.resolvedDocumentObject->getPyObject(), true)); + if (result.subObjectName.getString().empty()) { + pyobj = func.apply(tuple); + } + else { + Py::Dict dict; + dict.setItem("subname", Py::String(result.subObjectName.getString())); + dict.setItem("needSubElement", Py::True()); + pyobj = func.apply(tuple, dict); } - if(ptype == PseudoLinkPlacement) - pyobj = Py::Placement(Base::Placement(mat)); - else - pyobj = Py::Matrix(mat); break; } - case PseudoSelf: - pyobj = Py::Object(obj->getPyObject(),true); - break; default: { - // NOTE! We cannot directly call Property::getPyObject(), but - // instead, must obtain the property's python object through - // DocumentObjectPy::getAttr(). Because, PyObjectBase has internal - // attribute tracking only if we obtain attribute through - // getAttr(). Without attribute tracking, we can't do things like - // - // obj.Placement.Base.x = 10. - // - // What happens is that the when Python interpreter calls - // - // Base.setAttr('x', 10), - // - // PyObjectBase will lookup Base's parent, i.e. Placement, and call - // - // Placement.setAttr('Base', Base), - // - // and in turn calls - // - // obj.setAttr('Placement',Placement) - // - // The tracking logic is implemented in PyObjectBase::__getattro/__setattro - - auto container = result.resolvedProperty->getContainer(); - if(container - && container!=result.resolvedDocumentObject - && container!=result.resolvedSubObject) - { - if(!container->isDerivedFrom(DocumentObject::getClassTypeId())) - FC_WARN("Invalid property container"); - else - obj = static_cast(container); + Base::Matrix4D mat; + auto obj = result.resolvedDocumentObject; + switch (ptype) { + case PseudoPlacement: + case PseudoMatrix: + case PseudoLinkPlacement: + case PseudoLinkMatrix: + obj->getSubObject(result.subObjectName.getString().c_str(), nullptr, &mat); + break; + default: + break; } - pyobj = Py::Object(obj->getPyObject(),true); - idx = result.propertyIndex; - break; - }}} + if (result.resolvedSubObject) { + obj = result.resolvedSubObject; + } + switch (ptype) { + case PseudoPlacement: + pyobj = Py::Placement(Base::Placement(mat)); + break; + case PseudoMatrix: + pyobj = Py::Matrix(mat); + break; + case PseudoLinkPlacement: + case PseudoLinkMatrix: { + auto linked = obj->getLinkedObject(true, &mat, false); + if (!linked || linked == obj) { + auto ext = obj->getExtensionByType(true); + if (ext) { + ext->getTrueLinkedObject(true, &mat); + } + } + if (ptype == PseudoLinkPlacement) { + pyobj = Py::Placement(Base::Placement(mat)); + } + else { + pyobj = Py::Matrix(mat); + } + break; + } + case PseudoSelf: + pyobj = Py::Object(obj->getPyObject(), true); + break; + default: { + // NOTE! We cannot directly call Property::getPyObject(), but + // instead, must obtain the property's python object through + // DocumentObjectPy::getAttr(). Because, PyObjectBase has internal + // attribute tracking only if we obtain attribute through + // getAttr(). Without attribute tracking, we can't do things like + // + // obj.Placement.Base.x = 10. + // + // What happens is that the when Python interpreter calls + // + // Base.setAttr('x', 10), + // + // PyObjectBase will lookup Base's parent, i.e. Placement, and call + // + // Placement.setAttr('Base', Base), + // + // and in turn calls + // + // obj.setAttr('Placement',Placement) + // + // The tracking logic is implemented in PyObjectBase::__getattro/__setattro + + auto container = result.resolvedProperty->getContainer(); + if (container && container != result.resolvedDocumentObject + && container != result.resolvedSubObject) { + if (!container->isDerivedFrom(DocumentObject::getClassTypeId())) { + FC_WARN("Invalid property container"); + } + else { + obj = static_cast(container); + } + } + pyobj = Py::Object(obj->getPyObject(), true); + idx = result.propertyIndex; + break; + } + } + } } - auto setPropDep = [deps](DocumentObject *obj, Property *prop, const char *propName) { - if(!deps || !obj) + auto setPropDep = [deps](DocumentObject* obj, Property* prop, const char* propName) { + if (!deps || !obj) { return; - if(prop && prop->getContainer()!=obj) { - auto linkTouched = Base::freecad_dynamic_cast( - obj->getPropertyByName("_LinkTouched")); - if(linkTouched) + } + if (prop && prop->getContainer() != obj) { + auto linkTouched = + Base::freecad_dynamic_cast(obj->getPropertyByName("_LinkTouched")); + if (linkTouched) { propName = linkTouched->getName(); + } else { auto propOwner = Base::freecad_dynamic_cast(prop->getContainer()); - if(propOwner) + if (propOwner) { obj = propOwner; - else + } + else { propName = nullptr; + } } } - auto &propset = (*deps)[obj]; + auto& propset = (*deps)[obj]; // inserting a blank name in the propset indicates the dependency is // on all properties of the corresponding object. if (propset.size() != 1 || !propset.begin()->empty()) { @@ -1701,37 +1878,43 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, return; }; - App::DocumentObject *lastObj = result.resolvedDocumentObject; - if(result.resolvedSubObject) { - setPropDep(lastObj,nullptr,nullptr); + App::DocumentObject* lastObj = result.resolvedDocumentObject; + if (result.resolvedSubObject) { + setPropDep(lastObj, nullptr, nullptr); lastObj = result.resolvedSubObject; } - if(ptype == PseudoNone) + if (ptype == PseudoNone) { setPropDep(lastObj, result.resolvedProperty, result.resolvedProperty->getName()); - else - setPropDep(lastObj,nullptr,nullptr); + } + else { + setPropDep(lastObj, nullptr, nullptr); + } lastObj = nullptr; - if(components.empty()) + if (components.empty()) { return pyobj; + } size_t count = components.size(); - if(value) --count; - assert(idx<=count); + if (value) { + --count; + } + assert(idx <= count); - for(;idx(*pyobj)->getDocumentObjectPtr(); - else if(lastObj) { - const char *attr = components[idx].getName().c_str(); + } + else if (lastObj) { + const char* attr = components[idx].getName().c_str(); auto prop = lastObj->getPropertyByName(attr); - setPropDep(lastObj,prop,attr); + setPropDep(lastObj, prop, attr); lastObj = nullptr; } pyobj = components[idx].get(pyobj); } - if(value) { - components[idx].set(pyobj,*value); + if (value) { + components[idx].set(pyobj, *value); return Py::Object(); } return pyobj; @@ -1750,57 +1933,57 @@ Py::Object ObjectIdentifier::access(const ResolveResults &result, * @return The value of the property or field. */ -App::any ObjectIdentifier::getValue(bool pathValue, bool *isPseudoProperty) const +App::any ObjectIdentifier::getValue(bool pathValue, bool* isPseudoProperty) const { ResolveResults rs(*this); - if(isPseudoProperty) { - *isPseudoProperty = rs.propertyType!=PseudoNone; - if(rs.propertyType == PseudoSelf - && isLocalProperty() - && rs.propertyIndex+1 < (int)components.size() - && owner->getPropertyByName(components[rs.propertyIndex+1].getName().c_str())) - { + if (isPseudoProperty) { + *isPseudoProperty = rs.propertyType != PseudoNone; + if (rs.propertyType == PseudoSelf && isLocalProperty() + && rs.propertyIndex + 1 < (int)components.size() + && owner->getPropertyByName(components[rs.propertyIndex + 1].getName().c_str())) { *isPseudoProperty = false; } } - if(rs.resolvedProperty && rs.propertyType==PseudoNone && pathValue) + if (rs.resolvedProperty && rs.propertyType == PseudoNone && pathValue) { return rs.resolvedProperty->getPathValue(*this); + } Base::PyGILStateLocker lock; try { return pyObjectToAny(access(rs)); - }catch(Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } return {}; } -Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool *isPseudoProperty) const +Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool* isPseudoProperty) const { ResolveResults rs(*this); - if(isPseudoProperty) { - *isPseudoProperty = rs.propertyType!=PseudoNone; - if(rs.propertyType == PseudoSelf - && isLocalProperty() - && rs.propertyIndex+1 < (int)components.size() - && owner->getPropertyByName(components[rs.propertyIndex+1].getName().c_str())) - { + if (isPseudoProperty) { + *isPseudoProperty = rs.propertyType != PseudoNone; + if (rs.propertyType == PseudoSelf && isLocalProperty() + && rs.propertyIndex + 1 < (int)components.size() + && owner->getPropertyByName(components[rs.propertyIndex + 1].getName().c_str())) { *isPseudoProperty = false; } } - if(rs.resolvedProperty && rs.propertyType==PseudoNone && pathValue) { + if (rs.resolvedProperty && rs.propertyType == PseudoNone && pathValue) { Py::Object res; - if(rs.resolvedProperty->getPyPathValue(*this,res)) + if (rs.resolvedProperty->getPyPathValue(*this, res)) { return res; + } } try { return access(rs); - }catch(Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } return Py::Object(); @@ -1816,79 +1999,95 @@ Py::Object ObjectIdentifier::getPyValue(bool pathValue, bool *isPseudoProperty) * @param value Value to set */ -void ObjectIdentifier::setValue(const App::any &value) const +void ObjectIdentifier::setValue(const App::any& value) const { std::stringstream ss; ResolveResults rs(*this); - if(rs.propertyType) - FC_THROWM(Base::RuntimeError,"Cannot set pseudo property"); + if (rs.propertyType) { + FC_THROWM(Base::RuntimeError, "Cannot set pseudo property"); + } Base::PyGILStateLocker lock; try { Py::Object pyvalue = pyObjectFromAny(value); - access(rs,&pyvalue); - }catch(Py::Exception &) { + access(rs, &pyvalue); + } + catch (Py::Exception&) { Base::PyException::ThrowException(); } } -const std::string &ObjectIdentifier::getSubObjectName(bool newStyle) const { - if(newStyle && !shadowSub.newName.empty()) +const std::string& ObjectIdentifier::getSubObjectName(bool newStyle) const +{ + if (newStyle && !shadowSub.newName.empty()) { return shadowSub.newName; - if(!shadowSub.oldName.empty()) + } + if (!shadowSub.oldName.empty()) { return shadowSub.oldName; + } return subObjectName.getString(); } -const std::string &ObjectIdentifier::getSubObjectName() const { +const std::string& ObjectIdentifier::getSubObjectName() const +{ return subObjectName.getString(); } -void ObjectIdentifier::importSubNames(const ObjectIdentifier::SubNameMap &subNameMap) +void ObjectIdentifier::importSubNames(const ObjectIdentifier::SubNameMap& subNameMap) { - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return; + } ResolveResults result(*this); - auto it = subNameMap.find(std::make_pair(result.resolvedDocumentObject,std::string())); - if(it!=subNameMap.end()) { + auto it = subNameMap.find(std::make_pair(result.resolvedDocumentObject, std::string())); + if (it != subNameMap.end()) { auto obj = owner->getDocument()->getObject(it->second.c_str()); - if(!obj) { + if (!obj) { FC_ERR("Failed to find import object " << it->second << " from " - << result.resolvedDocumentObject->getFullName()); + << result.resolvedDocumentObject->getFullName()); return; } documentNameSet = false; documentName.str.clear(); - if(documentObjectName.isRealString()) + if (documentObjectName.isRealString()) { documentObjectName.str = obj->Label.getValue(); - else + } + else { documentObjectName.str = obj->getNameInDocument(); + } _cache.clear(); } - if(subObjectName.getString().empty()) + if (subObjectName.getString().empty()) { return; - it = subNameMap.find(std::make_pair( - result.resolvedDocumentObject,subObjectName.str)); - if(it==subNameMap.end()) + } + it = subNameMap.find(std::make_pair(result.resolvedDocumentObject, subObjectName.str)); + if (it == subNameMap.end()) { return; - subObjectName = String(it->second,true); + } + subObjectName = String(it->second, true); _cache.clear(); shadowSub.newName.clear(); shadowSub.oldName.clear(); } -bool ObjectIdentifier::updateElementReference(ExpressionVisitor &v, - App::DocumentObject *feature, bool reverse) +bool ObjectIdentifier::updateElementReference(ExpressionVisitor& v, + App::DocumentObject* feature, + bool reverse) { assert(v.getPropertyLink()); - if(subObjectName.getString().empty()) + if (subObjectName.getString().empty()) { return false; + } ResolveResults result(*this); - if(!result.resolvedSubObject) + if (!result.resolvedSubObject) { return false; - if(v.getPropertyLink()->_updateElementReference( - feature,result.resolvedDocumentObject,subObjectName.str,shadowSub,reverse)) { + } + if (v.getPropertyLink()->_updateElementReference(feature, + result.resolvedDocumentObject, + subObjectName.str, + shadowSub, + reverse)) { _cache.clear(); v.aboutToChange(); return true; @@ -1896,17 +2095,20 @@ bool ObjectIdentifier::updateElementReference(ExpressionVisitor &v, return false; } -bool ObjectIdentifier::adjustLinks(ExpressionVisitor &v, const std::set &inList) { +bool ObjectIdentifier::adjustLinks(ExpressionVisitor& v, + const std::set& inList) +{ ResolveResults result(*this); - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return false; - if(result.resolvedSubObject) { + } + if (result.resolvedSubObject) { PropertyLinkSub prop; prop.setValue(result.resolvedDocumentObject, {subObjectName.getString()}); - if(prop.adjustLink(inList)) { + if (prop.adjustLink(inList)) { v.aboutToChange(); - documentObjectName = String(prop.getValue()->getNameInDocument(),false,true); - subObjectName = String(prop.getSubValues().front(),true); + documentObjectName = String(prop.getValue()->getNameInDocument(), false, true); + subObjectName = String(prop.getSubValues().front(), true); _cache.clear(); return true; } @@ -1914,24 +2116,29 @@ bool ObjectIdentifier::adjustLinks(ExpressionVisitor &v, const std::setisTouched(); - else + } + else { return result.resolvedDocumentObject->isTouched(); + } } - }catch(...) {} + } + catch (...) { + } return false; } -void ObjectIdentifier::resolveAmbiguity() { - if(!owner || !owner->isAttachedToDocument() || isLocalProperty() || - (documentObjectNameSet && !documentObjectName.getString().empty() && - (documentObjectName.isRealString() || documentObjectName.isForceIdentifier()))) - { +void ObjectIdentifier::resolveAmbiguity() +{ + if (!owner || !owner->isAttachedToDocument() || isLocalProperty() + || (documentObjectNameSet && !documentObjectName.getString().empty() + && (documentObjectName.isRealString() || documentObjectName.isForceIdentifier()))) { return; } @@ -1939,33 +2146,43 @@ void ObjectIdentifier::resolveAmbiguity() { resolveAmbiguity(result); } -void ObjectIdentifier::resolveAmbiguity(ResolveResults &result) { +void ObjectIdentifier::resolveAmbiguity(ResolveResults& result) +{ - if(!result.resolvedDocumentObject) + if (!result.resolvedDocumentObject) { return; + } - if(result.propertyIndex==1) + if (result.propertyIndex == 1) { components.erase(components.begin()); + } String subname = subObjectName; - if(result.resolvedDocumentObject == owner) { - setDocumentObjectName(owner,false,std::move(subname)); - }else if(result.flags.test(ResolveByIdentifier)) - setDocumentObjectName(result.resolvedDocumentObject,true,std::move(subname)); - else + if (result.resolvedDocumentObject == owner) { + setDocumentObjectName(owner, false, std::move(subname)); + } + else if (result.flags.test(ResolveByIdentifier)) { + setDocumentObjectName(result.resolvedDocumentObject, true, std::move(subname)); + } + else { setDocumentObjectName( - String(result.resolvedDocumentObject->Label.getStrValue(),true,false),true,std::move(subname)); + String(result.resolvedDocumentObject->Label.getStrValue(), true, false), + true, + std::move(subname)); + } - if(result.resolvedDocumentObject->getDocument() == owner->getDocument()) + if (result.resolvedDocumentObject->getDocument() == owner->getDocument()) { setDocumentName(String()); + } } /** Construct and initialize a ResolveResults object, given an ObjectIdentifier instance. * - * The constructor will invoke the ObjectIdentifier's resolve() method to initialize the object's data. + * The constructor will invoke the ObjectIdentifier's resolve() method to initialize the object's + * data. */ -ObjectIdentifier::ResolveResults::ResolveResults(const ObjectIdentifier &oi) +ObjectIdentifier::ResolveResults::ResolveResults(const ObjectIdentifier& oi) : propertyType(PseudoNone) { oi.resolve(*this); @@ -1975,36 +2192,43 @@ std::string ObjectIdentifier::ResolveResults::resolveErrorString() const { std::ostringstream ss; if (!resolvedDocument) { - if(flags.test(ResolveAmbiguous)) - ss << "Ambiguous document name/label '" - << resolvedDocumentName.getString() << "'"; - else + if (flags.test(ResolveAmbiguous)) { + ss << "Ambiguous document name/label '" << resolvedDocumentName.getString() << "'"; + } + else { ss << "Document '" << resolvedDocumentName.toString() << "' not found"; - } else if (!resolvedDocumentObject) { - if(flags.test(ResolveAmbiguous)) - ss << "Ambiguous document object name '" - << resolvedDocumentObjectName.getString() << "'"; - else - ss << "Document object '" << resolvedDocumentObjectName.toString() - << "' not found"; - } else if (!subObjectName.getString().empty() && !resolvedSubObject) { - ss << "Sub-object '" << resolvedDocumentObjectName.getString() - << '.' << subObjectName.toString() << "' not found"; - } else if (!resolvedProperty) { - if(propertyType != PseudoShape && - !subObjectName.getString().empty() && - !boost::ends_with(subObjectName.getString(),".")) - { + } + } + else if (!resolvedDocumentObject) { + if (flags.test(ResolveAmbiguous)) { + ss << "Ambiguous document object name '" << resolvedDocumentObjectName.getString() + << "'"; + } + else { + ss << "Document object '" << resolvedDocumentObjectName.toString() << "' not found"; + } + } + else if (!subObjectName.getString().empty() && !resolvedSubObject) { + ss << "Sub-object '" << resolvedDocumentObjectName.getString() << '.' + << subObjectName.toString() << "' not found"; + } + else if (!resolvedProperty) { + if (propertyType != PseudoShape && !subObjectName.getString().empty() + && !boost::ends_with(subObjectName.getString(), ".")) { ss << "Non geometry subname reference must end with '.'"; - }else + } + else { ss << "Property '" << propertyName << "' not found"; + } } return ss.str(); } -void ObjectIdentifier::ResolveResults::getProperty(const ObjectIdentifier &oi) { - resolvedProperty = oi.resolveProperty( - resolvedDocumentObject,propertyName.c_str(),resolvedSubObject,propertyType); +void ObjectIdentifier::ResolveResults::getProperty(const ObjectIdentifier& oi) +{ + resolvedProperty = oi.resolveProperty(resolvedDocumentObject, + propertyName.c_str(), + resolvedSubObject, + propertyType); } - diff --git a/src/App/ObjectIdentifier.h b/src/App/ObjectIdentifier.h index 4cbe0b7cec51..c62f69c47c47 100644 --- a/src/App/ObjectIdentifier.h +++ b/src/App/ObjectIdentifier.h @@ -34,7 +34,8 @@ #include "ElementNamingUtils.h" -namespace Py { +namespace Py +{ class Object; } namespace App @@ -43,12 +44,14 @@ namespace App using any = boost::any; template -inline const T &any_cast(const boost::any &value) { +inline const T& any_cast(const boost::any& value) +{ return boost::any_cast(value); } template -inline T &any_cast(boost::any &value) { +inline T& any_cast(boost::any& value) +{ return boost::any_cast(value); } @@ -58,48 +61,49 @@ class PropertyContainer; class DocumentObject; class ExpressionVisitor; -AppExport std::string quote(const std::string &input, bool toPython=false); +AppExport std::string quote(const std::string& input, bool toPython = false); // Unfortunately VS2013 does not support default move constructor, so we have // to implement them manually -#define FC_DEFAULT_CTORS(_t) \ - _t(const _t &) = default;\ - _t &operator=(const _t &) = default;\ - _t(_t &&other) { *this = std::move(other); }\ - _t &operator=(_t &&other) - -class AppExport ObjectIdentifier { +#define FC_DEFAULT_CTORS(_t) \ + _t(const _t&) = default; \ + _t& operator=(const _t&) = default; \ + _t(_t&& other) \ + { \ + *this = std::move(other); \ + } \ + _t& operator=(_t&& other) + +class AppExport ObjectIdentifier +{ public: - - class AppExport DocumentMapper { + class AppExport DocumentMapper + { public: - explicit DocumentMapper(const std::map &); + explicit DocumentMapper(const std::map&); ~DocumentMapper(); }; - class String { + class String + { friend class ObjectIdentifier; public: - - String(const std::string &s = "", - bool _isRealString = false, - bool _forceIdentifier = false) - : str(s), - isString(_isRealString), - forceIdentifier(_forceIdentifier) - {}//explicit bombs - - explicit String(std::string &&s, - bool _isRealString = false, - bool _forceIdentifier = false) - : str(std::move(s)), - isString(_isRealString), - forceIdentifier(_forceIdentifier) + String(const std::string& s = "", bool _isRealString = false, bool _forceIdentifier = false) + : str(s) + , isString(_isRealString) + , forceIdentifier(_forceIdentifier) + {} // explicit bombs + + explicit String(std::string&& s, bool _isRealString = false, bool _forceIdentifier = false) + : str(std::move(s)) + , isString(_isRealString) + , forceIdentifier(_forceIdentifier) {} - FC_DEFAULT_CTORS(String) { + FC_DEFAULT_CTORS(String) + { str = std::move(other.str); isString = other.isString; forceIdentifier = other.forceIdentifier; @@ -109,40 +113,70 @@ class AppExport ObjectIdentifier { // Accessors /** Returns the string */ - const std::string &getString() const { return str; } + const std::string& getString() const + { + return str; + } /** Return true is string need to be quoted */ - bool isRealString() const { return isString; } + bool isRealString() const + { + return isString; + } - bool isForceIdentifier() const { return forceIdentifier; } + bool isForceIdentifier() const + { + return forceIdentifier; + } /** Returns a possibly quoted string */ - std::string toString(bool toPython=false) const; + std::string toString(bool toPython = false) const; // Operators - explicit operator std::string() const { return str; } + explicit operator std::string() const + { + return str; + } + + explicit operator const char*() const + { + return str.c_str(); + } - explicit operator const char *() const { return str.c_str(); } + bool operator==(const String& other) const + { + return str == other.str; + } - bool operator==(const String & other) const { return str == other.str; } + bool operator!=(const String& other) const + { + return str != other.str; + } - bool operator!=(const String & other) const { return str != other.str; } + bool operator>=(const String& other) const + { + return str >= other.str; + } - bool operator>=(const String & other) const { return str >= other.str; } + bool operator<(const String& other) const + { + return str < other.str; + } - bool operator<(const String & other) const { return str < other.str; } + bool operator>(const String& other) const + { + return str > other.str; + } - bool operator>(const String & other) const { return str > other.str; } + void checkImport(const App::DocumentObject* owner, + const App::DocumentObject* obj = nullptr, + String* objName = nullptr); - void checkImport(const App::DocumentObject *owner, - const App::DocumentObject *obj=nullptr, String *objName=nullptr); private: - std::string str; bool isString; bool forceIdentifier; - }; /** @@ -151,21 +185,22 @@ class AppExport ObjectIdentifier { * a single entry, and array, or a map to other sub-fields. */ - class AppExport Component { + class AppExport Component + { private: - - enum typeEnum { + enum typeEnum + { SIMPLE, MAP, ARRAY, RANGE, - } ; + }; public: - // Constructors - FC_DEFAULT_CTORS(Component) { + FC_DEFAULT_CTORS(Component) + { name = std::move(other.name); type = other.type; begin = other.begin; @@ -174,98 +209,147 @@ class AppExport ObjectIdentifier { return *this; } - Component(const String &_name = String(), typeEnum _type=SIMPLE, - int begin=INT_MAX, int end=INT_MAX, int step=1);//explicit bombs - Component(String &&_name, typeEnum _type=SIMPLE, - int begin=INT_MAX, int end=INT_MAX, int step=1);//explicit bombs + Component(const String& _name = String(), + typeEnum _type = SIMPLE, + int begin = INT_MAX, + int end = INT_MAX, + int step = 1); // explicit bombs + Component(String&& _name, + typeEnum _type = SIMPLE, + int begin = INT_MAX, + int end = INT_MAX, + int step = 1); // explicit bombs - static Component SimpleComponent(const char * _component); + static Component SimpleComponent(const char* _component); - static Component SimpleComponent(const String & _component); - static Component SimpleComponent(String &&_component); + static Component SimpleComponent(const String& _component); + static Component SimpleComponent(String&& _component); static Component ArrayComponent(int _index); - static Component RangeComponent(int _begin, int _end = INT_MAX, int _step=1); + static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1); - static Component MapComponent(const String &_key); - static Component MapComponent(String &&_key); + static Component MapComponent(const String& _key); + static Component MapComponent(String&& _key); // Type queries - bool isSimple() const { return type == SIMPLE; } + bool isSimple() const + { + return type == SIMPLE; + } - bool isMap() const { return type == MAP; } + bool isMap() const + { + return type == MAP; + } - bool isArray() const { return type == ARRAY; } + bool isArray() const + { + return type == ARRAY; + } - bool isRange() const { return type == RANGE; } + bool isRange() const + { + return type == RANGE; + } // Accessors - void toString(std::ostream &ss, bool toPython=false) const; + void toString(std::ostream& ss, bool toPython = false) const; - const std::string &getName() const { return name.getString(); } + const std::string& getName() const + { + return name.getString(); + } - int getIndex() const {return begin;} + int getIndex() const + { + return begin; + } size_t getIndex(size_t count) const; - int getBegin() const { return begin; } - int getEnd() const { return end; } - int getStep() const { return step; } + int getBegin() const + { + return begin; + } + int getEnd() const + { + return end; + } + int getStep() const + { + return step; + } // Operators - bool operator==(const Component & other) const; - bool operator<(const Component & other) const; + bool operator==(const Component& other) const; + bool operator<(const Component& other) const; - Py::Object get(const Py::Object &pyobj) const; - void set(Py::Object &pyobj, const Py::Object &value) const; - void del(Py::Object &pyobj) const; + Py::Object get(const Py::Object& pyobj) const; + void set(Py::Object& pyobj, const Py::Object& value) const; + void del(Py::Object& pyobj) const; private: - String name; typeEnum type; int begin; int end; int step; friend class ObjectIdentifier; - }; - static Component SimpleComponent(const char * _component) - {return Component::SimpleComponent(_component);} + static Component SimpleComponent(const char* _component) + { + return Component::SimpleComponent(_component); + } - static Component SimpleComponent(const String & _component) - {return Component::SimpleComponent(_component);} + static Component SimpleComponent(const String& _component) + { + return Component::SimpleComponent(_component); + } - static Component SimpleComponent(String &&_component) - {return Component::SimpleComponent(std::move(_component));} + static Component SimpleComponent(String&& _component) + { + return Component::SimpleComponent(std::move(_component)); + } - static Component SimpleComponent(const std::string _component) - {return Component::SimpleComponent(_component.c_str());} + static Component SimpleComponent(const std::string _component) + { + return Component::SimpleComponent(_component.c_str()); + } static Component ArrayComponent(int _index) - {return Component::ArrayComponent(_index); } + { + return Component::ArrayComponent(_index); + } - static Component RangeComponent(int _begin, int _end = INT_MAX, int _step=1) - {return Component::RangeComponent(_begin,_end,_step);} + static Component RangeComponent(int _begin, int _end = INT_MAX, int _step = 1) + { + return Component::RangeComponent(_begin, _end, _step); + } - static Component MapComponent(const String &_key) - {return Component::MapComponent(_key);} + static Component MapComponent(const String& _key) + { + return Component::MapComponent(_key); + } - static Component MapComponent(String &&_key) - {return Component::MapComponent(_key);} + static Component MapComponent(String&& _key) + { + return Component::MapComponent(_key); + } - explicit ObjectIdentifier(const App::PropertyContainer * _owner = nullptr, - const std::string & property = std::string(), int index=INT_MAX); + explicit ObjectIdentifier(const App::PropertyContainer* _owner = nullptr, + const std::string& property = std::string(), + int index = INT_MAX); - ObjectIdentifier(const App::PropertyContainer * _owner, bool localProperty); + ObjectIdentifier(const App::PropertyContainer* _owner, bool localProperty); - ObjectIdentifier(const App::Property & prop, int index=INT_MAX);//explicit bombs + ObjectIdentifier(const App::Property& prop, int index = INT_MAX); // explicit bombs - FC_DEFAULT_CTORS(ObjectIdentifier) { + FC_DEFAULT_CTORS(ObjectIdentifier) + { owner = other.owner; documentName = std::move(other.documentName); documentObjectName = std::move(other.documentObjectName); @@ -282,16 +366,21 @@ class AppExport ObjectIdentifier { virtual ~ObjectIdentifier() = default; - App::DocumentObject *getOwner() const { return owner; } + App::DocumentObject* getOwner() const + { + return owner; + } // Components - void addComponent(const Component &c) { + void addComponent(const Component& c) + { components.push_back(c); _cache.clear(); } // Components - void addComponent(Component &&c) { + void addComponent(Component&& c) + { components.push_back(std::move(c)); _cache.clear(); } @@ -299,23 +388,29 @@ class AppExport ObjectIdentifier { std::string getPropertyName() const; template - void addComponents(const C &cs) { components.insert(components.end(), cs.begin(), cs.end()); } + void addComponents(const C& cs) + { + components.insert(components.end(), cs.begin(), cs.end()); + } - const Component & getPropertyComponent(int i, int *idx=nullptr) const; + const Component& getPropertyComponent(int i, int* idx = nullptr) const; - void setComponent(int idx, Component &&comp); - void setComponent(int idx, const Component &comp); + void setComponent(int idx, Component&& comp); + void setComponent(int idx, const Component& comp); std::vector getPropertyComponents() const; - const std::vector &getComponents() const { return components; } + const std::vector& getComponents() const + { + return components; + } - std::string getSubPathStr(bool toPython=false) const; + std::string getSubPathStr(bool toPython = false) const; int numComponents() const; int numSubComponents() const; - const std::string &toString() const; + const std::string& toString() const; std::string toPersistentString() const; @@ -323,37 +418,46 @@ class AppExport ObjectIdentifier { bool isTouched() const; - App::Property *getProperty(int *ptype=nullptr) const; + App::Property* getProperty(int* ptype = nullptr) const; App::ObjectIdentifier canonicalPath() const; // Document-centric functions - void setDocumentName(String &&name, bool force = false); + void setDocumentName(String&& name, bool force = false); String getDocumentName() const; - void setDocumentObjectName(String &&name, bool force = false, - String &&subname = String(), bool checkImport=false); + void setDocumentObjectName(String&& name, + bool force = false, + String&& subname = String(), + bool checkImport = false); - void setDocumentObjectName(const App::DocumentObject *obj, bool force = false, - String &&subname = String(), bool checkImport=false); + void setDocumentObjectName(const App::DocumentObject* obj, + bool force = false, + String&& subname = String(), + bool checkImport = false); - bool hasDocumentObjectName(bool forced=false) const; + bool hasDocumentObjectName(bool forced = false) const; - bool isLocalProperty() const { return localProperty; } + bool isLocalProperty() const + { + return localProperty; + } String getDocumentObjectName() const; - const std::string &getSubObjectName(bool newStyle) const; - const std::string &getSubObjectName() const; + const std::string& getSubObjectName(bool newStyle) const; + const std::string& getSubObjectName() const; - using SubNameMap = std::map,std::string>; - void importSubNames(const SubNameMap &subNameMap); + using SubNameMap = std::map, std::string>; + void importSubNames(const SubNameMap& subNameMap); - bool updateLabelReference(App::DocumentObject *, const std::string &, const char *); + bool updateLabelReference(App::DocumentObject*, const std::string&, const char*); - bool relabeledDocument(ExpressionVisitor &v, const std::string &oldLabel, const std::string &newLabel); + bool relabeledDocument(ExpressionVisitor& v, + const std::string& oldLabel, + const std::string& newLabel); /** Type for storing dependency of an ObjectIdentifier * @@ -365,7 +469,7 @@ class AppExport ObjectIdentifier { * the property may not exist at the time this ObjectIdentifier is * constructed. */ - using Dependencies = std::map >; + using Dependencies = std::map>; /** Get dependencies of this object identifier * @@ -377,7 +481,7 @@ class AppExport ObjectIdentifier { * first referred object dependency. Or else, all object and property * dependencies will be returned. */ - Dependencies getDep(bool needProps, std::vector *labels=nullptr) const; + Dependencies getDep(bool needProps, std::vector* labels = nullptr) const; /** Get dependencies of this object identifier * @@ -390,104 +494,112 @@ class AppExport ObjectIdentifier { * first referred object dependency. Or else, all object and property * dependencies will be returned. */ - void getDep(Dependencies &deps, bool needProps, std::vector *labels=nullptr) const; + void + getDep(Dependencies& deps, bool needProps, std::vector* labels = nullptr) const; /// Returns all label references - void getDepLabels(std::vector &labels) const; + void getDepLabels(std::vector& labels) const; - App::Document *getDocument(String name = String(), bool *ambiguous=nullptr) const; + App::Document* getDocument(String name = String(), bool* ambiguous = nullptr) const; - App::DocumentObject *getDocumentObject() const; + App::DocumentObject* getDocumentObject() const; std::vector getStringList() const; - App::ObjectIdentifier relativeTo(const App::ObjectIdentifier & other) const; + App::ObjectIdentifier relativeTo(const App::ObjectIdentifier& other) const; - bool replaceObject(ObjectIdentifier &res, const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const; + bool replaceObject(ObjectIdentifier& res, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const; // Operators - App::ObjectIdentifier & operator<<(const Component & value); - App::ObjectIdentifier & operator<<(Component &&value); + App::ObjectIdentifier& operator<<(const Component& value); + App::ObjectIdentifier& operator<<(Component&& value); - bool operator==(const ObjectIdentifier & other) const; + bool operator==(const ObjectIdentifier& other) const; - bool operator!=(const ObjectIdentifier & other) const; + bool operator!=(const ObjectIdentifier& other) const; - bool operator<(const ObjectIdentifier &other) const; + bool operator<(const ObjectIdentifier& other) const; // Getter - App::any getValue(bool pathValue=false, bool *isPseudoProperty=nullptr) const; + App::any getValue(bool pathValue = false, bool* isPseudoProperty = nullptr) const; - Py::Object getPyValue(bool pathValue=false, bool *isPseudoProperty=nullptr) const; + Py::Object getPyValue(bool pathValue = false, bool* isPseudoProperty = nullptr) const; // Setter: is const because it does not alter the object state, // but does have an aiding effect. - void setValue(const App::any & value) const; + void setValue(const App::any& value) const; // Static functions - static ObjectIdentifier parse(const App::DocumentObject *docObj, const std::string & str); + static ObjectIdentifier parse(const App::DocumentObject* docObj, const std::string& str); std::string resolveErrorString() const; - bool adjustLinks(ExpressionVisitor &v, const std::set &inList); + bool adjustLinks(ExpressionVisitor& v, const std::set& inList); - bool updateElementReference(ExpressionVisitor &v, App::DocumentObject *feature=nullptr, bool reverse=false); + bool updateElementReference(ExpressionVisitor& v, + App::DocumentObject* feature = nullptr, + bool reverse = false); void resolveAmbiguity(); - bool verify(const App::Property &prop, bool silent=false) const; + bool verify(const App::Property& prop, bool silent = false) const; std::size_t hash() const; protected: + struct ResolveResults + { - struct ResolveResults { + explicit ResolveResults(const ObjectIdentifier& oi); - explicit ResolveResults(const ObjectIdentifier & oi); - - int propertyIndex{0}; - App::Document * resolvedDocument{nullptr}; + int propertyIndex {0}; + App::Document* resolvedDocument {nullptr}; String resolvedDocumentName; - App::DocumentObject * resolvedDocumentObject{nullptr}; + App::DocumentObject* resolvedDocumentObject {nullptr}; String resolvedDocumentObjectName; String subObjectName; - App::DocumentObject * resolvedSubObject{nullptr}; - App::Property * resolvedProperty{nullptr}; + App::DocumentObject* resolvedSubObject {nullptr}; + App::Property* resolvedProperty {nullptr}; std::string propertyName; - int propertyType{0}; + int propertyType {0}; std::bitset<32> flags; std::string resolveErrorString() const; - void getProperty(const ObjectIdentifier &oi); + void getProperty(const ObjectIdentifier& oi); }; friend struct ResolveResults; - App::Property *resolveProperty(const App::DocumentObject *obj, - const char *propertyName, App::DocumentObject *&sobj,int &ptype) const; + App::Property* resolveProperty(const App::DocumentObject* obj, + const char* propertyName, + App::DocumentObject*& sobj, + int& ptype) const; - void getSubPathStr(std::ostream &ss, const ResolveResults &result, bool toPython=false) const; + void getSubPathStr(std::ostream& ss, const ResolveResults& result, bool toPython = false) const; - Py::Object access(const ResolveResults &rs, - Py::Object *value=nullptr, Dependencies *deps=nullptr) const; + Py::Object access(const ResolveResults& rs, + Py::Object* value = nullptr, + Dependencies* deps = nullptr) const; - void resolve(ResolveResults & results) const; - void resolveAmbiguity(ResolveResults &results); + void resolve(ResolveResults& results) const; + void resolveAmbiguity(ResolveResults& results); - static App::DocumentObject *getDocumentObject( - const App::Document *doc, const String &name, std::bitset<32> &flags); + static App::DocumentObject* + getDocumentObject(const App::Document* doc, const String& name, std::bitset<32>& flags); - void getDepLabels(const ResolveResults &result, std::vector &labels) const; + void getDepLabels(const ResolveResults& result, std::vector& labels) const; - App::DocumentObject * owner; - String documentName; - String documentObjectName; - String subObjectName; + App::DocumentObject* owner; + String documentName; + String documentObjectName; + String subObjectName; ElementNamePair shadowSub; std::vector components; bool documentNameSet; @@ -495,35 +607,39 @@ class AppExport ObjectIdentifier { bool localProperty; private: - std::string _cache; // Cached string represstation of this identifier - std::size_t _hash; // Cached hash of this string + std::string _cache; // Cached string represstation of this identifier + std::size_t _hash; // Cached hash of this string }; -inline std::size_t hash_value(const App::ObjectIdentifier & path) { +inline std::size_t hash_value(const App::ObjectIdentifier& path) +{ return path.hash(); } /** Helper function to convert Python object to/from App::any -* -* WARNING! Must hold Python global interpreter lock before calling these -* functions -*/ + * + * WARNING! Must hold Python global interpreter lock before calling these + * functions + */ //@{ -App::any AppExport pyObjectToAny(Py::Object pyobj, bool check=true); -Py::Object AppExport pyObjectFromAny(const App::any &value); +App::any AppExport pyObjectToAny(Py::Object pyobj, bool check = true); +Py::Object AppExport pyObjectFromAny(const App::any& value); //@} -} +} // namespace App -namespace std { +namespace std +{ template<> -struct hash { +struct hash +{ using argument_type = App::ObjectIdentifier; using result_type = std::size_t; - inline result_type operator()(argument_type const& s) const { + inline result_type operator()(argument_type const& s) const + { return s.hash(); } }; -} +} // namespace std #endif diff --git a/src/App/Property.cpp b/src/App/Property.cpp index 2db9e5ed369c..2b20f8f166df 100644 --- a/src/App/Property.cpp +++ b/src/App/Property.cpp @@ -45,7 +45,7 @@ using namespace App; // Property //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::Property , Base::Persistence) +TYPESYSTEM_SOURCE_ABSTRACT(App::Property, Base::Persistence) //************************************************************************** // Construction/Destruction @@ -54,9 +54,8 @@ static std::atomic _PropID; // Here is the implementation! Description should take place in the header file! Property::Property() - : _id(++_PropID) -{ -} + : _id(++_PropID) +{} Property::~Property() = default; @@ -75,16 +74,21 @@ bool Property::isValidName(const char* name) return name && name[0] != '\0'; } -std::string Property::getFullName() const { +std::string Property::getFullName() const +{ std::string name; - if(myName) { - if(father) + if (myName) { + if (father) { name = father->getFullName() + "."; - else + } + else { name = "?."; + } name += myName; - }else + } + else { return "?"; + } return name; } @@ -116,9 +120,11 @@ std::string Property::getFileName(const char* postfix, const char* prefix) const short Property::getType() const { short type = 0; -#define GET_PTYPE(_name) do {\ - if(testStatus(App::Property::Prop##_name)) type|=Prop_##_name;\ - }while(0) +#define GET_PTYPE(_name) \ + do { \ + if (testStatus(App::Property::Prop##_name)) \ + type |= Prop_##_name; \ + } while (0) GET_PTYPE(ReadOnly); GET_PTYPE(Hidden); GET_PTYPE(Output); @@ -128,10 +134,13 @@ short Property::getType() const return type; } -void Property::syncType(unsigned type) { -#define SYNC_PTYPE(_name) do{\ - if(type & Prop_##_name) StatusBits.set((size_t)Prop##_name);\ - }while(0) +void Property::syncType(unsigned type) +{ +#define SYNC_PTYPE(_name) \ + do { \ + if (type & Prop_##_name) \ + StatusBits.set((size_t)Prop##_name); \ + } while (0) SYNC_PTYPE(ReadOnly); SYNC_PTYPE(Transient); SYNC_PTYPE(Hidden); @@ -150,32 +159,33 @@ const char* Property::getDocumentation() const return father->getPropertyDocumentation(this); } -void Property::setContainer(PropertyContainer *Father) +void Property::setContainer(PropertyContainer* Father) { father = Father; } -void Property::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void Property::setPathValue(const ObjectIdentifier& path, const boost::any& value) { path.setValue(value); } -const boost::any Property::getPathValue(const ObjectIdentifier &path) const +const boost::any Property::getPathValue(const ObjectIdentifier& path) const { return path.getValue(); } -void Property::getPaths(std::vector &paths) const +void Property::getPaths(std::vector& paths) const { paths.emplace_back(getContainer(), getName()); } -ObjectIdentifier Property::canonicalPath(const ObjectIdentifier &p) const +ObjectIdentifier Property::canonicalPath(const ObjectIdentifier& p) const { return p; } -namespace App { +namespace App +{ /*! * \brief The PropertyCleaner struct * Make deleting dynamic property safer by postponing its destruction. @@ -186,43 +196,51 @@ namespace App { * removed property, and only deleting them when no onChanged() call is * active. */ -struct PropertyCleaner { - explicit PropertyCleaner(Property *p) +struct PropertyCleaner +{ + explicit PropertyCleaner(Property* p) : prop(p) { ++_PropCleanerCounter; } - ~PropertyCleaner() { - if(--_PropCleanerCounter) + ~PropertyCleaner() + { + if (--_PropCleanerCounter) { return; + } bool found = false; while (!_RemovedProps.empty()) { auto p = _RemovedProps.back(); _RemovedProps.pop_back(); - if(p != prop) + if (p != prop) { delete p; - else + } + else { found = true; + } } - if (found) + if (found) { _RemovedProps.push_back(prop); + } } - static void add(Property *prop) { + static void add(Property* prop) + { _RemovedProps.push_back(prop); } - Property *prop; + Property* prop; static std::vector _RemovedProps; static int _PropCleanerCounter; }; -} +} // namespace App std::vector PropertyCleaner::_RemovedProps; int PropertyCleaner::_PropCleanerCounter = 0; -void Property::destroy(Property *p) { +void Property::destroy(Property* p) +{ if (p) { // Is it necessary to nullify the container? May cause crash if any // onChanged() caller assumes a non-null container. @@ -253,8 +271,8 @@ void Property::hasSetValue() PropertyCleaner guard(this); if (father) { father->onChanged(this); - if(!testStatus(Busy)) { - Base::BitsetLocker guard(StatusBits,Busy); + if (!testStatus(Busy)) { + Base::BitsetLocker guard(StatusBits, Busy); signalChanged(*this); } } @@ -263,16 +281,17 @@ void Property::hasSetValue() void Property::aboutToSetValue() { - if (father) + if (father) { father->onBeforeChange(this); + } } -void Property::verifyPath(const ObjectIdentifier &p) const +void Property::verifyPath(const ObjectIdentifier& p) const { p.verify(*this); } -Property *Property::Copy() const +Property* Property::Copy() const { // have to be reimplemented by a subclass! assert(0); @@ -285,7 +304,8 @@ void Property::Paste(const Property& /*from*/) assert(0); } -void Property::setStatusValue(unsigned long status) { +void Property::setStatusValue(unsigned long status) +{ // clang-format off static const unsigned long mask = (1<onPropertyStatusChanged(*this,oldStatus); + if (father) { + static unsigned long _signalMask = (1 << ReadOnly) | (1 << Hidden); + if ((status & _signalMask) != (oldStatus & _signalMask)) { + father->onPropertyStatusChanged(*this, oldStatus); + } } } -void Property::setStatus(Status pos, bool on) { +void Property::setStatus(Status pos, bool on) +{ auto bits = StatusBits; - bits.set(pos,on); + bits.set(pos, on); setStatusValue(bits.to_ulong()); } -bool Property::isSame(const Property &other) const { - if(&other == this) +bool Property::isSame(const Property& other) const +{ + if (&other == this) { return true; - if(other.getTypeId() != getTypeId() || getMemSize() != other.getMemSize()) + } + if (other.getTypeId() != getTypeId() || getMemSize() != other.getMemSize()) { return false; + } - Base::StringWriter writer,writer2; + Base::StringWriter writer, writer2; Save(writer); other.Save(writer2); return writer.getString() == writer2.getString(); @@ -333,9 +358,10 @@ bool Property::isSame(const Property &other) const { // PropertyListsBase //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -void PropertyListsBase::_setPyObject(PyObject *value) { +void PropertyListsBase::_setPyObject(PyObject* value) +{ std::vector indices; - std::vector vals; + std::vector vals; Py::Object pySeq; if (PyDict_Check(value)) { @@ -344,42 +370,48 @@ void PropertyListsBase::_setPyObject(PyObject *value) { vals.reserve(size); indices.reserve(size); int listSize = getSize(); - for(auto it=dict.begin();it!=dict.end();++it) { - const auto &item = *it; - PyObject *key = item.first.ptr(); - if(!PyLong_Check(key)) + for (auto it = dict.begin(); it != dict.end(); ++it) { + const auto& item = *it; + PyObject* key = item.first.ptr(); + if (!PyLong_Check(key)) { throw Base::TypeError("expect key type to be integer"); + } long idx = PyLong_AsLong(key); - if(idx<-1 || idx>listSize) + if (idx < -1 || idx > listSize) { throw Base::ValueError("index out of bound"); - if(idx==-1 || idx==listSize) { + } + if (idx == -1 || idx == listSize) { idx = listSize; ++listSize; } indices.push_back(idx); vals.push_back(item.second.ptr()); } - } else { - if (PySequence_Check(value)) + } + else { + if (PySequence_Check(value)) { pySeq = value; + } else { - PyObject *iter = PyObject_GetIter(value); - if(iter) { - Py::Object pyIter(iter,true); - pySeq = Py::asObject(PySequence_Fast(iter,"")); - } else { + PyObject* iter = PyObject_GetIter(value); + if (iter) { + Py::Object pyIter(iter, true); + pySeq = Py::asObject(PySequence_Fast(iter, "")); + } + else { PyErr_Clear(); vals.push_back(value); } } - if(!pySeq.isNone()) { + if (!pySeq.isNone()) { Py::Sequence seq(pySeq); vals.reserve(seq.size()); - for(auto it=seq.begin();it!=seq.end();++it) + for (auto it = seq.begin(); it != seq.end(); ++it) { vals.push_back((*it).ptr()); + } } } - setPyValues(vals,indices); + setPyValues(vals, indices); } @@ -388,4 +420,4 @@ void PropertyListsBase::_setPyObject(PyObject *value) { // PropertyLists //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLists , App::Property) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLists, App::Property) diff --git a/src/App/Property.h b/src/App/Property.h index 3dd456428e46..f222148d654e 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -33,7 +33,8 @@ #include #include "ElementNamingUtils.h" -namespace Py { +namespace Py +{ class Object; } @@ -52,33 +53,34 @@ class ObjectIdentifier; * possible properties. It is also possible to define user properties * and use them in the framework... */ -class AppExport Property : public Base::Persistence +class AppExport Property: public Base::Persistence { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: enum Status { - Touched = 0, // touched property - Immutable = 1, // can't modify property - ReadOnly = 2, // for property editor - Hidden = 3, // for property editor - Transient = 4, // for property container save - MaterialEdit = 5, // to turn ON PropertyMaterial edit - NoMaterialListEdit = 6, // to turn OFF PropertyMaterialList edit - Output = 7, // same effect as Prop_Output - LockDynamic = 8, // prevent being removed from dynamic property - NoModify = 9, // prevent causing Gui::Document::setModified() - PartialTrigger = 10, // allow change in partial doc - NoRecompute = 11, // touch owner for recompute on property change - Single = 12, // for save/load of floating point numbers - Ordered = 13, // for PropertyLists whether the order of the elements is - // relevant for the container using it - EvalOnRestore = 14, // In case of expression binding, evaluate the - // expression on restore and touch the object on value change. - Busy = 15, // internal use to avoid recursive signaling - CopyOnChange = 16, // for Link to copy the linked object on change of the property with this flag - UserEdit = 17, // cause property editor to create button for user defined editing + Touched = 0, // touched property + Immutable = 1, // can't modify property + ReadOnly = 2, // for property editor + Hidden = 3, // for property editor + Transient = 4, // for property container save + MaterialEdit = 5, // to turn ON PropertyMaterial edit + NoMaterialListEdit = 6, // to turn OFF PropertyMaterialList edit + Output = 7, // same effect as Prop_Output + LockDynamic = 8, // prevent being removed from dynamic property + NoModify = 9, // prevent causing Gui::Document::setModified() + PartialTrigger = 10, // allow change in partial doc + NoRecompute = 11, // touch owner for recompute on property change + Single = 12, // for save/load of floating point numbers + Ordered = 13, // for PropertyLists whether the order of the elements is + // relevant for the container using it + EvalOnRestore = 14, // In case of expression binding, evaluate the + // expression on restore and touch the object on value change. + Busy = 15, // internal use to avoid recursive signaling + CopyOnChange = + 16, // for Link to copy the linked object on change of the property with this flag + UserEdit = 17, // cause property editor to create button for user defined editing // The following bits are corresponding to PropertyType set when the // property added. These types are meant to be static, and cannot be @@ -86,26 +88,26 @@ class AppExport Property : public Base::Persistence // required in PropertyContainer::getPropertyType() // PropStaticBegin = 21, - PropDynamic = 21, // indicating the property is dynamically added - PropNoPersist = 22, // corresponding to Prop_NoPersist - PropNoRecompute = 23, // corresponding to Prop_NoRecompute - PropReadOnly = 24, // corresponding to Prop_ReadOnly - PropTransient= 25, // corresponding to Prop_Transient - PropHidden = 26, // corresponding to Prop_Hidden - PropOutput = 27, // corresponding to Prop_Output + PropDynamic = 21, // indicating the property is dynamically added + PropNoPersist = 22, // corresponding to Prop_NoPersist + PropNoRecompute = 23, // corresponding to Prop_NoRecompute + PropReadOnly = 24, // corresponding to Prop_ReadOnly + PropTransient = 25, // corresponding to Prop_Transient + PropHidden = 26, // corresponding to Prop_Hidden + PropOutput = 27, // corresponding to Prop_Output PropStaticEnd = 28, - User1 = 28, // user-defined status - User2 = 29, // user-defined status - User3 = 30, // user-defined status - User4 = 31 // user-defined status + User1 = 28, // user-defined status + User2 = 29, // user-defined status + User3 = 30, // user-defined status + User4 = 31 // user-defined status }; Property(); ~Property() override; /// For safe deleting of a dynamic property - static void destroy(Property *p); + static void destroy(Property* p); /** This method is used to get the size of objects * It is not meant to have the exact size, it is more or less an estimation @@ -113,7 +115,8 @@ class AppExport Property : public Base::Persistence * This method is defined in Base::Persistence * @see Base::Persistence */ - unsigned int getMemSize () const override { + unsigned int getMemSize() const override + { // you have to implement this method in all property classes! return sizeof(father) + sizeof(StatusBits); } @@ -136,7 +139,10 @@ class AppExport Property : public Base::Persistence std::string getFullName() const; /// Get the class name of the associated property editor item - virtual const char* getEditorName() const { return ""; } + virtual const char* getEditorName() const + { + return ""; + } /// Get the type of the property in the container short getType() const; @@ -148,27 +154,31 @@ class AppExport Property : public Base::Persistence const char* getDocumentation() const; /// Is called by the framework to set the father (container) - void setContainer(PropertyContainer *Father); + void setContainer(PropertyContainer* Father); /// Get a pointer to the PropertyContainer derived class the property belongs to - PropertyContainer *getContainer() const {return father;} + PropertyContainer* getContainer() const + { + return father; + } /// Set value of property - virtual void setPathValue(const App::ObjectIdentifier & path, const boost::any & value); + virtual void setPathValue(const App::ObjectIdentifier& path, const boost::any& value); /// Get value of property - virtual const boost::any getPathValue(const App::ObjectIdentifier & path) const; + virtual const boost::any getPathValue(const App::ObjectIdentifier& path) const; /// Get Python value of property - virtual bool getPyPathValue(const App::ObjectIdentifier &, Py::Object &) const { + virtual bool getPyPathValue(const App::ObjectIdentifier&, Py::Object&) const + { return false; } /// Convert p to a canonical representation of it - virtual App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier & p) const; + virtual App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier& p) const; /// Get valid paths for this property; used by auto completer - virtual void getPaths(std::vector & paths) const; + virtual void getPaths(std::vector& paths) const; /** Called at the beginning of Document::afterRestore() * @@ -190,7 +200,8 @@ class AppExport Property : public Base::Persistence * with existing documents. PropertyExpressionEngine can now auto adjust * external references without any problem. */ - virtual void afterRestore() {} + virtual void afterRestore() + {} /** Called before calling DocumentObject::onDocumentRestored() * @@ -199,7 +210,8 @@ class AppExport Property : public Base::Persistence * is assumed ready. So, unlike Property::afterRestore(), this function is * called on objects with dependency order. */ - virtual void onContainerRestored() {} + virtual void onContainerRestored() + {} /** Property status handling */ @@ -207,50 +219,59 @@ class AppExport Property : public Base::Persistence /// Set the property touched void touch(); /// Test if this property is touched - inline bool isTouched() const { + inline bool isTouched() const + { return StatusBits.test(Touched); } /// Reset this property touched - inline void purgeTouched() { + inline void purgeTouched() + { StatusBits.reset(Touched); } /// return the status bits - inline unsigned long getStatus() const { + inline unsigned long getStatus() const + { return StatusBits.to_ulong(); } - inline bool testStatus(Status pos) const { + inline bool testStatus(Status pos) const + { return StatusBits.test(static_cast(pos)); } void setStatus(Status pos, bool on); void setStatusValue(unsigned long status); - ///Sets property editable/grayed out in property editor + /// Sets property editable/grayed out in property editor void setReadOnly(bool readOnly); - inline bool isReadOnly() const { + inline bool isReadOnly() const + { return testStatus(App::Property::ReadOnly); } /// Sets precision of properties using floating point /// numbers to single, the default is double. - void setSinglePrecision(bool single) { + void setSinglePrecision(bool single) + { setStatus(App::Property::Single, single); } /// Gets precision of properties using floating point numbers - inline bool isSinglePrecision() const { + inline bool isSinglePrecision() const + { return testStatus(App::Property::Single); } //@} /// Returns a new copy of the property (mainly for Undo/Redo and transactions) - virtual Property *Copy() const = 0; + virtual Property* Copy() const = 0; /// Paste the value from the property (mainly for Undo/Redo and transactions) - virtual void Paste(const Property &from) = 0; + virtual void Paste(const Property& from) = 0; /// Called when a child property has changed value - virtual void hasSetChildValue(Property &) {} + virtual void hasSetChildValue(Property&) + {} /// Called before a child property changing value - virtual void aboutToSetChildValue(Property &) {} + virtual void aboutToSetChildValue(Property&) + {} /// Compare if this property has the same content as the given one - virtual bool isSame(const Property &other) const; + virtual bool isSame(const Property& other) const; /** Return a unique ID for the property * @@ -258,11 +279,15 @@ class AppExport Property : public Base::Persistence * internal counter. The intention of the ID is to be used as a key for * mapping, instead of using the raw pointer. Because, it is possible for * the runtime memory allocator to reuse just deleted memory, which will - * cause hard to debug problem if use pointer as key. + * cause hard to debug problem if use pointer as key. */ - int64_t getID() const {return _id;} + int64_t getID() const + { + return _id; + } - virtual void beforeSave() const {} + virtual void beforeSave() const + {} friend class PropertyContainer; friend struct PropertyData; @@ -287,31 +312,32 @@ class AppExport Property : public Base::Persistence virtual void aboutToSetValue(); /// Verify a path for the current property - virtual void verifyPath(const App::ObjectIdentifier & p) const; + virtual void verifyPath(const App::ObjectIdentifier& p) const; /// Return a file name suitable for saving this property - std::string getFileName(const char *postfix=0, const char *prefix=0) const; + std::string getFileName(const char* postfix = 0, const char* prefix = 0) const; public: // forbidden Property(const Property&) = delete; - Property& operator = (const Property&) = delete; + Property& operator=(const Property&) = delete; private: // Sync status with Property_Type void syncType(unsigned type); private: - PropertyContainer *father{nullptr}; - const char *myName{nullptr}; + PropertyContainer* father {nullptr}; + const char* myName {nullptr}; int64_t _id; public: - boost::signals2::signal signalChanged; + boost::signals2::signal signalChanged; }; -/** A template class that is used to inhibit multiple nested calls to aboutToSetValue/hasSetValue for properties. +/** A template class that is used to inhibit multiple nested calls to aboutToSetValue/hasSetValue + * for properties. * * A template class that is used to inhibit multiple nested calls to * aboutToSetValue/hasSetValue for properties, and only invoke it on change and @@ -338,12 +364,15 @@ class AppExport Property : public Base::Persistence * you can manually call AtomicPropertyChange::tryInvoke(). If the condition is * satisfied, it will call hasSetValue() that allows exception propagation. */ -template class AtomicPropertyChangeInterface { +template +class AtomicPropertyChangeInterface +{ protected: AtomicPropertyChangeInterface() = default; public: - class AtomicPropertyChange { + class AtomicPropertyChange + { public: /** Constructor * @@ -352,10 +381,13 @@ template class AtomicPropertyChangeInterface { * hasn't been marked before, and calls its * aboutToSetValue(). */ - explicit AtomicPropertyChange(P & prop, bool markChange=true) : mProp(prop) { + explicit AtomicPropertyChange(P& prop, bool markChange = true) + : mProp(prop) + { mProp.signalCounter++; - if (markChange) + if (markChange) { aboutToChange(); + } } /** Mark the property as changed @@ -363,7 +395,8 @@ template class AtomicPropertyChangeInterface { * It will mark the property as changed only if it has been marked * before, and only then will it call the property's aboutToSetValue(). */ - void aboutToChange() { + void aboutToChange() + { if (!mProp.hasChanged) { mProp.hasChanged = true; mProp.aboutToSetValue(); @@ -376,7 +409,8 @@ template class AtomicPropertyChangeInterface { * of the class in current call stack, it will call property's * hasSetValue() */ - ~AtomicPropertyChange() { + ~AtomicPropertyChange() + { // Signal counter == 1? meaning we are the last one. Invoke // hasSetValue() before decrease counter to prevent recursive call // triggered by another AtomicPropertyChange created inside @@ -385,13 +419,17 @@ template class AtomicPropertyChangeInterface { // Must make sure to not throw in a destructor try { mProp.hasSetValue(); - } catch(Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); - } catch(...) {} + } + catch (...) { + } mProp.hasChanged = false; } - if (mProp.signalCounter>0) + if (mProp.signalCounter > 0) { mProp.signalCounter--; + } } /** Check and invoke property's hasSetValue() @@ -401,22 +439,24 @@ template class AtomicPropertyChangeInterface { */ // Destructor cannot throw. So we provide this function to allow error // propagation. - void tryInvoke() { - if (mProp.signalCounter==1 && mProp.hasChanged) { + void tryInvoke() + { + if (mProp.signalCounter == 1 && mProp.hasChanged) { mProp.hasSetValue(); - if (mProp.signalCounter>0) + if (mProp.signalCounter > 0) { --mProp.signalCounter; + } mProp.hasChanged = false; } } private: - P & mProp; /**< Referenced to property we work on */ + P& mProp; /**< Referenced to property we work on */ }; protected: - int signalCounter{0}; /**< Counter for invoking transaction start/stop */ - bool hasChanged{false}; + int signalCounter {0}; /**< Counter for invoking transaction start/stop */ + bool hasChanged {false}; }; @@ -429,25 +469,28 @@ template class AtomicPropertyChangeInterface { class AppExport PropertyListsBase { public: - virtual void setSize(int newSize)=0; - virtual int getSize() const =0; + virtual void setSize(int newSize) = 0; + virtual int getSize() const = 0; - const std::set &getTouchList() const { + const std::set& getTouchList() const + { return _touchList; } - void clearTouchList() { + void clearTouchList() + { _touchList.clear(); } protected: - virtual void setPyValues(const std::vector &vals, const std::vector &indices) { + virtual void setPyValues(const std::vector& vals, const std::vector& indices) + { (void)vals; (void)indices; throw Base::NotImplementedError("not implemented"); } - void _setPyObject(PyObject *); + void _setPyObject(PyObject*); protected: std::set _touchList; @@ -458,111 +501,141 @@ class AppExport PropertyListsBase * multiple values, not only a single value. * All property types which may contain more than one value inherits this class. */ -class AppExport PropertyLists : public Property, public PropertyListsBase +class AppExport PropertyLists: public Property, public PropertyListsBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - void setPyObject(PyObject *obj) override { + void setPyObject(PyObject* obj) override + { _setPyObject(obj); } // if the order of the elements in the list relevant? // if yes, certain operations, like restoring must make sure that the // order is kept despite errors. - inline void setOrderRelevant(bool on) { this->setStatus(Status::Ordered,on); } - inline bool isOrderRelevant() const { return this->testStatus(Status::Ordered);} - + inline void setOrderRelevant(bool on) + { + this->setStatus(Status::Ordered, on); + } + inline bool isOrderRelevant() const + { + return this->testStatus(Status::Ordered); + } }; /** Helper class to implement PropertyLists */ -template, class ParentT = PropertyLists > -class PropertyListsT: public ParentT - , public AtomicPropertyChangeInterface > +template, class ParentT = PropertyLists> +class PropertyListsT: public ParentT, + public AtomicPropertyChangeInterface> { public: using const_reference = typename ListT::const_reference; using list_type = ListT; using parent_type = ParentT; using atomic_change = typename AtomicPropertyChangeInterface< - PropertyListsT >::AtomicPropertyChange; + PropertyListsT>::AtomicPropertyChange; friend atomic_change; - virtual void setSize(int newSize, const_reference def) { - _lValueList.resize(newSize,def); + virtual void setSize(int newSize, const_reference def) + { + _lValueList.resize(newSize, def); } - void setSize(int newSize) override { + void setSize(int newSize) override + { _lValueList.resize(newSize); } - int getSize() const override { + int getSize() const override + { return static_cast(_lValueList.size()); } - void setValue(const_reference value) { + void setValue(const_reference value) + { ListT vals; - vals.resize(1,value); + vals.resize(1, value); setValues(vals); } - virtual void setValues(const ListT &newValues = ListT()) { + virtual void setValues(const ListT& newValues = ListT()) + { atomic_change guard(*this); this->_touchList.clear(); this->_lValueList = newValues; guard.tryInvoke(); } - void setValue(const ListT &newValues = ListT()) { + void setValue(const ListT& newValues = ListT()) + { setValues(newValues); } - const ListT &getValues() const{return _lValueList;} + const ListT& getValues() const + { + return _lValueList; + } // alias to getValues - const ListT &getValue() const{return getValues();} + const ListT& getValue() const + { + return getValues(); + } - const_reference operator[] (int idx) const {return _lValueList[idx];} + const_reference operator[](int idx) const + { + return _lValueList[idx]; + } - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return this->getTypeId() == other.getTypeId() && this->getValue() == static_cast(&other)->getValue(); } - void setPyObject(PyObject *value) override { + void setPyObject(PyObject* value) override + { try { setValue(getPyValue(value)); return; - }catch(...){} + } + catch (...) { + } parent_type::setPyObject(value); } - virtual void set1Value(int index, const_reference value) { + virtual void set1Value(int index, const_reference value) + { int size = getSize(); - if (index<-1 || index>size) + if (index < -1 || index > size) { throw Base::RuntimeError("index out of bound"); + } atomic_change guard(*this); - if (index==-1 || index == size) { + if (index == -1 || index == size) { index = size; - setSize(index+1,value); - } else + setSize(index + 1, value); + } + else { _lValueList[index] = value; + } this->_touchList.insert(index); guard.tryInvoke(); } protected: - void setPyValues(const std::vector& vals, const std::vector& indices) override { if (indices.empty()) { ListT values {}; values.reserve(vals.size()); - for (auto *valsContent : vals) { + for (auto* valsContent : vals) { values.push_back(getPyValue(valsContent)); } setValues(std::move(values)); @@ -584,6 +657,6 @@ class PropertyListsT: public ParentT ListT _lValueList; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTY_H +#endif // APP_PROPERTY_H diff --git a/src/App/PropertyContainerPy.xml b/src/App/PropertyContainerPy.xml index 3ededf7d54aa..572e2ab14589 100644 --- a/src/App/PropertyContainerPy.xml +++ b/src/App/PropertyContainerPy.xml @@ -1,13 +1,13 @@  - @@ -16,14 +16,14 @@ - getPropertyByName(name, checkOwner=0) -> object or Tuple + getPropertyByName(name, checkOwner=0) -> object or Tuple Returns the value of a named property. Note that the returned property may not -always belong to this container (e.g. from a linked object). +always belong to this container (e.g. from a linked object). -name : str +name : str Name of the property. -checkOwner : int +checkOwner : int 0: just return the property. 1: raise exception if not found or the property does not belong to this container. 2: return a tuple (owner, propertyValue). @@ -31,44 +31,44 @@ checkOwner : int - getPropertyTouchList(name) -> tuple + getPropertyTouchList(name) -> tuple -Returns a list of index of touched values for list type properties. +Returns a list of index of touched values for list type properties. -name : str +name : str Property name. - getTypeOfProperty(name) -> list + getTypeOfProperty(name) -> list Returns the type of a named property. This can be a list conformed by elements in -(Hidden, NoRecompute, NoPersist, Output, ReadOnly, Transient). +(Hidden, NoRecompute, NoPersist, Output, ReadOnly, Transient). -name : str +name : str Property name. - getTypeIdOfProperty(name) -> str + getTypeIdOfProperty(name) -> str -Returns the C++ class name of a named property. +Returns the C++ class name of a named property. -name : str +name : str Property name. - setEditorMode(name, type) -> None + setEditorMode(name, type) -> None -Set the behaviour of the property in the property editor. +Set the behaviour of the property in the property editor. -name : str +name : str Property name. -type : int, sequence of str +type : int, sequence of str Property type. 0: default behaviour. 1: item is ready-only. 2: item is hidden. 3: item is hidden and read-only. If sequence, the available items are 'ReadOnly' and 'Hidden'. @@ -76,121 +76,121 @@ type : int, sequence of str - getEditorMode(name) -> list + getEditorMode(name) -> list Get the behaviour of the property in the property editor. It returns a list of strings with the current mode. If the list is empty there are no special restrictions. If the list contains 'ReadOnly' then the item appears in the property editor but is disabled. -If the list contains 'Hidden' then the item even doesn't appear in the property editor. +If the list contains 'Hidden' then the item even doesn't appear in the property editor. -name : str +name : str Property name. - getGroupOfProperty(name) -> str + getGroupOfProperty(name) -> str Returns the name of the group which the property belongs to in this class. -The properties are sorted in different named groups for convenience. +The properties are sorted in different named groups for convenience. -name : str +name : str Property name. - setGroupOfProperty(name, group) -> None + setGroupOfProperty(name, group) -> None -Set the name of the group of a dynamic property. +Set the name of the group of a dynamic property. -name : str +name : str Property name. -group : str +group : str Group name. - setPropertyStatus(name, val) -> None + setPropertyStatus(name, val) -> None -Set property status. +Set property status. -name : str +name : str Property name. -val : int, str, sequence of str or int +val : int, str, sequence of str or int Call getPropertyStatus() to get a list of supported text value. If the text start with '-' or the integer value is negative, then the status is cleared. - getPropertyStatus(name='') -> list + getPropertyStatus(name='') -> list -Get property status. +Get property status. -name : str +name : str Property name. If empty, returns a list of supported text names of the status. - getDocumentationOfProperty(name) -> str + getDocumentationOfProperty(name) -> str -Returns the documentation string of the property of this class. +Returns the documentation string of the property of this class. -name : str +name : str Property name. - setDocumentationOfProperty(name, docstring) -> None + setDocumentationOfProperty(name, docstring) -> None -Set the documentation string of a dynamic property of this class. +Set the documentation string of a dynamic property of this class. -name : str +name : str Property name. -docstring : str +docstring : str Documentation string. - getEnumerationsOfProperty(name) -> list or None + getEnumerationsOfProperty(name) -> list or None Return all enumeration strings of the property of this class or None if not a -PropertyEnumeration. +PropertyEnumeration. -name : str +name : str Property name. - dumpPropertyContent(Property, Compression=3) -> bytearray + dumpPropertyContent(Property, Compression=3) -> bytearray Dumps the content of the property, both the XML representation and the additional -data files required, into a byte representation. +data files required, into a byte representation. -Property : str +Property : str Property Name. -Compression : int +Compression : int Set the data compression level in the range [0, 9]. Set to 0 for no compression. - restorePropertyContent(name, obj) -> None + restorePropertyContent(name, obj) -> None Restore the content of the object from a byte representation as stored by `dumpPropertyContent`. -It could be restored from any Python object implementing the buffer protocol. +It could be restored from any Python object implementing the buffer protocol. -name : str +name : str Property name. -obj : buffer +obj : buffer Object with buffer protocol support. diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp index 8e2196dbbf55..4700b5a090b7 100644 --- a/src/App/PropertyContainerPyImp.cpp +++ b/src/App/PropertyContainerPyImp.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include "PropertyContainer.h" @@ -49,12 +49,13 @@ std::string PropertyContainerPy::representation() const return {""}; } -PyObject* PropertyContainerPy::getPropertyByName(PyObject *args) +PyObject* PropertyContainerPy::getPropertyByName(PyObject* args) { - char *pstr; - int checkOwner=0; - if (!PyArg_ParseTuple(args, "s|i", &pstr, &checkOwner)) + char* pstr {}; + int checkOwner = 0; + if (!PyArg_ParseTuple(args, "s|i", &pstr, &checkOwner)) { return nullptr; + } if (checkOwner < 0 || checkOwner > 2) { PyErr_SetString(PyExc_ValueError, "'checkOwner' expected in the range [0, 2]"); @@ -67,76 +68,87 @@ PyObject* PropertyContainerPy::getPropertyByName(PyObject *args) return nullptr; } - if (!checkOwner || (checkOwner==1 && prop->getContainer()==getPropertyContainerPtr())) + if (!checkOwner || (checkOwner == 1 && prop->getContainer() == getPropertyContainerPtr())) { return prop->getPyObject(); + } - Py::TupleN res(Py::asObject(prop->getContainer()->getPyObject()), Py::asObject(prop->getPyObject())); + Py::TupleN res(Py::asObject(prop->getContainer()->getPyObject()), + Py::asObject(prop->getPyObject())); return Py::new_reference_to(res); } -PyObject* PropertyContainerPy::getPropertyTouchList(PyObject *args) +PyObject* PropertyContainerPy::getPropertyTouchList(PyObject* args) { - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } App::Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (prop && prop->isDerivedFrom(PropertyLists::getClassTypeId())) { - const auto &touched = static_cast(prop)->getTouchList(); + const auto& touched = static_cast(prop)->getTouchList(); Py::Tuple ret(touched.size()); - int i=0; - for(int idx : touched) - ret.setItem(i++,Py::Long(idx)); + int i = 0; + for (int idx : touched) { + ret.setItem(i++, Py::Long(idx)); + } return Py::new_reference_to(ret); } - else if (!prop) { + if (!prop) { PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr); return nullptr; } - else { - PyErr_Format(PyExc_AttributeError, "Property '%s' is not of list type", pstr); - return nullptr; - } + + PyErr_Format(PyExc_AttributeError, "Property '%s' is not of list type", pstr); + return nullptr; } -PyObject* PropertyContainerPy::getTypeOfProperty(PyObject *args) +PyObject* PropertyContainerPy::getTypeOfProperty(PyObject* args) { Py::List ret; - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } - Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); + Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (!prop) { PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr); return nullptr; } - short Type = prop->getType(); - if (Type & Prop_ReadOnly) + short Type = prop->getType(); + if (Type & Prop_ReadOnly) { ret.append(Py::String("ReadOnly")); - if (Type & Prop_Transient) + } + if (Type & Prop_Transient) { ret.append(Py::String("Transient")); - if (Type & Prop_Hidden) + } + if (Type & Prop_Hidden) { ret.append(Py::String("Hidden")); - if (Type & Prop_Output) + } + if (Type & Prop_Output) { ret.append(Py::String("Output")); - if (Type & Prop_NoRecompute) + } + if (Type & Prop_NoRecompute) { ret.append(Py::String("NoRecompute")); - if (Type & Prop_NoPersist) + } + if (Type & Prop_NoPersist) { ret.append(Py::String("NoPersist")); + } return Py::new_reference_to(ret); } -PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject *args) +PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject* args) { - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } - Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); + Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (!prop) { PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr); return nullptr; @@ -146,10 +158,10 @@ PyObject* PropertyContainerPy::getTypeIdOfProperty(PyObject *args) return Py::new_reference_to(str); } -PyObject* PropertyContainerPy::setEditorMode(PyObject *args) +PyObject* PropertyContainerPy::setEditorMode(PyObject* args) { - char* name; - short type; + char* name {}; + short type {}; if (PyArg_ParseTuple(args, "sh", &name, &type)) { App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name); if (!prop) { @@ -166,7 +178,7 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args) } PyErr_Clear(); - PyObject *iter; + PyObject* iter {}; if (PyArg_ParseTuple(args, "sO", &name, &iter)) { if (PyTuple_Check(iter) || PyList_Check(iter)) { Py::Sequence seq(iter); @@ -180,12 +192,14 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args) std::bitset<32> status(prop->getStatus()); status.reset(Property::ReadOnly); status.reset(Property::Hidden); - for (Py::Sequence::iterator it = seq.begin();it!=seq.end();++it) { + for (Py::Sequence::iterator it = seq.begin(); it != seq.end(); ++it) { std::string str = static_cast(Py::String(*it)); - if (str == "ReadOnly") + if (str == "ReadOnly") { status.set(Property::ReadOnly); - else if (str == "Hidden") + } + else if (str == "Hidden") { status.set(Property::Hidden); + } } prop->setStatusValue(status.to_ulong()); @@ -193,13 +207,15 @@ PyObject* PropertyContainerPy::setEditorMode(PyObject *args) } } - PyErr_SetString(PyExc_TypeError, "First argument must be str, second can be int, list or tuple"); + PyErr_SetString(PyExc_TypeError, + "First argument must be str, second can be int, list or tuple"); return nullptr; } -static const std::map &getStatusMap() { - static std::map statusMap; - if(statusMap.empty()) { +static const std::map& getStatusMap() +{ + static std::map statusMap; + if (statusMap.empty()) { statusMap["Immutable"] = Property::Immutable; statusMap["ReadOnly"] = Property::ReadOnly; statusMap["Hidden"] = Property::Hidden; @@ -217,12 +233,13 @@ static const std::map &getStatusMap() { return statusMap; } -PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args) +PyObject* PropertyContainerPy::setPropertyStatus(PyObject* args) { char* name {}; PyObject* pyValue {}; - if (!PyArg_ParseTuple(args, "sO", &name, &pyValue)) + if (!PyArg_ParseTuple(args, "sO", &name, &pyValue)) { return nullptr; + } App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name); if (!prop) { @@ -247,7 +264,7 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args) for (const auto& item : items) { bool value = true; if (item.isString()) { - const auto &statusMap = getStatusMap(); + const auto& statusMap = getStatusMap(); auto v = static_cast(Py::String(item)); if (v.size() > 1 && v[0] == '-') { value = false; @@ -288,17 +305,19 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args) Py_Return; } -PyObject* PropertyContainerPy::getPropertyStatus(PyObject *args) +PyObject* PropertyContainerPy::getPropertyStatus(PyObject* args) { const char* name = ""; - if (!PyArg_ParseTuple(args, "|s", &name)) + if (!PyArg_ParseTuple(args, "|s", &name)) { return nullptr; + } Py::List ret; - const auto &statusMap = getStatusMap(); + const auto& statusMap = getStatusMap(); if (!name[0]) { - for(auto &v : statusMap) + for (auto& v : statusMap) { ret.append(Py::String(v.first.c_str())); + } } else { App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name); @@ -308,32 +327,37 @@ PyObject* PropertyContainerPy::getPropertyStatus(PyObject *args) } auto linkProp = Base::freecad_dynamic_cast(prop); - if (linkProp && linkProp->testFlag(App::PropertyLinkBase::LinkAllowPartial)) + if (linkProp && linkProp->testFlag(App::PropertyLinkBase::LinkAllowPartial)) { ret.append(Py::String("AllowPartial")); + } std::bitset<32> bits(prop->getStatus()); - for(size_t i=1; i(i)) { + for (auto& v : statusMap) { + if (v.second == static_cast(i)) { ret.append(Py::String(v.first.c_str())); found = true; break; } } - if (!found) + if (!found) { ret.append(Py::Int(static_cast(i))); + } } } return Py::new_reference_to(ret); } -PyObject* PropertyContainerPy::getEditorMode(PyObject *args) +PyObject* PropertyContainerPy::getEditorMode(PyObject* args) { - char* name; - if (!PyArg_ParseTuple(args, "s", &name)) + char* name {}; + if (!PyArg_ParseTuple(args, "s", &name)) { return nullptr; + } App::Property* prop = getPropertyContainerPtr()->getPropertyByName(name); if (!prop) { @@ -343,20 +367,23 @@ PyObject* PropertyContainerPy::getEditorMode(PyObject *args) Py::List ret; if (prop) { - short Type = prop->getType(); - if ((prop->testStatus(Property::ReadOnly)) || (Type & Prop_ReadOnly)) + short Type = prop->getType(); + if ((prop->testStatus(Property::ReadOnly)) || (Type & Prop_ReadOnly)) { ret.append(Py::String("ReadOnly")); - if ((prop->testStatus(Property::Hidden)) || (Type & Prop_Hidden)) + } + if ((prop->testStatus(Property::Hidden)) || (Type & Prop_Hidden)) { ret.append(Py::String("Hidden")); + } } return Py::new_reference_to(ret); } -PyObject* PropertyContainerPy::getGroupOfProperty(PyObject *args) +PyObject* PropertyContainerPy::getGroupOfProperty(PyObject* args) { - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (!prop) { @@ -365,37 +392,44 @@ PyObject* PropertyContainerPy::getGroupOfProperty(PyObject *args) } const char* Group = getPropertyContainerPtr()->getPropertyGroup(prop); - if (Group) + if (Group) { return Py::new_reference_to(Py::String(Group)); - else + } + else { return Py::new_reference_to(Py::String("")); + } } -PyObject* PropertyContainerPy::setGroupOfProperty(PyObject *args) +PyObject* PropertyContainerPy::setGroupOfProperty(PyObject* args) { - char *pstr; - char *group; - if (!PyArg_ParseTuple(args, "ss", &pstr, &group)) + char* pstr {}; + char* group {}; + if (!PyArg_ParseTuple(args, "ss", &pstr, &group)) { return nullptr; + } - PY_TRY { + PY_TRY + { Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr); if (!prop) { - PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr); + PyErr_Format(PyExc_AttributeError, + "Property container has no dynamic property '%s'", + pstr); return nullptr; } - prop->getContainer()->changeDynamicProperty(prop,group,nullptr); + prop->getContainer()->changeDynamicProperty(prop, group, nullptr); Py_Return; } PY_CATCH } -PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args) +PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject* args) { - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (!prop) { @@ -404,36 +438,43 @@ PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args) } const char* docstr = getPropertyContainerPtr()->getPropertyDocumentation(prop); - if (docstr) + if (docstr) { return Py::new_reference_to(Py::String(docstr)); - else + } + else { return Py::new_reference_to(Py::String("")); + } } -PyObject* PropertyContainerPy::setDocumentationOfProperty(PyObject *args) +PyObject* PropertyContainerPy::setDocumentationOfProperty(PyObject* args) { - char *pstr; - char *doc; - if (!PyArg_ParseTuple(args, "ss", &pstr, &doc)) + char* pstr {}; + char* doc {}; + if (!PyArg_ParseTuple(args, "ss", &pstr, &doc)) { return nullptr; + } - PY_TRY { + PY_TRY + { Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr); if (!prop) { - PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr); + PyErr_Format(PyExc_AttributeError, + "Property container has no dynamic property '%s'", + pstr); return nullptr; } - prop->getContainer()->changeDynamicProperty(prop,nullptr,doc); + prop->getContainer()->changeDynamicProperty(prop, nullptr, doc); Py_Return; } PY_CATCH } -PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args) +PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject* args) { - char *pstr; - if (!PyArg_ParseTuple(args, "s", &pstr)) + char* pstr {}; + if (!PyArg_ParseTuple(args, "s", &pstr)) { return nullptr; + } Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); if (!prop) { @@ -441,13 +482,14 @@ PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args) return nullptr; } - PropertyEnumeration *enumProp = dynamic_cast(prop); - if (!enumProp) + PropertyEnumeration* enumProp = dynamic_cast(prop); + if (!enumProp) { Py_Return; + } std::vector enumerations = enumProp->getEnumVector(); Py::List ret; - for (const auto & it : enumerations) { + for (const auto& it : enumerations) { ret.append(Py::String(it)); } return Py::new_reference_to(ret); @@ -456,24 +498,30 @@ PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args) Py::List PropertyContainerPy::getPropertiesList() const { Py::List ret; - std::map Map; + std::map Map; getPropertyContainerPtr()->getPropertyMap(Map); - for (std::map::const_iterator It=Map.begin(); It!=Map.end(); ++It) - ret.append(Py::String(It->first)); + for (const auto& It : Map) { + ret.append(Py::String(It.first)); + } return ret; } -PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwds) +PyObject* PropertyContainerPy::dumpPropertyContent(PyObject* args, PyObject* kwds) { int compression = 3; - const char* property; - static const std::array kwds_def {"Property", "Compression", nullptr}; + const char* property {}; + static const std::array kwds_def {"Property", "Compression", nullptr}; PyErr_Clear(); - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "s|i", kwds_def, &property, &compression)) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "s|i", + kwds_def, + &property, + &compression)) { return nullptr; } @@ -483,35 +531,36 @@ PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwd return nullptr; } - //setup the stream. the in flag is needed to make "read" work - std::stringstream stream(std::stringstream::out | std::stringstream::in | std::stringstream::binary); + // setup the stream. the in flag is needed to make "read" work + std::stringstream stream(std::stringstream::out | std::stringstream::in + | std::stringstream::binary); try { prop->dumpToStream(stream, compression); } catch (...) { - PyErr_SetString(PyExc_IOError, "Unable to parse content into binary representation"); - return nullptr; + PyErr_SetString(PyExc_IOError, "Unable to parse content into binary representation"); + return nullptr; } - //build the byte array with correct size - if (!stream.seekp(0, stream.end)) { + // build the byte array with correct size + if (!stream.seekp(0, std::stringstream::end)) { PyErr_SetString(PyExc_IOError, "Unable to find end of stream"); return nullptr; } std::stringstream::pos_type offset = stream.tellp(); - if (!stream.seekg(0, stream.beg)) { + if (!stream.seekg(0, std::stringstream::beg)) { PyErr_SetString(PyExc_IOError, "Unable to find begin of stream"); return nullptr; } PyObject* ba = PyByteArray_FromStringAndSize(nullptr, offset); - //use the buffer protocol to access the underlying array and write into it + // use the buffer protocol to access the underlying array and write into it Py_buffer buf = Py_buffer(); PyObject_GetBuffer(ba, &buf, PyBUF_WRITABLE); try { - if(!stream.read((char*)buf.buf, offset)) { + if (!stream.read((char*)buf.buf, offset)) { PyErr_SetString(PyExc_IOError, "Error copying data into byte array"); return nullptr; } @@ -526,12 +575,13 @@ PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwd return ba; } -PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args) +PyObject* PropertyContainerPy::restorePropertyContent(PyObject* args) { - PyObject* buffer; - char* property; - if( !PyArg_ParseTuple(args, "sO", &property, &buffer) ) + PyObject* buffer {}; + char* property {}; + if (!PyArg_ParseTuple(args, "sO", &property, &buffer)) { return nullptr; + } Property* prop = getPropertyContainerPtr()->getPropertyByName(property); if (!prop) { @@ -539,28 +589,29 @@ PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args) return nullptr; } - //check if it really is a buffer - if( !PyObject_CheckBuffer(buffer) ) { + // check if it really is a buffer + if (!PyObject_CheckBuffer(buffer)) { PyErr_SetString(PyExc_TypeError, "Must be a buffer object"); return nullptr; } Py_buffer buf; - if(PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0) + if (PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0) { return nullptr; + } - if(!PyBuffer_IsContiguous(&buf, 'C')) { + if (!PyBuffer_IsContiguous(&buf, 'C')) { PyErr_SetString(PyExc_TypeError, "Buffer must be contiguous"); return nullptr; } - //check if it really is a buffer + // check if it really is a buffer try { using Device = boost::iostreams::basic_array_source; boost::iostreams::stream stream((char*)buf.buf, buf.len); prop->restoreFromStream(stream); } - catch(...) { + catch (...) { PyErr_SetString(PyExc_IOError, "Unable to restore content"); return nullptr; } @@ -568,13 +619,13 @@ PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args) Py_Return; } -PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const +PyObject* PropertyContainerPy::getCustomAttributes(const char* attr) const { // search in PropertyList - if(FC_LOG_INSTANCE.level()>FC_LOGLEVEL_TRACE) { + if (FC_LOG_INSTANCE.level() > FC_LOGLEVEL_TRACE) { FC_TRACE("Get property " << attr); } - Property *prop = getPropertyContainerPtr()->getPropertyByName(attr); + Property* prop = getPropertyContainerPtr()->getPropertyByName(attr); if (prop) { PyObject* pyobj = prop->getPyObject(); if (!pyobj && PyErr_Occurred()) { @@ -583,44 +634,49 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const } return pyobj; } - else if (Base::streq(attr, "__dict__")) { + if (Base::streq(attr, "__dict__")) { // get the properties to the C++ PropertyContainer class - std::map Map; + std::map Map; getPropertyContainerPtr()->getPropertyMap(Map); Py::Dict dict; - for (const auto & it : Map) { + for (const auto& it : Map) { dict.setItem(it.first, Py::String("")); } return Py::new_reference_to(dict); } - ///FIXME: For v0.20: Do not use stuff from Part module here! - else if(Base::streq(attr,"Shape") && getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + /// FIXME: For v0.20: Do not use stuff from Part module here! + if (Base::streq(attr, "Shape") + && getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { // Special treatment of Shape property - static PyObject *_getShape = nullptr; - if(!_getShape) { + static PyObject* _getShape = nullptr; + if (!_getShape) { _getShape = Py_None; - PyObject *mod = PyImport_ImportModule("Part"); - if(!mod) { + PyObject* mod = PyImport_ImportModule("Part"); + if (!mod) { PyErr_Clear(); - } else { + } + else { Py::Object pyMod = Py::asObject(mod); - if(pyMod.hasAttr("getShape")) + if (pyMod.hasAttr("getShape")) { _getShape = Py::new_reference_to(pyMod.getAttr("getShape")); + } } } - if(_getShape != Py_None) { + if (_getShape != Py_None) { Py::Tuple args(1); - args.setItem(0,Py::Object(const_cast(this))); + args.setItem(0, Py::Object(const_cast(this))); auto res = PyObject_CallObject(_getShape, args.ptr()); - if(!res) + if (!res) { PyErr_Clear(); + } else { - Py::Object pyres(res,true); - if(pyres.hasAttr("isNull")) { + Py::Object pyres(res, true); + if (pyres.hasAttr("isNull")) { Py::Callable func(pyres.getAttr("isNull")); - if(!func.apply().isTrue()) + if (!func.apply().isTrue()) { return Py::new_reference_to(res); + } } } } @@ -629,13 +685,13 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const return nullptr; } -int PropertyContainerPy::setCustomAttributes(const char* attr, PyObject *obj) +int PropertyContainerPy::setCustomAttributes(const char* attr, PyObject* obj) { // search in PropertyList - Property *prop = getPropertyContainerPtr()->getPropertyByName(attr); + Property* prop = getPropertyContainerPtr()->getPropertyByName(attr); if (prop) { // Read-only attributes must not be set over its Python interface - if(prop->testStatus(Property::Immutable)) { + if (prop->testStatus(Property::Immutable)) { std::stringstream s; s << "Object attribute '" << attr << "' is read-only"; throw Py::AttributeError(s.str()); diff --git a/src/App/PropertyExpressionEngine.cpp b/src/App/PropertyExpressionEngine.cpp index 63fd2c40fbe7..7bc7182ee59e 100644 --- a/src/App/PropertyExpressionEngine.cpp +++ b/src/App/PropertyExpressionEngine.cpp @@ -42,46 +42,52 @@ using namespace Base; using namespace boost; namespace sp = std::placeholders; -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyExpressionContainer , App::PropertyXLinkContainer) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyExpressionContainer, App::PropertyXLinkContainer) static std::set _ExprContainers; -PropertyExpressionContainer::PropertyExpressionContainer() { +PropertyExpressionContainer::PropertyExpressionContainer() +{ static bool inited; - if(!inited) { + if (!inited) { inited = true; - GetApplication().signalRelabelDocument.connect(PropertyExpressionContainer::slotRelabelDocument); + GetApplication().signalRelabelDocument.connect( + PropertyExpressionContainer::slotRelabelDocument); } _ExprContainers.insert(this); } -PropertyExpressionContainer::~PropertyExpressionContainer() { +PropertyExpressionContainer::~PropertyExpressionContainer() +{ _ExprContainers.erase(this); } -void PropertyExpressionContainer::slotRelabelDocument(const App::Document &doc) { +void PropertyExpressionContainer::slotRelabelDocument(const App::Document& doc) +{ // For use a private _ExprContainers to track all living // PropertyExpressionContainer including those inside undo/redo stack, // because document relabel is not undoable/redoable. - if(doc.getOldLabel() != doc.Label.getValue()) { - for(auto prop : _ExprContainers) + if (doc.getOldLabel() != doc.Label.getValue()) { + for (auto prop : _ExprContainers) { prop->onRelabeledDocument(doc); + } } } /////////////////////////////////////////////////////////////////////////////////////// -struct PropertyExpressionEngine::Private { +struct PropertyExpressionEngine::Private +{ // For some reason, MSVC has trouble with vector of scoped_connection if // defined in header, hence the private structure here. std::vector conns; - std::unordered_map > propMap; + std::unordered_map> propMap; }; /////////////////////////////////////////////////////////////////////////////////////// -TYPESYSTEM_SOURCE(App::PropertyExpressionEngine , App::PropertyExpressionContainer) +TYPESYSTEM_SOURCE(App::PropertyExpressionEngine, App::PropertyExpressionContainer) /** * @brief Construct a new PropertyExpressionEngine object. @@ -89,8 +95,7 @@ TYPESYSTEM_SOURCE(App::PropertyExpressionEngine , App::PropertyExpressionContain PropertyExpressionEngine::PropertyExpressionEngine() : validator(0) -{ -} +{} /** * @brief Destroy the PropertyExpressionEngine object. @@ -111,14 +116,15 @@ unsigned int PropertyExpressionEngine::getMemSize() const return 0; } -Property *PropertyExpressionEngine::Copy() const +Property* PropertyExpressionEngine::Copy() const { - PropertyExpressionEngine * engine = new PropertyExpressionEngine(); + PropertyExpressionEngine* engine = new PropertyExpressionEngine(); - for (const auto & it : expressions) { + for (const auto& it : expressions) { ExpressionInfo info; - if (it.second.expression) + if (it.second.expression) { info.expression = std::shared_ptr(it.second.expression->copy()); + } engine->expressions[it.first] = info; } @@ -129,68 +135,79 @@ Property *PropertyExpressionEngine::Copy() const void PropertyExpressionEngine::hasSetValue() { - App::DocumentObject *owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument() || owner->isRestoring() || testFlag(LinkDetached)) { + App::DocumentObject* owner = dynamic_cast(getContainer()); + if (!owner || !owner->isAttachedToDocument() || owner->isRestoring() + || testFlag(LinkDetached)) { PropertyExpressionContainer::hasSetValue(); return; } - std::map deps; + std::map deps; std::vector labels; unregisterElementReference(); UpdateElementReferenceExpressionVisitor v(*this); - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(expr) { - expr->getDepObjects(deps,&labels); - if(!restoring) + if (expr) { + expr->getDepObjects(deps, &labels); + if (!restoring) { expr->visit(v); + } } } registerLabelReferences(std::move(labels)); updateDeps(std::move(deps)); - if(pimpl) { + if (pimpl) { pimpl->conns.clear(); pimpl->propMap.clear(); } // check if there is any hidden references bool hasHidden = false; - for(auto &v : _Deps) { - if(v.second) { + for (auto& v : _Deps) { + if (v.second) { hasHidden = true; break; } } - if(hasHidden) { - if(!pimpl) { + if (hasHidden) { + if (!pimpl) { pimpl = std::make_unique(); } - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(!expr) continue; - for(auto &dep : expr->getIdentifiers()) { - if(!dep.second) + if (!expr) { + continue; + } + for (auto& dep : expr->getIdentifiers()) { + if (!dep.second) { continue; - const ObjectIdentifier &var = dep.first; - for(auto &vdep : var.getDep(true)) { + } + const ObjectIdentifier& var = dep.first; + for (auto& vdep : var.getDep(true)) { auto obj = vdep.first; auto objName = obj->getFullName() + "."; - for(auto &propName : vdep.second) { + for (auto& propName : vdep.second) { std::string key = objName + propName; - auto &propDeps = pimpl->propMap[key]; - if(propDeps.empty()) { - //NOLINTBEGIN - if(!propName.empty()) { - pimpl->conns.emplace_back(obj->signalChanged.connect(std::bind( - &PropertyExpressionEngine::slotChangedProperty,this,sp::_1,sp::_2))); + auto& propDeps = pimpl->propMap[key]; + if (propDeps.empty()) { + // NOLINTBEGIN + if (!propName.empty()) { + pimpl->conns.emplace_back(obj->signalChanged.connect( + std::bind(&PropertyExpressionEngine::slotChangedProperty, + this, + sp::_1, + sp::_2))); } else { - pimpl->conns.emplace_back(obj->signalChanged.connect(std::bind( - &PropertyExpressionEngine::slotChangedObject,this,sp::_1,sp::_2))); + pimpl->conns.emplace_back(obj->signalChanged.connect( + std::bind(&PropertyExpressionEngine::slotChangedObject, + this, + sp::_1, + sp::_2))); } - //NOLINTEND + // NOLINTEND } propDeps.push_back(e.first); } @@ -202,60 +219,73 @@ void PropertyExpressionEngine::hasSetValue() PropertyExpressionContainer::hasSetValue(); } -void PropertyExpressionEngine::updateHiddenReference(const std::string &key) { - if(!pimpl) +void PropertyExpressionEngine::updateHiddenReference(const std::string& key) +{ + if (!pimpl) { return; + } auto it = pimpl->propMap.find(key); - if(it == pimpl->propMap.end()) + if (it == pimpl->propMap.end()) { return; - for(auto &var : it->second) { + } + for (auto& var : it->second) { auto it = expressions.find(var); - if(it == expressions.end() || it->second.busy) + if (it == expressions.end() || it->second.busy) { continue; - Property *myProp = var.getProperty(); - if(!myProp) + } + Property* myProp = var.getProperty(); + if (!myProp) { continue; + } Base::StateLocker guard(it->second.busy); App::any value; try { value = it->second.expression->getValueAsAny(); - if(!isAnyEqual(value, myProp->getPathValue(var))) + if (!isAnyEqual(value, myProp->getPathValue(var))) { myProp->setPathValue(var, value); - }catch(Base::Exception &e) { + } + } + catch (Base::Exception& e) { e.ReportException(); - FC_ERR("Failed to evaluate property binding " - << myProp->getFullName() << " on change of " << key); - }catch(std::bad_cast &) { - FC_ERR("Invalid type '" << value.type().name() - << "' in property binding " << myProp->getFullName() - << " on change of " << key); - }catch(std::exception &e) { + FC_ERR("Failed to evaluate property binding " << myProp->getFullName() + << " on change of " << key); + } + catch (std::bad_cast&) { + FC_ERR("Invalid type '" << value.type().name() << "' in property binding " + << myProp->getFullName() << " on change of " << key); + } + catch (std::exception& e) { FC_ERR(e.what()); - FC_ERR("Failed to evaluate property binding " - << myProp->getFullName() << " on change of " << key); + FC_ERR("Failed to evaluate property binding " << myProp->getFullName() + << " on change of " << key); } } } -void PropertyExpressionEngine::slotChangedObject(const App::DocumentObject &obj, const App::Property &) { +void PropertyExpressionEngine::slotChangedObject(const App::DocumentObject& obj, + const App::Property&) +{ updateHiddenReference(obj.getFullName()); } -void PropertyExpressionEngine::slotChangedProperty(const App::DocumentObject &, const App::Property &prop) { +void PropertyExpressionEngine::slotChangedProperty(const App::DocumentObject&, + const App::Property& prop) +{ updateHiddenReference(prop.getFullName()); } -void PropertyExpressionEngine::Paste(const Property &from) +void PropertyExpressionEngine::Paste(const Property& from) { - const PropertyExpressionEngine &fromee = dynamic_cast(from); + const PropertyExpressionEngine& fromee = dynamic_cast(from); AtomicPropertyChange signaller(*this); expressions.clear(); - for(auto &e : fromee.expressions) { + for (auto& e : fromee.expressions) { ExpressionInfo info; - if (e.second.expression) + if (e.second.expression) { info.expression = std::shared_ptr(e.second.expression->copy()); + } expressions[e.first] = info; expressionChanged(e.first); } @@ -263,18 +293,19 @@ void PropertyExpressionEngine::Paste(const Property &from) signaller.tryInvoke(); } -void PropertyExpressionEngine::Save(Base::Writer &writer) const +void PropertyExpressionEngine::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); - } else { + } + else { writer.Stream() << R"(" xlink="1">)" << std::endl; writer.incInd(); PropertyExpressionContainer::Save(writer); } - for (const auto & it : expressions) { + for (const auto& it : expressions) { std::string expression, comment; if (it.second.expression) { expression = it.second.expression->toString(true); @@ -282,24 +313,25 @@ void PropertyExpressionEngine::Save(Base::Writer &writer) const } writer.Stream() << writer.ind() << "" << std::endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyExpressionEngine::Restore(Base::XMLReader &reader) +void PropertyExpressionEngine::Restore(Base::XMLReader& reader) { reader.readElement("ExpressionEngine"); int count = reader.getAttributeAsFloat("count"); - if(reader.hasAttribute("xlink") && reader.getAttributeAsInteger("xlink")) + if (reader.hasAttribute("xlink") && reader.getAttributeAsInteger("xlink")) { PropertyExpressionContainer::Restore(reader); + } restoredExpressions = std::make_unique>(); restoredExpressions->reserve(count); @@ -307,11 +339,12 @@ void PropertyExpressionEngine::Restore(Base::XMLReader &reader) reader.readElement("Expression"); restoredExpressions->emplace_back(); - auto &info = restoredExpressions->back(); + auto& info = restoredExpressions->back(); info.path = reader.getAttribute("path"); info.expr = reader.getAttribute("expression"); - if(reader.hasAttribute("comment")) + if (reader.hasAttribute("comment")) { info.comment = reader.getAttribute("comment"); + } } reader.readEndElement("ExpressionEngine"); @@ -326,11 +359,12 @@ void PropertyExpressionEngine::Restore(Base::XMLReader &reader) * @param edges Edges in graph */ -void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & path, - const std::shared_ptr expression, - boost::unordered_map & nodes, - boost::unordered_map & revNodes, - std::vector & edges) const +void PropertyExpressionEngine::buildGraphStructures( + const ObjectIdentifier& path, + const std::shared_ptr expression, + boost::unordered_map& nodes, + boost::unordered_map& revNodes, + std::vector& edges) const { /* Insert target property into nodes structure */ if (nodes.find(path) == nodes.end()) { @@ -345,14 +379,16 @@ void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & pat /* Insert dependencies into nodes structure */ ExpressionDeps deps; - if (expression) + if (expression) { deps = expression->getDeps(); + } - for(auto &dep : deps) { - for(auto &info : dep.second) { - if(info.first.empty()) + for (auto& dep : deps) { + for (auto& info : dep.second) { + if (info.first.empty()) { continue; - for(auto &oid : info.second) { + } + for (auto& oid : info.second) { ObjectIdentifier cPath(oid.canonicalPath()); if (nodes.find(cPath) == nodes.end()) { int s = nodes.size(); @@ -370,27 +406,31 @@ void PropertyExpressionEngine::buildGraphStructures(const ObjectIdentifier & pat * @return New ObjectIdentifier */ -ObjectIdentifier PropertyExpressionEngine::canonicalPath(const ObjectIdentifier &p) const +ObjectIdentifier PropertyExpressionEngine::canonicalPath(const ObjectIdentifier& p) const { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); // Am I owned by a DocumentObject? - if (!docObj) + if (!docObj) { throw Base::RuntimeError("PropertyExpressionEngine must be owned by a DocumentObject."); + } int ptype; - Property * prop = p.getProperty(&ptype); + Property* prop = p.getProperty(&ptype); // p pointing to a property...? - if (!prop) + if (!prop) { throw Base::RuntimeError(p.resolveErrorString().c_str()); + } - if(ptype || prop->getContainer()!=getContainer()) + if (ptype || prop->getContainer() != getContainer()) { return p; + } // In case someone calls this with p pointing to a PropertyExpressionEngine for some reason - if (prop->isDerivedFrom(PropertyExpressionEngine::classTypeId)) + if (prop->isDerivedFrom(PropertyExpressionEngine::classTypeId)) { return p; + } // Dispatch call to actual canonicalPath implementation return p.canonicalPath(); @@ -408,20 +448,22 @@ size_t PropertyExpressionEngine::numExpressions() const void PropertyExpressionEngine::afterRestore() { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); - if(restoredExpressions && docObj) { + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); + if (restoredExpressions && docObj) { Base::FlagToggler flag(restoring); AtomicPropertyChange signaller(*this); PropertyExpressionContainer::afterRestore(); ObjectIdentifier::DocumentMapper mapper(this->_DocMap); - for(auto &info : *restoredExpressions) { + for (auto& info : *restoredExpressions) { ObjectIdentifier path = ObjectIdentifier::parse(docObj, info.path); if (!info.expr.empty()) { - std::shared_ptr expression(Expression::parse(docObj, info.expr.c_str())); - if(expression) + std::shared_ptr expression( + Expression::parse(docObj, info.expr.c_str())); + if (expression) { expression->comment = std::move(info.comment); + } setValue(path, expression); } } @@ -430,14 +472,16 @@ void PropertyExpressionEngine::afterRestore() restoredExpressions.reset(); } -void PropertyExpressionEngine::onContainerRestored() { +void PropertyExpressionEngine::onContainerRestored() +{ Base::FlagToggler flag(restoring); unregisterElementReference(); UpdateElementReferenceExpressionVisitor v(*this); - for(auto &e : expressions) { + for (auto& e : expressions) { auto expr = e.second.expression; - if(expr) + if (expr) { expr->visit(v); + } } } @@ -447,17 +491,17 @@ void PropertyExpressionEngine::onContainerRestored() { * @return Expression for \a path, or empty boost::any if not found. */ -const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentifier & path) const +const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentifier& path) const { // Get a canonical path ObjectIdentifier usePath(canonicalPath(path)); - ExpressionMap::const_iterator i = expressions.find(usePath); - - if (i != expressions.end()) + auto i = expressions.find(usePath); + if (i != expressions.end()) { return i->second; - else - return boost::any(); + } + + return boost::any(); } /** @@ -467,33 +511,36 @@ const boost::any PropertyExpressionEngine::getPathValue(const App::ObjectIdentif * @param comment Optional comment. */ -void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, std::shared_ptr expr) +void PropertyExpressionEngine::setValue(const ObjectIdentifier& path, + std::shared_ptr expr) { ObjectIdentifier usePath(canonicalPath(path)); - const Property * prop = usePath.getProperty(); + const Property* prop = usePath.getProperty(); - // Try to access value; it should trigger an exception if it is not supported, or if the path is invalid + // Try to access value; it should trigger an exception if it is not supported, or if the path is + // invalid prop->getPathValue(usePath); - // Check if the current expression equals the new one and do nothing if so to reduce unneeded computations - ExpressionMap::iterator it = expressions.find(usePath); - if(it != expressions.end() - && (expr == it->second.expression || - (expr && it->second.expression - && expr->isSame(*it->second.expression)))) - { + // Check if the current expression equals the new one and do nothing if so to reduce unneeded + // computations + auto it = expressions.find(usePath); + if (it != expressions.end() + && (expr == it->second.expression + || (expr && it->second.expression && expr->isSame(*it->second.expression)))) { return; } if (expr) { std::string error = validateExpression(usePath, expr); - if (!error.empty()) + if (!error.empty()) { throw Base::RuntimeError(error.c_str()); + } AtomicPropertyChange signaller(*this); expressions[usePath] = ExpressionInfo(expr); expressionChanged(usePath); signaller.tryInvoke(); - } else if (it != expressions.end()) { + } + else if (it != expressions.end()) { AtomicPropertyChange signaller(*this); expressions.erase(it); expressionChanged(usePath); @@ -502,52 +549,63 @@ void PropertyExpressionEngine::setValue(const ObjectIdentifier & path, std::shar } /** - * @brief The cycle_detector struct is used by the boost graph routines to detect cycles in the graph. + * @brief The cycle_detector struct is used by the boost graph routines to detect cycles in the + * graph. */ -struct cycle_detector : public boost::dfs_visitor<> { - cycle_detector( bool& has_cycle, int & src) - : _has_cycle(has_cycle), _src(src) { } +struct cycle_detector: public boost::dfs_visitor<> +{ + cycle_detector(bool& has_cycle, int& src) + : _has_cycle(has_cycle) + , _src(src) + {} - template - void back_edge(Edge e, Graph&g) { - _has_cycle = true; - _src = source(e, g); + template + void back_edge(Edge e, Graph& g) + { + _has_cycle = true; + _src = source(e, g); } - protected: +protected: bool& _has_cycle; - int & _src; + int& _src; }; /** * @brief Build a graph of all expressions in \a exprs. * @param exprs Expressions to use in graph * @param revNodes Map from int[nodeid] to ObjectIndentifer. - * @param g Graph to update. May contain additional nodes than in revNodes, because of outside dependencies. + * @param g Graph to update. May contain additional nodes than in revNodes, because of outside + * dependencies. */ -void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, - boost::unordered_map & revNodes, - DiGraph & g, ExecuteOption option) const +void PropertyExpressionEngine::buildGraph(const ExpressionMap& exprs, + boost::unordered_map& revNodes, + DiGraph& g, + ExecuteOption option) const { boost::unordered_map nodes; std::vector edges; // Build data structure for graph - for (const auto & expr : exprs) { - if(option!=ExecuteAll) { + for (const auto& expr : exprs) { + if (option != ExecuteAll) { auto prop = expr.first.getProperty(); - if(!prop) + if (!prop) { throw Base::RuntimeError("Path does not resolve to a property."); - bool is_output = prop->testStatus(App::Property::Output)||(prop->getType()&App::Prop_Output); - if((is_output && option==ExecuteNonOutput) || (!is_output && option==ExecuteOutput)) + } + bool is_output = + prop->testStatus(App::Property::Output) || (prop->getType() & App::Prop_Output); + if ((is_output && option == ExecuteNonOutput) + || (!is_output && option == ExecuteOutput)) { continue; - if(option == ExecuteOnRestore - && !prop->testStatus(Property::Transient) - && !(prop->getType() & Prop_Transient) - && !prop->testStatus(Property::EvalOnRestore)) + } + if (option == ExecuteOnRestore && !prop->testStatus(Property::Transient) + && !(prop->getType() & Prop_Transient) + && !prop->testStatus(Property::EvalOnRestore)) { continue; + } } buildGraphStructures(expr.first, expr.second.expression, nodes, revNodes, edges); } @@ -556,8 +614,9 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, g = DiGraph(nodes.size()); // Add edges to graph - for (const auto & edge : edges) + for (const auto& edge : edges) { add_edge(edge.first, edge.second, g); + } // Check for cycles bool has_cycle = false; @@ -566,7 +625,7 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, depth_first_search(g, visitor(vis)); if (has_cycle) { - std::string s = revNodes[src].toString() + " reference creates a cyclic dependency."; + std::string s = revNodes[src].toString() + " reference creates a cyclic dependency."; throw Base::RuntimeError(s.c_str()); } @@ -578,7 +637,8 @@ void PropertyExpressionEngine::buildGraph(const ExpressionMap & exprs, * order, in case properties depends on each other. */ -std::vector PropertyExpressionEngine::computeEvaluationOrder(ExecuteOption option) +std::vector +PropertyExpressionEngine::computeEvaluationOrder(ExecuteOption option) { std::vector evaluationOrder; boost::unordered_map revNodes; @@ -593,8 +653,9 @@ std::vector PropertyExpressionEngine::computeEvaluationOr for (int i : c) { // we return the evaluation order for our properties, not the dependencies // the topo sort will contain node ids for both our props and their deps - if (revNodes.find(i) != revNodes.end()) + if (revNodes.find(i) != revNodes.end()) { evaluationOrder.push_back(revNodes[i]); + } } return evaluationOrder; @@ -605,45 +666,57 @@ std::vector PropertyExpressionEngine::computeEvaluationOr * @return StdReturn on success. */ -DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption option, bool *touched) +DocumentObjectExecReturn* App::PropertyExpressionEngine::execute(ExecuteOption option, + bool* touched) { - DocumentObject * docObj = freecad_dynamic_cast(getContainer()); + DocumentObject* docObj = freecad_dynamic_cast(getContainer()); - if (!docObj) + if (!docObj) { throw Base::RuntimeError("PropertyExpressionEngine must be owned by a DocumentObject."); + } - if (running) + if (running) { return DocumentObject::StdReturn; + } - if(option == ExecuteOnRestore) { + if (option == ExecuteOnRestore) { bool found = false; - for(auto &e : expressions) { + for (auto& e : expressions) { auto prop = e.first.getProperty(); - if(!prop) + if (!prop) { continue; - if(prop->testStatus(App::Property::Transient) - || (prop->getType()&App::Prop_Transient) - || prop->testStatus(App::Property::EvalOnRestore)) - { + } + if (prop->testStatus(App::Property::Transient) + || (prop->getType() & App::Prop_Transient) + || prop->testStatus(App::Property::EvalOnRestore)) { found = true; break; } } - if(!found) + if (!found) { return DocumentObject::StdReturn; + } } /* Resetter class, to ensure that the "running" variable gets set to false, even if * an exception is thrown. */ - class resetter { + class resetter + { public: - explicit resetter(bool & b) : _b(b) { _b = true; } - ~resetter() { _b = false; } + explicit resetter(bool& b) + : _b(b) + { + _b = true; + } + ~resetter() + { + _b = false; + } private: - bool & _b; + bool& _b; }; resetter r(running); @@ -657,19 +730,21 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o #endif /* Evaluate the expressions, and update properties */ - for (;it != evaluationOrder.end();++it) { + for (; it != evaluationOrder.end(); ++it) { // Get property to update - Property * prop = it->getProperty(); + Property* prop = it->getProperty(); - if (!prop) + if (!prop) { throw Base::RuntimeError("Path does not resolve to a property."); + } DocumentObject* parent = freecad_dynamic_cast(prop->getContainer()); /* Make sure property belongs to the same container as this PropertyExpressionEngine */ - if (parent != docObj) + if (parent != docObj) { throw Base::RuntimeError("Invalid property owner."); + } /* Set value of property */ App::any value; @@ -692,24 +767,29 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o // // if (option == ExecuteOnRestore && prop->testStatus(Property::EvalOnRestore)) { - if (isAnyEqual(value, prop->getPathValue(*it))) + if (isAnyEqual(value, prop->getPathValue(*it))) { continue; - if (touched) + } + if (touched) { *touched = true; + } } prop->setPathValue(*it, value); } - }catch(Base::Exception &e) { + } + catch (Base::Exception& e) { std::ostringstream ss; ss << e.what() << std::endl << "in property binding '" << prop->getFullName() << "'"; e.setMessage(ss.str()); throw; - }catch(std::bad_cast &) { + } + catch (std::bad_cast&) { std::ostringstream ss; ss << "Invalid type '" << value.type().name() << "'"; ss << "\nin property binding '" << prop->getFullName() << "'"; throw Base::TypeError(ss.str().c_str()); - }catch(std::exception &e) { + } + catch (std::exception& e) { std::ostringstream ss; ss << e.what() << "\nin property binding '" << prop->getFullName() << "'"; throw Base::RuntimeError(ss.str().c_str()); @@ -724,23 +804,28 @@ DocumentObjectExecReturn *App::PropertyExpressionEngine::execute(ExecuteOption o * @param paths Object identifier */ -void PropertyExpressionEngine::getPathsToDocumentObject(DocumentObject* obj, - std::vector & paths) const +void PropertyExpressionEngine::getPathsToDocumentObject( + DocumentObject* obj, + std::vector& paths) const { - DocumentObject * owner = freecad_dynamic_cast(getContainer()); + DocumentObject* owner = freecad_dynamic_cast(getContainer()); - if (!owner || owner==obj) + if (!owner || owner == obj) { return; + } - for(auto &v : expressions) { - if (!v.second.expression) + for (auto& v : expressions) { + if (!v.second.expression) { continue; - const auto &deps = v.second.expression->getDeps(); + } + const auto& deps = v.second.expression->getDeps(); auto it = deps.find(obj); - if(it==deps.end()) + if (it == deps.end()) { continue; - for(auto &dep : it->second) - paths.insert(paths.end(),dep.second.begin(),dep.second.end()); + } + for (auto& dep : it->second) { + paths.insert(paths.end(), dep.second.begin(), dep.second.end()); + } } } @@ -751,10 +836,11 @@ void PropertyExpressionEngine::getPathsToDocumentObject(DocumentObject* obj, bool PropertyExpressionEngine::depsAreTouched() const { - for(auto &v : _Deps) { + for (auto& v : _Deps) { // v.second indicates if it is a hidden reference - if(!v.second && v.first->isTouched()) + if (!v.second && v.first->isTouched()) { return true; + } } return false; } @@ -766,25 +852,28 @@ bool PropertyExpressionEngine::depsAreTouched() const * @return Empty string on success, error message on failure. */ -std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier &path, std::shared_ptr expr) const +std::string +PropertyExpressionEngine::validateExpression(const ObjectIdentifier& path, + std::shared_ptr expr) const { std::string error; ObjectIdentifier usePath(canonicalPath(path)); if (validator) { error = validator(usePath, expr); - if (!error.empty()) + if (!error.empty()) { return error; + } } // Get document object - DocumentObject * pathDocObj = usePath.getDocumentObject(); + DocumentObject* pathDocObj = usePath.getDocumentObject(); assert(pathDocObj); auto inList = pathDocObj->getInListEx(true); - for(auto &v : expr->getDepObjects()) { + for (auto& v : expr->getDepObjects()) { auto docObj = v.first; - if(!v.second && inList.count(docObj)) { + if (!v.second && inList.count(docObj)) { std::stringstream ss; ss << "cyclic reference to " << docObj->getFullName(); return ss.str(); @@ -807,7 +896,7 @@ std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier buildGraph(newExpressions, revNodes, g); } - catch (const Base::Exception & e) { + catch (const Base::Exception& e) { return e.what(); } @@ -819,29 +908,34 @@ std::string PropertyExpressionEngine::validateExpression(const ObjectIdentifier * @param paths Map with current and new object identifier. */ -void PropertyExpressionEngine::renameExpressions(const std::map & paths) +void PropertyExpressionEngine::renameExpressions( + const std::map& paths) { ExpressionMap newExpressions; std::map canonicalPaths; /* ensure input map uses canonical paths */ - for (const auto & path : paths) + for (const auto& path : paths) { canonicalPaths[canonicalPath(path.first)] = path.second; + } - for (ExpressionMap::const_iterator i = expressions.begin(); i != expressions.end(); ++i) { - std::map::const_iterator j = canonicalPaths.find(i->first); + for (auto i = expressions.begin(); i != expressions.end(); ++i) { + auto j = canonicalPaths.find(i->first); // Renamed now? - if (j != canonicalPaths.end()) + if (j != canonicalPaths.end()) { newExpressions[j->second] = i->second; - else + } + else { newExpressions[i->first] = i->second; + } } aboutToSetValue(); expressions = newExpressions; - for (ExpressionMap::const_iterator i = expressions.begin(); i != expressions.end(); ++i) + for (auto i = expressions.begin(); i != expressions.end(); ++i) { expressionChanged(i->first); + } hasSetValue(); } @@ -851,18 +945,19 @@ void PropertyExpressionEngine::renameExpressions(const std::map &paths) +void PropertyExpressionEngine::renameObjectIdentifiers( + const std::map& paths) { - for (const auto & it : expressions) { + for (const auto& it : expressions) { RenameObjectIdentifierExpressionVisitor v(*this, paths, it.first); it.second.expression->visit(v); } } -PyObject *PropertyExpressionEngine::getPyObject() +PyObject* PropertyExpressionEngine::getPyObject() { Py::List list; - for (const auto & it : expressions) { + for (const auto& it : expressions) { Py::Tuple tuple(2); tuple.setItem(0, Py::String(it.first.toString())); auto expr = it.second.expression; @@ -872,7 +967,7 @@ PyObject *PropertyExpressionEngine::getPyObject() return Py::new_reference_to(list); } -void PropertyExpressionEngine::setPyObject(PyObject *) +void PropertyExpressionEngine::setPyObject(PyObject*) { throw Base::RuntimeError("Property is read-only"); } @@ -905,42 +1000,50 @@ void PropertyExpressionEngine::breakLink(App::DocumentObject *obj, bool clear) { } */ -bool PropertyExpressionEngine::adjustLink(const std::set &inList) { +bool PropertyExpressionEngine::adjustLink(const std::set& inList) +{ auto owner = dynamic_cast(getContainer()); - if(!owner) + if (!owner) { return false; + } bool found = false; - for(auto &v : _Deps) { - if(inList.count(v.first)) { + for (auto& v : _Deps) { + if (inList.count(v.first)) { found = true; break; } } - if(!found) + if (!found) { return false; + } AtomicPropertyChange signaler(*this); - for(auto &v : expressions) { + for (auto& v : expressions) { try { - if(v.second.expression && v.second.expression->adjustLinks(inList)) + if (v.second.expression && v.second.expression->adjustLinks(inList)) { expressionChanged(v.first); - }catch(Base::Exception &e) { + } + } + catch (Base::Exception& e) { std::ostringstream ss; ss << "Failed to adjust link for " << owner->getFullName() << " in expression " - << v.second.expression->toString() << ": " << e.what(); + << v.second.expression->toString() << ": " << e.what(); throw Base::RuntimeError(ss.str()); } } return true; } -void PropertyExpressionEngine::updateElementReference(DocumentObject *feature, bool reverse, bool notify) +void PropertyExpressionEngine::updateElementReference(DocumentObject* feature, + bool reverse, + bool notify) { (void)notify; - if(!feature) + if (!feature) { unregisterElementReference(); - UpdateElementReferenceExpressionVisitor v(*this,feature,reverse); - for(auto &e : expressions) { + } + UpdateElementReferenceExpressionVisitor v(*this, feature, reverse); + for (auto& e : expressions) { if (e.second.expression) { e.second.expression->visit(v); if (v.changed()) { @@ -949,103 +1052,123 @@ void PropertyExpressionEngine::updateElementReference(DocumentObject *feature, b } } } - if(feature && v.changed()) { + if (feature && v.changed()) { auto owner = dynamic_cast(getContainer()); - if(owner) + if (owner) { owner->onUpdateElementReference(this); + } } } -bool PropertyExpressionEngine::referenceChanged() const { +bool PropertyExpressionEngine::referenceChanged() const +{ return false; } -Property *PropertyExpressionEngine::CopyOnImportExternal( - const std::map &nameMap) const +Property* PropertyExpressionEngine::CopyOnImportExternal( + const std::map& nameMap) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR std::shared_ptr expr(it->second.expression->importSubNames(nameMap).release()); #else std::shared_ptr expr(it->second.expression->importSubNames(nameMap)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { - engine->expressions[it2->first] = ExpressionInfo( - std::shared_ptr(it2->second.expression->copy())); + for (auto it2 = expressions.begin(); it2 != it; ++it2) { + engine->expressions[it2->first] = + ExpressionInfo(std::shared_ptr(it2->second.expression->copy())); } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } -Property *PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyExpressionEngine::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR - std::shared_ptr expr(it->second.expression->updateLabelReference(obj,ref,newLabel).release()); + std::shared_ptr expr( + it->second.expression->updateLabelReference(obj, ref, newLabel).release()); #else - std::shared_ptr expr(it->second.expression->updateLabelReference(obj,ref,newLabel)); + std::shared_ptr expr( + it->second.expression->updateLabelReference(obj, ref, newLabel)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { + for (auto it2 = expressions.begin(); it2 != it; ++it2) { ExpressionInfo info; - if (it2->second.expression) + if (it2->second.expression) { info.expression = std::shared_ptr(it2->second.expression->copy()); + } engine->expressions[it2->first] = info; } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } -Property *PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyExpressionEngine::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - std::unique_ptr engine; - for(auto it=expressions.begin();it!=expressions.end();++it) { + std::unique_ptr engine; + for (auto it = expressions.begin(); it != expressions.end(); ++it) { #ifdef BOOST_NO_CXX11_SMART_PTR std::shared_ptr expr( - it->second.expression->replaceObject(parent,oldObj,newObj).release()); + it->second.expression->replaceObject(parent, oldObj, newObj).release()); #else std::shared_ptr expr( - it->second.expression->replaceObject(parent,oldObj,newObj)); + it->second.expression->replaceObject(parent, oldObj, newObj)); #endif - if(!expr && !engine) + if (!expr && !engine) { continue; - if(!engine) { + } + if (!engine) { engine = std::make_unique(); - for(auto it2=expressions.begin();it2!=it;++it2) { + for (auto it2 = expressions.begin(); it2 != it; ++it2) { ExpressionInfo info; - if (it2->second.expression) + if (it2->second.expression) { info.expression = std::shared_ptr(it2->second.expression->copy()); + } engine->expressions[it2->first] = info; } - }else if(!expr) + } + else if (!expr) { expr = it->second.expression; + } engine->expressions[it->first] = ExpressionInfo(expr); } - if(!engine) + if (!engine) { return nullptr; + } engine->validator = validator; return engine.release(); } @@ -1054,30 +1177,34 @@ std::map PropertyExpressionEngine::getExpressions() const { std::map res; - for(auto &v : expressions) + for (auto& v : expressions) { res[v.first] = v.second.expression.get(); + } return res; } void PropertyExpressionEngine::setExpressions( - std::map &&exprs) + std::map&& exprs) { AtomicPropertyChange signaller(*this); #ifdef BOOST_NO_CXX11_SMART_PTR - for(auto &v : exprs) - setValue(v.first,std::shared_ptr(v.second.release())); + for (auto& v : exprs) { + setValue(v.first, std::shared_ptr(v.second.release())); + } #else - for(auto &v : exprs) - setValue(v.first,std::move(v.second)); + for (auto& v : exprs) { + setValue(v.first, std::move(v.second)); + } #endif } -void PropertyExpressionEngine::onRelabeledDocument(const App::Document &doc) +void PropertyExpressionEngine::onRelabeledDocument(const App::Document& doc) { RelabelDocumentExpressionVisitor v(doc); - for(auto &e : expressions) { - if (e.second.expression) + for (auto& e : expressions) { + if (e.second.expression) { e.second.expression->visit(v); + } } } diff --git a/src/App/PropertyExpressionEngine.h b/src/App/PropertyExpressionEngine.h index 248a1c132347..98dd5ba6cbca 100644 --- a/src/App/PropertyExpressionEngine.h +++ b/src/App/PropertyExpressionEngine.h @@ -31,12 +31,14 @@ #include #include -namespace Base { +namespace Base +{ class Writer; class XMLReader; -} +} // namespace Base -namespace App { +namespace App +{ class DocumentObject; class DocumentObjectExecReturn; @@ -44,84 +46,96 @@ class ObjectIdentifier; class Expression; using ExpressionPtr = std::unique_ptr; -class AppExport PropertyExpressionContainer : public App::PropertyXLinkContainer +class AppExport PropertyExpressionContainer: public App::PropertyXLinkContainer { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: PropertyExpressionContainer(); ~PropertyExpressionContainer() override; virtual std::map getExpressions() const = 0; - virtual void setExpressions(std::map &&exprs) = 0; + virtual void setExpressions(std::map&& exprs) = 0; protected: - virtual void onRelabeledDocument(const App::Document &doc) = 0; + virtual void onRelabeledDocument(const App::Document& doc) = 0; private: - static void slotRelabelDocument(const App::Document &doc); + static void slotRelabelDocument(const App::Document& doc); }; -class AppExport PropertyExpressionEngine : public App::PropertyExpressionContainer, - private App::AtomicPropertyChangeInterface +class AppExport PropertyExpressionEngine + : public App::PropertyExpressionContainer, + private App::AtomicPropertyChangeInterface { TYPESYSTEM_HEADER_WITH_OVERRIDE(); -public: - void updateElementReference( - App::DocumentObject *feature, bool reverse=false, bool notify=false) override; +public: + void updateElementReference(App::DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - bool adjustLink(const std::set &inList) override; - Property *CopyOnImportExternal(const std::map &nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; - - using ValidatorFunc = std::function expr)>; + bool adjustLink(const std::set& inList) override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; + Property* CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; + + using ValidatorFunc = std::function expr)>; /** * @brief The ExpressionInfo struct encapsulates an expression. */ - struct ExpressionInfo { + struct ExpressionInfo + { std::shared_ptr expression; /**< The actual expression tree */ bool busy; - explicit ExpressionInfo(std::shared_ptr expression = std::shared_ptr()) { + explicit ExpressionInfo( + std::shared_ptr expression = std::shared_ptr()) + { this->expression = expression; this->busy = false; } - ExpressionInfo(const ExpressionInfo &) = default; + ExpressionInfo(const ExpressionInfo&) = default; - ExpressionInfo & operator=(const ExpressionInfo &) = default; + ExpressionInfo& operator=(const ExpressionInfo&) = default; }; PropertyExpressionEngine(); ~PropertyExpressionEngine() override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; std::map getExpressions() const override; - void setExpressions(std::map &&exprs) override; - void onRelabeledDocument(const App::Document &doc) override; + void setExpressions(std::map&& exprs) override; + void onRelabeledDocument(const App::Document& doc) override; - void setValue() { } // Dummy + void setValue() + {} // Dummy - Property *Copy() const override; + Property* Copy() const override; - void Paste(const Property &from) override; + void Paste(const Property& from) override; - void Save (Base::Writer & writer) const override; + void Save(Base::Writer& writer) const override; - void Restore(Base::XMLReader &reader) override; + void Restore(Base::XMLReader& reader) override; - void setValue(const App::ObjectIdentifier &path, std::shared_ptr expr); + void setValue(const App::ObjectIdentifier& path, std::shared_ptr expr); - const boost::any getPathValue(const App::ObjectIdentifier & path) const override; + const boost::any getPathValue(const App::ObjectIdentifier& path) const override; /// Execute options - enum ExecuteOption { + enum ExecuteOption + { /// Execute all expression ExecuteAll, /// Execute only output property bindings @@ -135,67 +149,74 @@ class AppExport PropertyExpressionEngine : public App::PropertyExpressionContain * * @param option: execution option, see ExecuteOption. */ - DocumentObjectExecReturn * execute(ExecuteOption option=ExecuteAll, bool *touched=nullptr); + DocumentObjectExecReturn* execute(ExecuteOption option = ExecuteAll, bool* touched = nullptr); - void getPathsToDocumentObject(DocumentObject*, std::vector & paths) const; + void getPathsToDocumentObject(DocumentObject*, std::vector& paths) const; bool depsAreTouched() const; /* Expression validator */ - void setValidator(ValidatorFunc f) { validator = f; } + void setValidator(ValidatorFunc f) + { + validator = f; + } - std::string validateExpression(const App::ObjectIdentifier & path, std::shared_ptr expr) const; + std::string validateExpression(const App::ObjectIdentifier& path, + std::shared_ptr expr) const; - void renameExpressions(const std::map &paths); + void renameExpressions(const std::map& paths); - void renameObjectIdentifiers(const std::map & paths); + void + renameObjectIdentifiers(const std::map& paths); - App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier &p) const override; + App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier& p) const override; size_t numExpressions() const; - ///signal called when an expression was changed - boost::signals2::signal expressionChanged; + /// signal called when an expression was changed + boost::signals2::signal expressionChanged; void afterRestore() override; void onContainerRestored() override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; /* Python interface */ - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; protected: void hasSetValue() override; private: - - using DiGraph = boost::adjacency_list< boost::listS, boost::vecS, boost::directedS >; + using DiGraph = boost::adjacency_list; using Edge = std::pair; - // Note: use std::map instead of unordered_map to keep the binding order stable - #if defined(FC_OS_MACOSX) || defined(FC_OS_BSD) || defined(_LIBCPP_VERSION) +// Note: use std::map instead of unordered_map to keep the binding order stable +#if defined(FC_OS_MACOSX) || defined(FC_OS_BSD) || defined(_LIBCPP_VERSION) using ExpressionMap = std::map; - #else +#else using ExpressionMap = std::map; - #endif +#endif std::vector computeEvaluationOrder(ExecuteOption option); - void buildGraphStructures(const App::ObjectIdentifier &path, - const std::shared_ptr expression, boost::unordered_map &nodes, - boost::unordered_map &revNodes, std::vector &edges) const; + void buildGraphStructures(const App::ObjectIdentifier& path, + const std::shared_ptr expression, + boost::unordered_map& nodes, + boost::unordered_map& revNodes, + std::vector& edges) const; - void buildGraph(const ExpressionMap &exprs, - boost::unordered_map &revNodes, - DiGraph &g, ExecuteOption option=ExecuteAll) const; + void buildGraph(const ExpressionMap& exprs, + boost::unordered_map& revNodes, + DiGraph& g, + ExecuteOption option = ExecuteAll) const; - void slotChangedObject(const App::DocumentObject &obj, const App::Property &prop); - void slotChangedProperty(const App::DocumentObject &obj, const App::Property &prop); - void updateHiddenReference(const std::string &key); + void slotChangedObject(const App::DocumentObject& obj, const App::Property& prop); + void slotChangedProperty(const App::DocumentObject& obj, const App::Property& prop); + void updateHiddenReference(const std::string& key); bool running = false; /**< Boolean used to avoid loops */ bool restoring = false; @@ -204,21 +225,22 @@ class AppExport PropertyExpressionEngine : public App::PropertyExpressionContain ValidatorFunc validator; /**< Valdiator functor */ - struct RestoredExpression { + struct RestoredExpression + { std::string path; std::string expr; std::string comment; }; - /**< Expressions are read from file to this map first before they are validated and inserted into the actual map */ - std::unique_ptr > restoredExpressions; + /**< Expressions are read from file to this map first before they are validated and inserted + * into the actual map */ + std::unique_ptr> restoredExpressions; struct Private; std::unique_ptr pimpl; friend class AtomicPropertyChange; - }; -} +} // namespace App -#endif // EXPRESSIONENGINE_H +#endif // EXPRESSIONENGINE_H diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 9944d637fb60..eec521f391db 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -41,12 +41,11 @@ using namespace Base; using namespace std; - //************************************************************************** // PropertyFileIncluded //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property) +TYPESYSTEM_SOURCE(App::PropertyFileIncluded, App::Property) PropertyFileIncluded::PropertyFileIncluded() = default; @@ -78,7 +77,7 @@ void PropertyFileIncluded::aboutToSetValue() std::string PropertyFileIncluded::getDocTransientPath() const { std::string path; - PropertyContainer *co = getContainer(); + PropertyContainer* co = getContainer(); if (co->isDerivedFrom(DocumentObject::getClassTypeId())) { path = static_cast(co)->getDocument()->TransientDir.getValue(); std::replace(path.begin(), path.end(), '\\', '/'); @@ -86,7 +85,8 @@ std::string PropertyFileIncluded::getDocTransientPath() const return path; } -std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, const std::string& filename) const +std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, + const std::string& filename) const { Base::Uuid uuid; Base::FileInfo fi(path + "/" + filename); @@ -99,8 +99,8 @@ std::string PropertyFileIncluded::getUniqueFileName(const std::string& path, con std::string PropertyFileIncluded::getExchangeTempFile() const { - return Base::FileInfo::getTempFileName(Base::FileInfo - (getValue()).fileName().c_str(), getDocTransientPath().c_str()); + return Base::FileInfo::getTempFileName(Base::FileInfo(getValue()).fileName().c_str(), + getDocTransientPath().c_str()); } std::string PropertyFileIncluded::getOriginalFileName() const @@ -111,8 +111,9 @@ std::string PropertyFileIncluded::getOriginalFileName() const void PropertyFileIncluded::setValue(const char* sFile, const char* sName) { if (sFile && sFile[0] != '\0') { - if (_cValue == sFile) + if (_cValue == sFile) { throw Base::FileSystemError("Not possible to set the same file!"); + } // keep the path to the original file _OriginalName = sFile; @@ -126,7 +127,7 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName) throw Base::FileSystemError(str.str()); } - aboutToSetValue(); // undo/redo by moving the file away with temp name + aboutToSetValue(); // undo/redo by moving the file away with temp name // remove old file (if not moved by undo) Base::FileInfo value(_cValue); @@ -144,16 +145,16 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName) std::string dir = pathTrans; std::string fnp = fi.fileNamePure(); std::string ext = fi.extension(); - int i=0; + int i = 0; do { i++; std::stringstream str; str << dir << "/" << fnp << i; - if (!ext.empty()) + if (!ext.empty()) { str << "." << ext; + } fi.setFile(str.str()); - } - while (fi.exists()); + } while (fi.exists()); _cValue = fi.filePath(); _BaseFileName = fi.fileName(); @@ -189,7 +190,7 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName) Base::FileInfo dst(_cValue); dst.setPermissions(Base::FileInfo::ReadOnly); } - // otherwise copy from origin location + // otherwise copy from origin location else { // if file already exists in transient dir make a new unique name Base::FileInfo fi(_cValue); @@ -198,16 +199,16 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName) std::string dir = fi.dirPath(); std::string fnp = fi.fileNamePure(); std::string ext = fi.extension(); - int i=0; + int i = 0; do { i++; std::stringstream str; str << dir << "/" << fnp << i; - if (!ext.empty()) + if (!ext.empty()) { str << "." << ext; + } fi.setFile(str.str()); - } - while (fi.exists()); + } while (fi.exists()); _cValue = fi.filePath(); _BaseFileName = fi.fileName(); @@ -231,40 +232,41 @@ void PropertyFileIncluded::setValue(const char* sFile, const char* sName) const char* PropertyFileIncluded::getValue() const { - return _cValue.c_str(); + return _cValue.c_str(); } -PyObject *PropertyFileIncluded::getPyObject() +PyObject* PropertyFileIncluded::getPyObject() { - PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),nullptr); + PyObject* p = PyUnicode_DecodeUTF8(_cValue.c_str(), _cValue.size(), nullptr); if (!p) { throw Base::UnicodeError("PropertyFileIncluded: UTF-8 conversion failure"); } return p; } -namespace App { +namespace App +{ const char* getNameFromFile(PyObject* value) { const char* string = nullptr; - PyObject *oname = PyObject_GetAttrString (value, "name"); + PyObject* oname = PyObject_GetAttrString(value, "name"); if (oname) { - if (PyUnicode_Check (oname)) { - string = PyUnicode_AsUTF8 (oname); + if (PyUnicode_Check(oname)) { + string = PyUnicode_AsUTF8(oname); } - else if (PyBytes_Check (oname)) { - string = PyBytes_AsString (oname); + else if (PyBytes_Check(oname)) { + string = PyBytes_AsString(oname); } - Py_DECREF (oname); + Py_DECREF(oname); } - if (!string) + if (!string) { throw Base::TypeError("Unable to get filename"); + } return string; } - bool isIOFile(PyObject* file) { PyObject* io = PyImport_ImportModule("io"); @@ -274,9 +276,9 @@ bool isIOFile(PyObject* file) Py_DECREF(io); return isFile; } -} +} // namespace App -void PropertyFileIncluded::setPyObject(PyObject *value) +void PropertyFileIncluded::setPyObject(PyObject* value) { if (PyUnicode_Check(value)) { std::string string = PyUnicode_AsUTF8(value); @@ -286,15 +288,16 @@ void PropertyFileIncluded::setPyObject(PyObject *value) std::string string = PyBytes_AsString(value); setValue(string.c_str()); } - else if (isIOFile(value)){ + else if (isIOFile(value)) { std::string string = getNameFromFile(value); setValue(string.c_str()); } else if (PyTuple_Check(value)) { - if (PyTuple_Size(value) != 2) - throw Base::TypeError("Tuple needs size of (filePath,newFileName)"); - PyObject* file = PyTuple_GetItem(value,0); - PyObject* name = PyTuple_GetItem(value,1); + if (PyTuple_Size(value) != 2) { + throw Base::TypeError("Tuple needs size of (filePath,newFileName)"); + } + PyObject* file = PyTuple_GetItem(value, 0); + PyObject* name = PyTuple_GetItem(value, 1); // decoding file std::string fileStr; @@ -330,7 +333,7 @@ void PropertyFileIncluded::setPyObject(PyObject *value) throw Base::TypeError(error); } - setValue(fileStr.c_str(),nameStr.c_str()); + setValue(fileStr.c_str(), nameStr.c_str()); } else if (PyDict_Check(value)) { Py::Dict dict(value); @@ -349,39 +352,40 @@ void PropertyFileIncluded::setPyObject(PyObject *value) } } -void PropertyFileIncluded::Save (Base::Writer &writer) const +void PropertyFileIncluded::Save(Base::Writer& writer) const { // when saving a document under a new file name the transient directory // name changes and thus the stored file name doesn't work any more. if (!_cValue.empty() && !Base::FileInfo(_cValue).exists()) { Base::FileInfo fi(getDocTransientPath() + "/" + _BaseFileName); - if (fi.exists()) + if (fi.exists()) { _cValue = fi.filePath(); + } } if (writer.isForceXML()) { if (!_cValue.empty()) { Base::FileInfo file(_cValue.c_str()); - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; // write the file in the XML stream writer.incInd(); writer.insertBinFile(_cValue.c_str()); writer.decInd(); - writer.Stream() << writer.ind() <<"" << endl; + writer.Stream() << writer.ind() << "" << endl; } else { writer.Stream() << writer.ind() << "" << std::endl; } } else { - // instead initiate an extra file + // instead initiate an extra file if (!_cValue.empty()) { Base::FileInfo file(_cValue.c_str()); std::string filename = writer.addFile(file.fileName().c_str(), this); filename = encodeAttribute(filename); - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } else { writer.Stream() << writer.ind() << "" << std::endl; @@ -389,14 +393,14 @@ void PropertyFileIncluded::Save (Base::Writer &writer) const } } -void PropertyFileIncluded::Restore(Base::XMLReader &reader) +void PropertyFileIncluded::Restore(Base::XMLReader& reader) { reader.readElement("FileIncluded"); if (reader.hasAttribute("file")) { - string file (reader.getAttribute("file") ); + string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); // is in the document transient path aboutToSetValue(); _cValue = getDocTransientPath() + "/" + file; @@ -406,7 +410,7 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader) } // section is XML stream else if (reader.hasAttribute("data")) { - string file (reader.getAttribute("data") ); + string file(reader.getAttribute("data")); if (!file.empty()) { // is in the document transient path aboutToSetValue(); @@ -422,7 +426,7 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader) } } -void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const +void PropertyFileIncluded::SaveDocFile(Base::Writer& writer) const { Base::ifstream from(Base::FileInfo(_cValue.c_str()), std::ios::in | std::ios::binary); if (!from) { @@ -440,7 +444,7 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const } } -void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader) +void PropertyFileIncluded::RestoreDocFile(Base::Reader& reader) { Base::FileInfo fi(_cValue.c_str()); if (fi.exists() && !fi.isWritable()) { @@ -469,7 +473,7 @@ void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader) hasSetValue(); } -Property *PropertyFileIncluded::Copy() const +Property* PropertyFileIncluded::Copy() const { std::unique_ptr prop(new PropertyFileIncluded()); @@ -486,8 +490,8 @@ Property *PropertyFileIncluded::Copy() const if (!done) { std::stringstream str; str << "PropertyFileIncluded::Copy(): " - << "Renaming the file '" << file.filePath() << "' to '" - << newName.filePath() << "' failed."; + << "Renaming the file '" << file.filePath() << "' to '" << newName.filePath() + << "' failed."; throw Base::FileSystemError(str.str()); } } @@ -497,14 +501,14 @@ Property *PropertyFileIncluded::Copy() const if (!done) { std::stringstream str; str << "PropertyFileIncluded::Copy(): " - << "Copying the file '" << file.filePath() << "' to '" - << newName.filePath() << "' failed."; + << "Copying the file '" << file.filePath() << "' to '" << newName.filePath() + << "' failed."; throw Base::FileSystemError(str.str()); } } // remember the new name for the Undo - Base::Console().Log("Copy '%s' to '%s'\n",_cValue.c_str(),newName.filePath().c_str()); + Base::Console().Log("Copy '%s' to '%s'\n", _cValue.c_str(), newName.filePath().c_str()); prop->_cValue = newName.filePath().c_str(); // make backup files writable to avoid copying them again on undo/redo @@ -514,10 +518,10 @@ Property *PropertyFileIncluded::Copy() const return prop.release(); } -void PropertyFileIncluded::Paste(const Property &from) +void PropertyFileIncluded::Paste(const Property& from) { aboutToSetValue(); - const PropertyFileIncluded &prop = dynamic_cast(from); + const PropertyFileIncluded& prop = dynamic_cast(from); // make sure that source and destination file are different if (_cValue != prop._cValue) { // delete old file (if still there) @@ -540,8 +544,8 @@ void PropertyFileIncluded::Paste(const Property &from) if (!fiSrc.renameFile(fiDst.filePath().c_str())) { std::stringstream str; str << "PropertyFileIncluded::Paste(): " - << "Renaming the file '" << fiSrc.filePath() << "' to '" - << fiDst.filePath() << "' failed."; + << "Renaming the file '" << fiSrc.filePath() << "' to '" << fiDst.filePath() + << "' failed."; throw Base::FileSystemError(str.str()); } } @@ -549,8 +553,8 @@ void PropertyFileIncluded::Paste(const Property &from) if (!fiSrc.copyTo(fiDst.filePath().c_str())) { std::stringstream str; str << "PropertyFileIncluded::Paste(): " - << "Copying the file '" << fiSrc.filePath() << "' to '" - << fiDst.filePath() << "' failed."; + << "Copying the file '" << fiSrc.filePath() << "' to '" << fiDst.filePath() + << "' failed."; throw Base::FileSystemError(str.str()); } } @@ -569,7 +573,7 @@ void PropertyFileIncluded::Paste(const Property &from) hasSetValue(); } -unsigned int PropertyFileIncluded::getMemSize () const +unsigned int PropertyFileIncluded::getMemSize() const { unsigned int mem = Property::getMemSize(); mem += _cValue.size(); @@ -591,7 +595,7 @@ std::string PropertyFileIncluded::getFilter() const // PropertyFile //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFile , App::PropertyString) +TYPESYSTEM_SOURCE(App::PropertyFile, App::PropertyString) PropertyFile::PropertyFile() { @@ -610,7 +614,7 @@ std::string PropertyFile::getFilter() const return m_filter; } -void PropertyFile::setPyObject(PyObject *value) +void PropertyFile::setPyObject(PyObject* value) { if (PyDict_Check(value)) { Py::Dict dict(value); @@ -626,4 +630,3 @@ void PropertyFile::setPyObject(PyObject *value) PropertyString::setPyObject(value); } } - diff --git a/src/App/PropertyFile.h b/src/App/PropertyFile.h index 3806b09bf81e..d36300fc929a 100644 --- a/src/App/PropertyFile.h +++ b/src/App/PropertyFile.h @@ -29,7 +29,8 @@ #include "PropertyStandard.h" -namespace Base { +namespace Base +{ class Writer; } @@ -37,9 +38,9 @@ namespace App { /** File properties - * This property holds a file name - */ -class AppExport PropertyFile : public PropertyString + * This property holds a file name + */ +class AppExport PropertyFile: public PropertyString { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -48,9 +49,11 @@ class AppExport PropertyFile : public PropertyString ~PropertyFile() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyFileItem"; } + { + return "Gui::PropertyEditor::PropertyFileItem"; + } - void setPyObject(PyObject *) override; + void setPyObject(PyObject*) override; virtual void setFilter(const std::string filter); virtual std::string getFilter() const; @@ -59,20 +62,20 @@ class AppExport PropertyFile : public PropertyString }; /** File include properties - * This property doesn't only save the file name like PropertyFile - * it also includes the file itself into the document. The file - * doesn't get loaded into memory, it gets copied from the document - * archive into the document transient directory. There it is accessible for - * the algorithms. You get the transient path through getDocTransientPath() - * It's allowed to read the file, it's not allowed to write the file - * directly in the transient path! That would undermine the Undo/Redo - * framework. It's only allowed to use setValue() to change the file. - * If you give a file name outside the transient dir to setValue() it - * will copy the file. If you give a file name in the transient path it - * will just rename and use the same file. You can use getExchangeTempFile() to - * get a file name in the transient dir to write a new file version. + * This property doesn't only save the file name like PropertyFile + * it also includes the file itself into the document. The file + * doesn't get loaded into memory, it gets copied from the document + * archive into the document transient directory. There it is accessible for + * the algorithms. You get the transient path through getDocTransientPath() + * It's allowed to read the file, it's not allowed to write the file + * directly in the transient path! That would undermine the Undo/Redo + * framework. It's only allowed to use setValue() to change the file. + * If you give a file name outside the transient dir to setValue() it + * will copy the file. If you give a file name in the transient path it + * will just rename and use the same file. You can use getExchangeTempFile() to + * get a file name in the transient dir to write a new file version. */ -class AppExport PropertyFileIncluded : public Property +class AppExport PropertyFileIncluded: public Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -80,27 +83,31 @@ class AppExport PropertyFileIncluded : public Property PropertyFileIncluded(); ~PropertyFileIncluded() override; - void setValue(const char* sFile, const char* sName=nullptr); + void setValue(const char* sFile, const char* sName = nullptr); const char* getValue() const; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyTransientFileItem"; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + { + return "Gui::PropertyEditor::PropertyTransientFileItem"; + } + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return getTypeId() == other.getTypeId() && _BaseFileName == static_cast(&other)->_BaseFileName && _OriginalName == static_cast(&other)->_OriginalName @@ -108,14 +115,17 @@ class AppExport PropertyFileIncluded : public Property } /** get a temp file name in the transient path of the document. - * Using this file for new Version of the file and set - * this file with setValue() is the fastest way to change - * the File. - */ + * Using this file for new Version of the file and set + * this file with setValue() is the fastest way to change + * the File. + */ std::string getExchangeTempFile() const; std::string getOriginalFileName() const; - bool isEmpty() const {return _cValue.empty();} + bool isEmpty() const + { + return _cValue.empty(); + } void setFilter(std::string filter); std::string getFilter() const; @@ -136,6 +146,6 @@ class AppExport PropertyFileIncluded : public Property }; -} // namespace App +} // namespace App -#endif // APP_PROPERTFILE_H +#endif // APP_PROPERTFILE_H diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index 29b075393e70..aeb2454960f8 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -48,14 +48,12 @@ using namespace Base; using namespace std; - - //************************************************************************** //************************************************************************** // PropertyVector //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVector , App::Property) +TYPESYSTEM_SOURCE(App::PropertyVector, App::Property) //************************************************************************** // Construction/Destruction @@ -63,72 +61,79 @@ TYPESYSTEM_SOURCE(App::PropertyVector , App::Property) PropertyVector::PropertyVector() = default; - PropertyVector::~PropertyVector() = default; //************************************************************************** // Base class implementer - -void PropertyVector::setValue(const Base::Vector3d &vec) +void PropertyVector::setValue(const Base::Vector3d& vec) { aboutToSetValue(); - _cVec=vec; + _cVec = vec; hasSetValue(); } void PropertyVector::setValue(double x, double y, double z) { aboutToSetValue(); - _cVec.Set(x,y,z); + _cVec.Set(x, y, z); hasSetValue(); } -const Base::Vector3d & PropertyVector::getValue()const +const Base::Vector3d& PropertyVector::getValue() const { return _cVec; } -PyObject *PropertyVector::getPyObject() +PyObject* PropertyVector::getPyObject() { return new Base::VectorPy(_cVec); } -void PropertyVector::setPyObject(PyObject *value) +void PropertyVector::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::VectorPy::Type))) { - Base::VectorPy *pcObject = static_cast(value); + Base::VectorPy* pcObject = static_cast(value); Base::Vector3d* val = pcObject->getVectorPtr(); setValue(*val); } - else if (PyTuple_Check(value)&&PyTuple_Size(value)==3) { - PyObject* item; + else if (PyTuple_Check(value) && PyTuple_Size(value) == 3) { + PyObject* item {}; Base::Vector3d cVec; // x - item = PyTuple_GetItem(value,0); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 0); + if (PyFloat_Check(item)) { cVec.x = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.x = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); + } // y - item = PyTuple_GetItem(value,1); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 1); + if (PyFloat_Check(item)) { cVec.y = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.y = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); + } // z - item = PyTuple_GetItem(value,2); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 2); + if (PyFloat_Check(item)) { cVec.z = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cVec.z = (double)PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Not allowed type used in tuple (float expected)..."); - setValue( cVec ); + } + setValue(cVec); } else { std::string error = std::string("type must be 'Vector' or tuple of three floats, not "); @@ -137,18 +142,19 @@ void PropertyVector::setPyObject(PyObject *value) } } -void PropertyVector::Save (Base::Writer &writer) const +void PropertyVector::Save(Base::Writer& writer) const { // clang-format off writer.Stream() << writer.ind() - << "" << endl; + << "\n"; // clang-format on } -void PropertyVector::Restore(Base::XMLReader &reader) +void PropertyVector::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyVector"); @@ -161,21 +167,21 @@ void PropertyVector::Restore(Base::XMLReader &reader) } -Property *PropertyVector::Copy() const +Property* PropertyVector::Copy() const { - PropertyVector *p= new PropertyVector(); + PropertyVector* p = new PropertyVector(); p->_cVec = _cVec; return p; } -void PropertyVector::Paste(const Property &from) +void PropertyVector::Paste(const Property& from) { aboutToSetValue(); _cVec = dynamic_cast(from)._cVec; hasSetValue(); } -void PropertyVector::getPaths(std::vector &paths) const +void PropertyVector::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x"))); @@ -185,10 +191,10 @@ void PropertyVector::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyVector::getPathValue(const ObjectIdentifier& path) const { Base::Unit unit = getUnit(); - if(!unit.isEmpty()) { + if (!unit.isEmpty()) { std::string p = path.getSubPathStr(); if (p == ".x" || p == ".y" || p == ".z") { // Convert double to quantity @@ -198,21 +204,26 @@ const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) cons return Property::getPathValue(path); } -bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyVector::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { Base::Unit unit = getUnit(); - if(unit.isEmpty()) + if (unit.isEmpty()) { return false; + } std::string p = path.getSubPathStr(); if (p == ".x") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().x,unit))); - } else if(p == ".y") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().y,unit))); - } else if(p == ".z") { - res = Py::asObject(new QuantityPy(new Quantity(getValue().z,unit))); - } else + res = Py::asObject(new QuantityPy(new Quantity(getValue().x, unit))); + } + else if (p == ".y") { + res = Py::asObject(new QuantityPy(new Quantity(getValue().y, unit))); + } + else if (p == ".z") { + res = Py::asObject(new QuantityPy(new Quantity(getValue().z, unit))); + } + else { return false; + } return true; } @@ -221,7 +232,7 @@ bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &re // PropertyVectorDistance //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVectorDistance , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyVectorDistance, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -235,7 +246,7 @@ PropertyVectorDistance::~PropertyVectorDistance() = default; // PropertyPosition //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPosition , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyPosition, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -249,7 +260,7 @@ PropertyPosition::~PropertyPosition() = default; // PropertyPosition //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyDirection , App::PropertyVector) +TYPESYSTEM_SOURCE(App::PropertyDirection, App::PropertyVector) //************************************************************************** // Construction/Destruction @@ -263,7 +274,7 @@ PropertyDirection::~PropertyDirection() = default; // PropertyVectorList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyVectorList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyVectorList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -277,55 +288,58 @@ PropertyVectorList::~PropertyVectorList() = default; void PropertyVectorList::setValue(double x, double y, double z) { - setValue(Base::Vector3d(x,y,z)); + setValue(Base::Vector3d(x, y, z)); } -PyObject *PropertyVectorList::getPyObject() +PyObject* PropertyVectorList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;i < getSize(); i++) + for (int i = 0; i < getSize(); i++) { PyList_SetItem(list, i, new VectorPy(_lValueList[i])); + } return list; } -Base::Vector3d PropertyVectorList::getPyValue(PyObject *item) const { +Base::Vector3d PropertyVectorList::getPyValue(PyObject* item) const +{ PropertyVector val; - val.setPyObject( item ); + val.setPyObject(item); return val.getValue(); } -void PropertyVectorList::Save (Base::Writer &writer) const +void PropertyVectorList::Save(Base::Writer& writer) const { if (!writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } } -void PropertyVectorList::Restore(Base::XMLReader &reader) +void PropertyVectorList::Restore(Base::XMLReader& reader) { reader.readElement("VectorList"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void PropertyVectorList::SaveDocFile (Base::Writer &writer) const +void PropertyVectorList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); str << uCt; if (!isSinglePrecision()) { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { str << it.x << it.y << it.z; } } else { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { float x = (float)it.x; float y = (float)it.y; float z = (float)it.z; @@ -334,40 +348,40 @@ void PropertyVectorList::SaveDocFile (Base::Writer &writer) const } } -void PropertyVectorList::RestoreDocFile(Base::Reader &reader) +void PropertyVectorList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (auto & it : values) { + for (auto& it : values) { str >> it.x >> it.y >> it.z; } } else { - float x,y,z; - for (auto & it : values) { - str >> x >> y >> z; - it.Set(x, y, z); + Base::Vector3f vec; + for (auto& it : values) { + str >> vec.x >> vec.y >> vec.z; + it.Set(vec.x, vec.y, vec.z); } } setValues(values); } -Property *PropertyVectorList::Copy() const +Property* PropertyVectorList::Copy() const { - PropertyVectorList *p= new PropertyVectorList(); + PropertyVectorList* p = new PropertyVectorList(); p->_lValueList = _lValueList; return p; } -void PropertyVectorList::Paste(const Property &from) +void PropertyVectorList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyVectorList::getMemSize () const +unsigned int PropertyVectorList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Base::Vector3d)); } @@ -377,7 +391,7 @@ unsigned int PropertyVectorList::getMemSize () const // PropertyMatrix //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyMatrix , App::Property) +TYPESYSTEM_SOURCE(App::PropertyMatrix, App::Property) //************************************************************************** // Construction/Destruction @@ -392,47 +406,52 @@ PropertyMatrix::~PropertyMatrix() = default; // Base class implementer -void PropertyMatrix::setValue(const Base::Matrix4D &mat) +void PropertyMatrix::setValue(const Base::Matrix4D& mat) { aboutToSetValue(); - _cMat=mat; + _cMat = mat; hasSetValue(); } -const Base::Matrix4D & PropertyMatrix::getValue()const +const Base::Matrix4D& PropertyMatrix::getValue() const { return _cMat; } -PyObject *PropertyMatrix::getPyObject() +PyObject* PropertyMatrix::getPyObject() { return new Base::MatrixPy(_cMat); } -void PropertyMatrix::setPyObject(PyObject *value) +void PropertyMatrix::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *pcObject = static_cast(value); - setValue( pcObject->value() ); + Base::MatrixPy* pcObject = static_cast(value); + setValue(pcObject->value()); } - else if (PyTuple_Check(value)&&PyTuple_Size(value)==16) { + else if (PyTuple_Check(value) && PyTuple_Size(value) == 16) { PyObject* item; Base::Matrix4D cMatrix; - for (int x=0; x<4;x++) { - for (int y=0; y<4;y++) { - item = PyTuple_GetItem(value,x+y*4); - if (PyFloat_Check(item)) + const int dim = 4; + for (int x = 0; x < dim; x++) { + for (int y = 0; y < dim; y++) { + item = PyTuple_GetItem(value, x + y * dim); + if (PyFloat_Check(item)) { cMatrix[x][y] = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { cMatrix[x][y] = (double)PyLong_AsLong(item); - else - throw Base::TypeError("Not allowed type used in matrix tuple (a number expected)..."); + } + else { + throw Base::TypeError( + "Not allowed type used in matrix tuple (a number expected)..."); + } } } - setValue( cMatrix ); + setValue(cMatrix); } else { std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not "); @@ -441,7 +460,7 @@ void PropertyMatrix::setPyObject(PyObject *value) } } -void PropertyMatrix::Save (Base::Writer &writer) const +void PropertyMatrix::Save(Base::Writer& writer) const { // clang-format off writer.Stream() << writer.ind() << "_cMat = _cMat; return p; } -void PropertyMatrix::Paste(const Property &from) +void PropertyMatrix::Paste(const Property& from) { aboutToSetValue(); _cMat = dynamic_cast(from)._cMat; @@ -501,7 +520,7 @@ void PropertyMatrix::Paste(const Property &from) // PropertyPlacement //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacement , App::Property) +TYPESYSTEM_SOURCE(App::PropertyPlacement, App::Property) //************************************************************************** // Construction/Destruction @@ -516,18 +535,17 @@ PropertyPlacement::~PropertyPlacement() = default; // Base class implementer -void PropertyPlacement::setValue(const Base::Placement &pos) +void PropertyPlacement::setValue(const Base::Placement& pos) { aboutToSetValue(); - _cPos=pos; + _cPos = pos; hasSetValue(); } -bool PropertyPlacement::setValueIfChanged(const Base::Placement &pos,double tol,double atol) +bool PropertyPlacement::setValueIfChanged(const Base::Placement& pos, double tol, double atol) { - if(_cPos.getPosition().IsEqual(pos.getPosition(),tol) - && _cPos.getRotation().isSame(pos.getRotation(),atol)) - { + if (_cPos.getPosition().IsEqual(pos.getPosition(), tol) + && _cPos.getRotation().isSame(pos.getRotation(), atol)) { return false; } setValue(pos); @@ -535,12 +553,12 @@ bool PropertyPlacement::setValueIfChanged(const Base::Placement &pos,double tol, } -const Base::Placement & PropertyPlacement::getValue()const +const Base::Placement& PropertyPlacement::getValue() const { return _cPos; } -void PropertyPlacement::getPaths(std::vector &paths) const +void PropertyPlacement::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base")) @@ -568,34 +586,44 @@ void PropertyPlacement::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -namespace { -double toDouble(const boost::any &value) +namespace +{ +double toDouble(const boost::any& value) { - double avalue{}; + double avalue {}; - if (value.type() == typeid(Base::Quantity)) + if (value.type() == typeid(Base::Quantity)) { avalue = boost::any_cast(value).getValue(); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { avalue = boost::any_cast(value); - else if (value.type() == typeid(int)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned int)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(short)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned short)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(long)) - avalue = boost::any_cast(value); - else if (value.type() == typeid(unsigned long)) - avalue = boost::any_cast(value); - else + } + else if (value.type() == typeid(int)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned int)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(short)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned short)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(long)) { + avalue = boost::any_cast(value); + } + else if (value.type() == typeid(unsigned long)) { + avalue = boost::any_cast(value); + } + else { throw std::bad_cast(); + } return avalue; } -} +} // namespace -void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyPlacement::setPathValue(const ObjectIdentifier& path, const boost::any& value) { auto updateAxis = [this](int index, double coord) { Base::Vector3d axis; @@ -615,18 +643,21 @@ void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost:: double yaw, pitch, roll; rot.getYawPitchRoll(yaw, pitch, roll); if (index == 0) { - if (angle < -180.0 || angle > 180.0) + if (angle < -180.0 || angle > 180.0) { throw Base::ValueError("Yaw angle is out of range [-180, +180]"); + } yaw = angle; } else if (index == 1) { - if (angle < -90.0 || angle > 90.0) + if (angle < -90.0 || angle > 90.0) { throw Base::ValueError("Pitch angle is out of range [-90, +90]"); + } pitch = angle; } else if (index == 2) { - if (angle < -180.0 || angle > 180.0) + if (angle < -180.0 || angle > 180.0) { throw Base::ValueError("Roll angle is out of range [-180, +180]"); + } roll = angle; } rot.setYawPitchRoll(yaw, pitch, roll); @@ -662,7 +693,7 @@ void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost:: } } -const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier& path) const { auto getAxis = [](const Base::Placement& plm) { Base::Vector3d axis; @@ -683,7 +714,9 @@ const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) c if (p == ".Rotation.Angle") { // Convert angle to degrees - return Base::Quantity(Base::toDegrees(boost::any_cast(Property::getPathValue(path))), Unit::Angle); + return Base::Quantity( + Base::toDegrees(boost::any_cast(Property::getPathValue(path))), + Unit::Angle); } else if (p == ".Base.x" || p == ".Base.y" || p == ".Base.z") { // Convert double to quantity @@ -712,7 +745,7 @@ const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) c } } -bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyPlacement::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { auto getAxis = [](const Base::Placement& plm) { Base::Vector3d axis; @@ -731,21 +764,22 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object std::string p = path.getSubPathStr(); if (p == ".Rotation.Angle") { - Base::Vector3d axis; double angle; - _cPos.getRotation().getValue(axis,angle); - res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle))); + Base::Vector3d axis; + double angle; + _cPos.getRotation().getValue(axis, angle); + res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle), Unit::Angle))); return true; } else if (p == ".Base.x") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x, Unit::Length))); return true; } else if (p == ".Base.y") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y, Unit::Length))); return true; } else if (p == ".Base.z") { - res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length))); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z, Unit::Length))); return true; } else if (p == ".Rotation.Axis.x") { @@ -776,15 +810,15 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object return false; } -PyObject *PropertyPlacement::getPyObject() +PyObject* PropertyPlacement::getPyObject() { return new Base::PlacementPy(new Base::Placement(_cPos)); } -void PropertyPlacement::setPyObject(PyObject *value) +void PropertyPlacement::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *pcObject = static_cast(value); + Base::MatrixPy* pcObject = static_cast(value); Base::Matrix4D mat = pcObject->value(); Base::Placement p; p.fromMatrix(mat); @@ -800,28 +834,30 @@ void PropertyPlacement::setPyObject(PyObject *value) } } -void PropertyPlacement::Save (Base::Writer &writer) const +void PropertyPlacement::Save(Base::Writer& writer) const { + // clang-format off writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << " A=\"" << rfAngle << "\"" + << " Ox=\"" << axis.x << "\"" + << " Oy=\"" << axis.y << "\"" + << " Oz=\"" << axis.z << "\""; + writer.Stream() << "/>" << std::endl; + // clang-format on } -void PropertyPlacement::Restore(Base::XMLReader &reader) +void PropertyPlacement::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyPlacement"); @@ -832,10 +868,10 @@ void PropertyPlacement::Restore(Base::XMLReader &reader) _cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"), reader.getAttributeAsFloat("Py"), reader.getAttributeAsFloat("Pz")), - Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), - reader.getAttributeAsFloat("Oy"), - reader.getAttributeAsFloat("Oz")), - reader.getAttributeAsFloat("A"))); + Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), + reader.getAttributeAsFloat("Oy"), + reader.getAttributeAsFloat("Oz")), + reader.getAttributeAsFloat("A"))); } else { _cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"), @@ -851,14 +887,14 @@ void PropertyPlacement::Restore(Base::XMLReader &reader) } -Property *PropertyPlacement::Copy() const +Property* PropertyPlacement::Copy() const { - PropertyPlacement *p= new PropertyPlacement(); + PropertyPlacement* p = new PropertyPlacement(); p->_cPos = _cPos; return p; } -void PropertyPlacement::Paste(const Property &from) +void PropertyPlacement::Paste(const Property& from) { aboutToSetValue(); _cPos = dynamic_cast(from)._cPos; @@ -870,7 +906,7 @@ void PropertyPlacement::Paste(const Property &from) // PropertyPlacementList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacementList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyPlacementList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -882,53 +918,57 @@ PropertyPlacementList::~PropertyPlacementList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyPlacementList::getPyObject() +PyObject* PropertyPlacementList::getPyObject() { - PyObject* list = PyList_New( getSize() ); + PyObject* list = PyList_New(getSize()); - for (int i = 0;i" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } } -void PropertyPlacementList::Restore(Base::XMLReader &reader) +void PropertyPlacementList::Restore(Base::XMLReader& reader) { reader.readElement("PlacementList"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void PropertyPlacementList::SaveDocFile (Base::Writer &writer) const +void PropertyPlacementList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); str << uCt; if (!isSinglePrecision()) { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { str << it.getPosition().x << it.getPosition().y << it.getPosition().z - << it.getRotation()[0] << it.getRotation()[1] << it.getRotation()[2] << it.getRotation()[3] ; + << it.getRotation()[0] << it.getRotation()[1] << it.getRotation()[2] + << it.getRotation()[3]; } } else { - for (const auto & it : _lValueList) { + for (const auto& it : _lValueList) { float x = (float)it.getPosition().x; float y = (float)it.getPosition().y; float z = (float)it.getPosition().z; @@ -941,28 +981,29 @@ void PropertyPlacementList::SaveDocFile (Base::Writer &writer) const } } -void PropertyPlacementList::RestoreDocFile(Base::Reader &reader) +void PropertyPlacementList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (auto & it : values) { + for (auto& it : values) { Base::Vector3d pos; double q0, q1, q2, q3; str >> pos.x >> pos.y >> pos.z >> q0 >> q1 >> q2 >> q3; - Base::Rotation rot(q0,q1,q2,q3); + Base::Rotation rot(q0, q1, q2, q3); it.setPosition(pos); it.setRotation(rot); } } else { - float x,y,z,q0,q1,q2,q3; - for (auto & it : values) { + float x {}, y {}, z {}; + float q0 {}, q1 {}, q2 {}, q3 {}; + for (auto& it : values) { str >> x >> y >> z >> q0 >> q1 >> q2 >> q3; Base::Vector3d pos(x, y, z); - Base::Rotation rot(q0,q1,q2,q3); + Base::Rotation rot(q0, q1, q2, q3); it.setPosition(pos); it.setRotation(rot); } @@ -970,32 +1011,30 @@ void PropertyPlacementList::RestoreDocFile(Base::Reader &reader) setValues(values); } -Property *PropertyPlacementList::Copy() const +Property* PropertyPlacementList::Copy() const { - PropertyPlacementList *p= new PropertyPlacementList(); + PropertyPlacementList* p = new PropertyPlacementList(); p->_lValueList = _lValueList; return p; } -void PropertyPlacementList::Paste(const Property &from) +void PropertyPlacementList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyPlacementList::getMemSize () const +unsigned int PropertyPlacementList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Base::Vector3d)); } - - //************************************************************************** //************************************************************************** // PropertyPlacement //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPlacementLink , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyPlacementLink, App::PropertyLink) //************************************************************************** // Construction/Destruction @@ -1006,26 +1045,27 @@ PropertyPlacementLink::PropertyPlacementLink() = default; PropertyPlacementLink::~PropertyPlacementLink() = default; -App::Placement * PropertyPlacementLink::getPlacementObject() const +App::Placement* PropertyPlacementLink::getPlacementObject() const { - if (_pcLink->isDerivedFrom()) + if (_pcLink->isDerivedFrom()) { return dynamic_cast(_pcLink); - else + } + else { return nullptr; - + } } //************************************************************************** // Base class implementer -Property *PropertyPlacementLink::Copy() const +Property* PropertyPlacementLink::Copy() const { - PropertyPlacementLink *p= new PropertyPlacementLink(); + PropertyPlacementLink* p = new PropertyPlacementLink(); p->_pcLink = _pcLink; return p; } -void PropertyPlacementLink::Paste(const Property &from) +void PropertyPlacementLink::Paste(const Property& from) { aboutToSetValue(); _pcLink = dynamic_cast(from)._pcLink; @@ -1037,21 +1077,21 @@ void PropertyPlacementLink::Paste(const Property &from) // PropertyRotation //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyRotation , App::Property) +TYPESYSTEM_SOURCE(App::PropertyRotation, App::Property) PropertyRotation::PropertyRotation() = default; PropertyRotation::~PropertyRotation() = default; -void PropertyRotation::setValue(const Base::Rotation &rot) +void PropertyRotation::setValue(const Base::Rotation& rot) { aboutToSetValue(); _rot = rot; hasSetValue(); } -bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol) +bool PropertyRotation::setValueIfChanged(const Base::Rotation& rot, double atol) { if (_rot.isSame(rot, atol)) { return false; @@ -1062,12 +1102,12 @@ bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol) } -const Base::Rotation & PropertyRotation::getValue() const +const Base::Rotation& PropertyRotation::getValue() const { return _rot; } -void PropertyRotation::getPaths(std::vector &paths) const +void PropertyRotation::getPaths(std::vector& paths) const { paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle"))); @@ -1082,7 +1122,7 @@ void PropertyRotation::getPaths(std::vector &paths) const << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z"))); } -void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyRotation::setPathValue(const ObjectIdentifier& path, const boost::any& value) { auto updateAxis = [this](int index, double coord) { Base::Vector3d axis; @@ -1090,7 +1130,7 @@ void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::a _rot.getRawValue(axis, angle); axis[index] = coord; - setValue(Base::Rotation{axis, angle}); + setValue(Base::Rotation {axis, angle}); }; std::string subpath = path.getSubPathStr(); @@ -1112,7 +1152,7 @@ void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::a } } -const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyRotation::getPathValue(const ObjectIdentifier& path) const { auto getAxis = [](const Base::Rotation& rot) { Base::Vector3d axis; @@ -1124,7 +1164,9 @@ const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) co if (p == ".Angle") { // Convert angle to degrees - return Base::Quantity(Base::toDegrees(boost::any_cast(Property::getPathValue(path))), Unit::Angle); + return Base::Quantity( + Base::toDegrees(boost::any_cast(Property::getPathValue(path))), + Unit::Angle); } else if (p == ".Axis.x") { return getAxis(_rot).x; @@ -1140,7 +1182,7 @@ const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) co } } -bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const +bool PropertyRotation::getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const { auto getAxis = [](const Base::Rotation& rot) { Base::Vector3d axis; @@ -1151,9 +1193,10 @@ bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object & std::string p = path.getSubPathStr(); if (p == ".Angle") { - Base::Vector3d axis; double angle; - _rot.getValue(axis,angle); - res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle))); + Base::Vector3d axis; + double angle; + _rot.getValue(axis, angle); + res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle), Unit::Angle))); return true; } else if (p == ".Axis.x") { @@ -1172,15 +1215,15 @@ bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object & return false; } -PyObject *PropertyRotation::getPyObject() +PyObject* PropertyRotation::getPyObject() { return new Base::RotationPy(new Base::Rotation(_rot)); } -void PropertyRotation::setPyObject(PyObject *value) +void PropertyRotation::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) { - Base::MatrixPy *object = static_cast(value); + Base::MatrixPy* object = static_cast(value); Base::Matrix4D mat = object->value(); Base::Rotation p; p.setValue(mat); @@ -1196,21 +1239,21 @@ void PropertyRotation::setPyObject(PyObject *value) } } -void PropertyRotation::Save (Base::Writer &writer) const +void PropertyRotation::Save(Base::Writer& writer) const { Vector3d axis; - double rfAngle; + double rfAngle {}; _rot.getRawValue(axis, rfAngle); writer.Stream() << writer.ind() << "\n"; } -void PropertyRotation::Restore(Base::XMLReader &reader) +void PropertyRotation::Restore(Base::XMLReader& reader) { reader.readElement("PropertyRotation"); aboutToSetValue(); @@ -1218,18 +1261,18 @@ void PropertyRotation::Restore(Base::XMLReader &reader) _rot = Rotation(Vector3d(reader.getAttributeAsFloat("Ox"), reader.getAttributeAsFloat("Oy"), reader.getAttributeAsFloat("Oz")), - reader.getAttributeAsFloat("A")); + reader.getAttributeAsFloat("A")); hasSetValue(); } -Property *PropertyRotation::Copy() const +Property* PropertyRotation::Copy() const { - PropertyRotation *p = new PropertyRotation(); + PropertyRotation* p = new PropertyRotation(); p->_rot = _rot; return p; } -void PropertyRotation::Paste(const Property &from) +void PropertyRotation::Paste(const Property& from) { aboutToSetValue(); _rot = dynamic_cast(from)._rot; @@ -1238,7 +1281,7 @@ void PropertyRotation::Paste(const Property &from) // ------------------------------------------------------------ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry , App::Property) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry, App::Property) PropertyGeometry::PropertyGeometry() = default; @@ -1246,43 +1289,49 @@ PropertyGeometry::~PropertyGeometry() = default; // ------------------------------------------------------------ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData , App::PropertyGeometry) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData, App::PropertyGeometry) PropertyComplexGeoData::PropertyComplexGeoData() = default; PropertyComplexGeoData::~PropertyComplexGeoData() = default; -std::string PropertyComplexGeoData::getElementMapVersion(bool) const { +std::string PropertyComplexGeoData::getElementMapVersion(bool) const +{ auto data = getComplexData(); - if(!data) + if (!data) { return std::string(); + } auto owner = Base::freecad_dynamic_cast(getContainer()); std::ostringstream ss; - if(owner && owner->getDocument() - && owner->getDocument()->getStringHasher()==data->Hasher) + if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { ss << "1."; - else + } + else { ss << "0."; + } ss << data->getElementMapVersion(); return ss.str(); } -bool PropertyComplexGeoData::checkElementMapVersion(const char * ver) const +bool PropertyComplexGeoData::checkElementMapVersion(const char* ver) const { auto data = getComplexData(); - if(!data) + if (!data) { return false; + } auto owner = Base::freecad_dynamic_cast(getContainer()); std::ostringstream ss; - const char *prefix; - if(owner && owner->getDocument() - && owner->getDocument()->getStringHasher() == data->Hasher) + const char* prefix; + if (owner && owner->getDocument() && owner->getDocument()->getStringHasher() == data->Hasher) { prefix = "1."; - else + } + else { prefix = "0."; - if (!boost::starts_with(ver, prefix)) + } + if (!boost::starts_with(ver, prefix)) { return true; - return data->checkElementMapVersion(ver+2); + } + return data->checkElementMapVersion(ver + 2); } @@ -1292,9 +1341,8 @@ void PropertyComplexGeoData::afterRestore() if (data && data->isRestoreFailed()) { data->resetRestoreFailure(); auto owner = Base::freecad_dynamic_cast(getContainer()); - if (owner && - owner->getDocument() && - !owner->getDocument()->testStatus(App::Document::PartialDoc)) { + if (owner && owner->getDocument() + && !owner->getDocument()->testStatus(App::Document::PartialDoc)) { owner->getDocument()->addRecomputeObject(owner); } } diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index d6c78f0a52e8..b335469f8dc9 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -34,11 +34,13 @@ #include -namespace Base { +namespace Base +{ class Writer; } -namespace Data { +namespace Data +{ class ComplexGeoData; } @@ -47,7 +49,6 @@ namespace App class Placement; - /** Vector properties * This is the father of all properties handling Integers. */ @@ -70,43 +71,48 @@ class AppExport PropertyVector: public Property /** Sets the property */ - void setValue(const Base::Vector3d &vec); + void setValue(const Base::Vector3d& vec); void setValue(double x, double y, double z); /// Get valid paths for this property; used by auto completer - void getPaths(std::vector &paths) const override; + void getPaths(std::vector& paths) const override; /** This method returns a string representation of the property */ - const Base::Vector3d &getValue() const; - const char* getEditorName() const override { + const Base::Vector3d& getValue() const; + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyVectorItem"; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override { + unsigned int getMemSize() const override + { return sizeof(Base::Vector3d); } - const boost::any getPathValue(const ObjectIdentifier &path) const override; + const boost::any getPathValue(const ObjectIdentifier& path) const override; - bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override; + bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override; - virtual Base::Unit getUnit() const { + virtual Base::Unit getUnit() const + { return {}; } - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return getTypeId() == other.getTypeId() && getValue() == dynamic_cast(&other)->getValue(); } @@ -133,11 +139,13 @@ class AppExport PropertyVectorDistance: public PropertyVector */ ~PropertyVectorDistance() override; - Base::Unit getUnit() const override { + Base::Unit getUnit() const override + { return Base::Unit::Length; } - const char* getEditorName() const override { + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyVectorDistanceItem"; } }; @@ -159,11 +167,13 @@ class AppExport PropertyPosition: public PropertyVector */ ~PropertyPosition() override; - Base::Unit getUnit() const override { + Base::Unit getUnit() const override + { return Base::Unit::Length; } - const char* getEditorName() const override { + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyPositionItem"; } }; @@ -185,11 +195,13 @@ class AppExport PropertyDirection: public PropertyVector */ ~PropertyDirection() override; - Base::Unit getUnit() const override { + Base::Unit getUnit() const override + { return Base::Unit::Length; } - const char* getEditorName() const override { + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyDirectionItem"; } }; @@ -216,24 +228,25 @@ class AppExport PropertyVectorList: public PropertyListsT void setValue(double x, double y, double z); using inherited::setValue; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override; - const char* getEditorName() const override { + unsigned int getMemSize() const override; + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyVectorListItem"; } protected: - Base::Vector3d getPyValue(PyObject *) const override; + Base::Vector3d getPyValue(PyObject*) const override; }; /// Property representing a 4x4 matrix @@ -259,31 +272,35 @@ class AppExport PropertyMatrix: public Property /** Sets the property */ - void setValue(const Base::Matrix4D &mat); + void setValue(const Base::Matrix4D& mat); /** This method returns a string representation of the property */ - const Base::Matrix4D &getValue() const; - const char* getEditorName() const override { + const Base::Matrix4D& getValue() const; + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyMatrixItem"; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override { + unsigned int getMemSize() const override + { return sizeof(Base::Matrix4D); } - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return getTypeId() == other.getTypeId() && getValue() == static_cast(&other)->getValue(); } @@ -315,49 +332,52 @@ class AppExport PropertyPlacement: public Property /** Sets the property */ - void setValue(const Base::Placement &pos); + void setValue(const Base::Placement& pos); /** Sets property only if changed * @param pos: input placement * @param tol: position tolerance * @param atol: angular tolerance */ - bool setValueIfChanged(const Base::Placement &pos, - double tol=1e-7, double atol=1e-12); + bool setValueIfChanged(const Base::Placement& pos, double tol = 1e-7, double atol = 1e-12); /** This method returns a string representation of the property */ - const Base::Placement &getValue() const; + const Base::Placement& getValue() const; /// Get valid paths for this property; used by auto completer - void getPaths(std::vector &paths) const override; + void getPaths(std::vector& paths) const override; - void setPathValue(const ObjectIdentifier &path, const boost::any &value) override; + void setPathValue(const ObjectIdentifier& path, const boost::any& value) override; - const boost::any getPathValue(const ObjectIdentifier &path) const override; + const boost::any getPathValue(const ObjectIdentifier& path) const override; - bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override; + bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override; - const char* getEditorName() const override { + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyPlacementItem"; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override { + unsigned int getMemSize() const override + { return sizeof(Base::Placement); } - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return getTypeId() == other.getTypeId() && getValue() == static_cast(&other)->getValue(); } @@ -371,7 +391,7 @@ class AppExport PropertyPlacement: public Property /** the general Link Property * Main Purpose of this property is to Link Objects and Features in a document. */ -class AppExport PropertyPlacementLink : public PropertyLink +class AppExport PropertyPlacementLink: public PropertyLink { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -390,10 +410,10 @@ class AppExport PropertyPlacementLink : public PropertyLink /** This method returns the linked DocumentObject */ - App::Placement * getPlacementObject() const; + App::Placement* getPlacementObject() const; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; }; @@ -409,21 +429,21 @@ class AppExport PropertyPlacementList: public PropertyListsT ~PropertyPlacementList() override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; protected: - Base::Placement getPyValue(PyObject *) const override; + Base::Placement getPyValue(PyObject* item) const override; }; @@ -431,7 +451,7 @@ class AppExport PropertyPlacementList: public PropertyListsT /*! * Encapsulates a Base::Rotation in a Property */ -class AppExport PropertyRotation : public Property +class AppExport PropertyRotation: public Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -450,42 +470,44 @@ class AppExport PropertyRotation : public Property /** Sets the property */ - void setValue(const Base::Rotation &rot); + void setValue(const Base::Rotation& rot); /** Sets property only if changed * @param pos: input placement * @param tol: position tolerance * @param atol: angular tolerance */ - bool setValueIfChanged(const Base::Rotation &rot, double atol=1e-12); + bool setValueIfChanged(const Base::Rotation& rot, double atol = 1e-12); /** This method returns a string representation of the property */ - const Base::Rotation &getValue() const; + const Base::Rotation& getValue() const; /// Get valid paths for this property; used by auto completer - void getPaths(std::vector &paths) const override; + void getPaths(std::vector& paths) const override; - void setPathValue(const ObjectIdentifier &path, const boost::any &value) override; + void setPathValue(const ObjectIdentifier& path, const boost::any& value) override; - const boost::any getPathValue(const ObjectIdentifier &path) const override; + const boost::any getPathValue(const ObjectIdentifier& path) const override; - bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override; + bool getPyPathValue(const ObjectIdentifier& path, Py::Object& res) const override; - const char* getEditorName() const override { + const char* getEditorName() const override + { return "Gui::PropertyEditor::PropertyRotationItem"; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override { + unsigned int getMemSize() const override + { return sizeof(Base::Placement); } @@ -497,7 +519,7 @@ class AppExport PropertyRotation : public Property /** The base class for all basic geometry properties. * @author Werner Mayer */ -class AppExport PropertyGeometry : public App::Property +class AppExport PropertyGeometry: public App::Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -512,7 +534,7 @@ class AppExport PropertyGeometry : public App::Property /// Get the placement of the geometry virtual Base::Matrix4D getTransform() const = 0; /// Applies a transformation on the real geometric data type - virtual void transformGeometry(const Base::Matrix4D &rclMat) = 0; + virtual void transformGeometry(const Base::Matrix4D& rclMat) = 0; /// Retrieve bounding box information virtual Base::BoundBox3d getBoundingBox() const = 0; //@} @@ -521,7 +543,7 @@ class AppExport PropertyGeometry : public App::Property /** The base class for all complex data properties. * @author Werner Mayer */ -class AppExport PropertyComplexGeoData : public App::PropertyGeometry +class AppExport PropertyComplexGeoData: public App::PropertyGeometry { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -532,7 +554,7 @@ class AppExport PropertyComplexGeoData : public App::PropertyGeometry /** @name Modification */ //@{ /// Applies a transformation on the real geometric data type - void transformGeometry(const Base::Matrix4D &rclMat) override = 0; + void transformGeometry(const Base::Matrix4D& rclMat) override = 0; //@} /** @name Getting basic geometric entities */ @@ -546,15 +568,15 @@ class AppExport PropertyComplexGeoData : public App::PropertyGeometry * @param persisted: if true, return the restored element map version. Or * else, return the current element map version */ - virtual std::string getElementMapVersion(bool restored=false) const; + virtual std::string getElementMapVersion(bool restored = false) const; /// Return true to signal element map version change - virtual bool checkElementMapVersion(const char * ver) const; + virtual bool checkElementMapVersion(const char* ver) const; void afterRestore() override; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYGEO_H +#endif // APP_PROPERTYGEO_H diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 4fd812f8ce67..3ba3b5984fee 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -43,7 +43,7 @@ #include "GeoFeature.h" -FC_LOG_LEVEL_INIT("PropertyLinks",true,true) +FC_LOG_LEVEL_INIT("PropertyLinks", true, true) using namespace App; using namespace Base; @@ -55,45 +55,54 @@ namespace sp = std::placeholders; // PropertyLinkBase //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkBase , App::Property) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkBase, App::Property) -static std::unordered_map > _LabelMap; - -static std::unordered_map > _ElementRefMap; +// clang-format off +static std::unordered_map> _LabelMap; +static std::unordered_map> _ElementRefMap; +// clang-format on PropertyLinkBase::PropertyLinkBase() = default; -PropertyLinkBase::~PropertyLinkBase() { +PropertyLinkBase::~PropertyLinkBase() +{ unregisterLabelReferences(); unregisterElementReference(); } -void PropertyLinkBase::setAllowExternal(bool allow) { - setFlag(LinkAllowExternal,allow); +void PropertyLinkBase::setAllowExternal(bool allow) +{ + setFlag(LinkAllowExternal, allow); } -void PropertyLinkBase::setSilentRestore(bool allow) { +void PropertyLinkBase::setSilentRestore(bool allow) +{ setFlag(LinkSilentRestore, allow); } -void PropertyLinkBase::setReturnNewElement(bool enable) { +void PropertyLinkBase::setReturnNewElement(bool enable) +{ setFlag(LinkNewElement, enable); } -void PropertyLinkBase::hasSetValue() { +void PropertyLinkBase::hasSetValue() +{ auto owner = dynamic_cast(getContainer()); - if(owner) + if (owner) { owner->clearOutListCache(); + } Property::hasSetValue(); } -bool PropertyLinkBase::isSame(const Property &other) const +bool PropertyLinkBase::isSame(const Property& other) const { - if(&other == this) + if (&other == this) { return true; - if(other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) - || getScope() != static_cast(&other)->getScope()) + } + if (other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) + || getScope() != static_cast(&other)->getScope()) { return false; + } static std::vector ret; static std::vector subs; @@ -104,13 +113,14 @@ bool PropertyLinkBase::isSame(const Property &other) const subs.clear(); ret2.clear(); subs2.clear(); - getLinks(ret,true,&subs,false); - static_cast(&other)->getLinks(ret2,true,&subs2,true); + getLinks(ret, true, &subs, false); + static_cast(&other)->getLinks(ret2, true, &subs2, true); - return ret==ret2 && subs==subs2; + return ret == ret2 && subs == subs2; } -void PropertyLinkBase::unregisterElementReference() { +void PropertyLinkBase::unregisterElementReference() +{ for (auto obj : _ElementRefs) { auto it = _ElementRefMap.find(obj); if (it != _ElementRefMap.end()) { @@ -125,102 +135,123 @@ void PropertyLinkBase::unregisterElementReference() { void PropertyLinkBase::unregisterLabelReferences() { - for(auto &label : _LabelRefs) { + for (auto& label : _LabelRefs) { auto it = _LabelMap.find(label); - if(it!=_LabelMap.end()) { + if (it != _LabelMap.end()) { it->second.erase(this); - if(it->second.empty()) + if (it->second.empty()) { _LabelMap.erase(it); + } } } _LabelRefs.clear(); } -void PropertyLinkBase::getLabelReferences(std::vector &subs,const char *subname) { - const char *dot; +void PropertyLinkBase::getLabelReferences(std::vector& subs, const char* subname) +{ + const char* dot; for (; (subname = strchr(subname, '$')) != nullptr; subname = dot + 1) { ++subname; - dot = strchr(subname,'.'); - if(!dot) break; - subs.emplace_back(subname,dot-subname); + dot = strchr(subname, '.'); + if (!dot) { + break; + } + subs.emplace_back(subname, dot - subname); } } -void PropertyLinkBase::registerLabelReferences(std::vector &&labels, bool reset) { - if(reset) +void PropertyLinkBase::registerLabelReferences(std::vector&& labels, bool reset) +{ + if (reset) { unregisterLabelReferences(); - for(auto &label : labels) { + } + for (auto& label : labels) { auto res = _LabelRefs.insert(std::move(label)); - if(res.second) + if (res.second) { _LabelMap[*res.first].insert(this); + } } } -void PropertyLinkBase::checkLabelReferences(const std::vector &subs, bool reset) { - if(reset) +void PropertyLinkBase::checkLabelReferences(const std::vector& subs, bool reset) +{ + if (reset) { unregisterLabelReferences(); + } std::vector labels; - for(auto &sub : subs) { + for (auto& sub : subs) { labels.clear(); - getLabelReferences(labels,sub.c_str()); - registerLabelReferences(std::move(labels),false); + getLabelReferences(labels, sub.c_str()); + registerLabelReferences(std::move(labels), false); } } -std::string PropertyLinkBase::updateLabelReference(const App::DocumentObject *parent, - const char *subname, App::DocumentObject *obj, const std::string &ref, const char *newLabel) +std::string PropertyLinkBase::updateLabelReference(const App::DocumentObject* parent, + const char* subname, + App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) { - if(!obj || !obj->isAttachedToDocument() || !parent || !parent->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument() || !parent || !parent->isAttachedToDocument()) { return {}; + } // Because the label is allowed to be the same across different // hierarchies, we have to search for all occurrences, and make sure the // referenced sub-object at the found hierarchy is actually the given // object. - for (const char *pos = subname; ((pos = strstr(pos, ref.c_str())) != nullptr); pos += ref.size()) { - auto sub = std::string(subname,pos+ref.size()-subname); + for (const char* pos = subname; ((pos = strstr(pos, ref.c_str())) != nullptr); + pos += ref.size()) { + auto sub = std::string(subname, pos + ref.size() - subname); auto sobj = parent->getSubObject(sub.c_str()); - if(sobj == obj) { + if (sobj == obj) { sub = subname; - sub.replace(pos+1-subname,ref.size()-2,newLabel); + sub.replace(pos + 1 - subname, ref.size() - 2, newLabel); return sub; } } return {}; } -std::vector > > -PropertyLinkBase::updateLabelReferences(App::DocumentObject *obj, const char *newLabel) +std::vector>> +PropertyLinkBase::updateLabelReferences(App::DocumentObject* obj, const char* newLabel) { - std::vector > > ret; - if(!obj || !obj->isAttachedToDocument()) + std::vector>> ret; + if (!obj || !obj->isAttachedToDocument()) { return ret; + } auto it = _LabelMap.find(obj->Label.getStrValue()); - if(it == _LabelMap.end()) + if (it == _LabelMap.end()) { return ret; + } std::string ref("$"); ref += obj->Label.getValue(); ref += '.'; std::vector props; props.reserve(it->second.size()); - props.insert(props.end(),it->second.begin(),it->second.end()); - for(auto prop : props) { - if(!prop->getContainer()) + props.insert(props.end(), it->second.begin(), it->second.end()); + for (auto prop : props) { + if (!prop->getContainer()) { continue; - std::unique_ptr copy(prop->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) - ret.emplace_back(prop,std::move(copy)); + } + std::unique_ptr copy(prop->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { + ret.emplace_back(prop, std::move(copy)); + } } return ret; } -static std::string propertyName(const Property *prop) { - if(!prop) +static std::string propertyName(const Property* prop) +{ + if (!prop) { return {}; - if(!prop->getContainer() || !prop->hasName()) { + } + if (!prop->getContainer() || !prop->hasName()) { auto xlink = Base::freecad_dynamic_cast(prop); - if(xlink) + if (xlink) { return propertyName(xlink->parent()); + } } return prop->getFullName(); } @@ -238,7 +269,8 @@ PropertyLinkBase::getElementReferences(DocumentObject* feature) return it->second; } -void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool reverse) { +void PropertyLinkBase::updateElementReferences(DocumentObject* feature, bool reverse) +{ if (!feature || !feature->getNameInDocument()) { return; } @@ -266,7 +298,9 @@ void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool rev } } -void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow) +void PropertyLinkBase::_registerElementReference(App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow) { if (!obj || !obj->getNameInDocument() || sub.empty()) { return; @@ -295,10 +329,11 @@ void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std:: } } -class StringGuard { +class StringGuard +{ public: - explicit StringGuard(char *c) - :c(c) + explicit StringGuard(char* c) + : c(c) { v1 = c[0]; v2 = c[1]; @@ -311,51 +346,60 @@ class StringGuard { c[1] = v2; } - char *c; + char* c; char v1; char v2; }; -void PropertyLinkBase::restoreLabelReference(const DocumentObject *obj, - std::string &subname, ShadowSub *shadow) +void PropertyLinkBase::restoreLabelReference(const DocumentObject* obj, + std::string& subname, + ShadowSub* shadow) { std::ostringstream ss; - char *sub = &subname[0]; - char *next=sub; - for(char *dot=strchr(next,'.');dot;next=dot+1,dot=strchr(next,'.')) { - if(dot!=next && dot[-1]!='@') + char* sub = &subname[0]; + char* next = sub; + for (char* dot = strchr(next, '.'); dot; next = dot + 1, dot = strchr(next, '.')) { + if (dot != next && dot[-1] != '@') { continue; - DocumentObject *sobj; + } + DocumentObject* sobj; try { - StringGuard guard(dot-1); + StringGuard guard(dot - 1); sobj = obj->getSubObject(subname.c_str()); - if(!sobj) { - FC_ERR("Failed to restore label reference " << obj->getFullName() - << '.' << ss.str()); + if (!sobj) { + FC_ERR("Failed to restore label reference " << obj->getFullName() << '.' + << ss.str()); return; } - }catch(...){ + } + catch (...) { throw; } - ss.write(sub,next-sub); + ss.write(sub, next - sub); ss << '$' << sobj->Label.getStrValue() << '.'; - sub = dot+1; + sub = dot + 1; } - if(sub == subname.c_str()) + if (sub == subname.c_str()) { return; + } - size_t count = sub-subname.c_str(); - const auto &newSub = ss.str(); - if(shadow && shadow->oldName.size()>=count) - shadow->oldName = newSub + (shadow->oldName.c_str()+count); - if(shadow && shadow->newName.size()>=count) - shadow->newName = newSub + (shadow->newName.c_str()+count); + size_t count = sub - subname.c_str(); + const auto& newSub = ss.str(); + if (shadow && shadow->oldName.size() >= count) { + shadow->oldName = newSub + (shadow->oldName.c_str() + count); + } + if (shadow && shadow->newName.size() >= count) { + shadow->newName = newSub + (shadow->newName.c_str() + count); + } subname = newSub + sub; } -bool PropertyLinkBase::_updateElementReference(DocumentObject *feature, - App::DocumentObject *obj, std::string &sub, ShadowSub &shadow, - bool reverse, bool notify) +bool PropertyLinkBase::_updateElementReference(DocumentObject* feature, + App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow, + bool reverse, + bool notify) { if (!obj || !obj->getNameInDocument()) { return false; @@ -575,32 +619,38 @@ PropertyLinkBase::tryReplaceLink(const PropertyContainer* owner, return res; } -std::pair > -PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer *owner, - DocumentObject *obj, const DocumentObject *parent, DocumentObject *oldObj, - DocumentObject *newObj, const std::vector &subs) +std::pair> +PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer* owner, + DocumentObject* obj, + const DocumentObject* parent, + DocumentObject* oldObj, + DocumentObject* newObj, + const std::vector& subs) { - std::pair > res; + std::pair> res; res.first = 0; - if (!obj) + if (!obj) { return res; + } - auto r = tryReplaceLink(owner,obj,parent,oldObj,newObj); - if(r.first) { + auto r = tryReplaceLink(owner, obj, parent, oldObj, newObj); + if (r.first) { res.first = r.first; res.second = subs; return res; } - for(auto it=subs.begin();it!=subs.end();++it) { - auto r = tryReplaceLink(owner,obj,parent,oldObj,newObj,it->c_str()); - if(r.first) { - if(!res.first) { + for (auto it = subs.begin(); it != subs.end(); ++it) { + auto r = tryReplaceLink(owner, obj, parent, oldObj, newObj, it->c_str()); + if (r.first) { + if (!res.first) { res.first = r.first; - res.second.insert(res.second.end(),subs.begin(),it); + res.second.insert(res.second.end(), subs.begin(), it); } res.second.push_back(std::move(r.second)); - }else if(res.first) + } + else if (res.first) { res.second.push_back(*it); + } } return res; } @@ -610,7 +660,7 @@ PropertyLinkBase::tryReplaceLinkSubs(const PropertyContainer *owner, // PropertyLinkListBase //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase , App::PropertyLinkBase) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase, App::PropertyLinkBase) //************************************************************************** //************************************************************************** @@ -618,15 +668,16 @@ TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyLinkListBase , App::PropertyLinkBase) //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TYPESYSTEM_SOURCE(App::PropertyLink, App::PropertyLinkBase) -TYPESYSTEM_SOURCE(App::PropertyLinkChild , App::PropertyLink) -TYPESYSTEM_SOURCE(App::PropertyLinkGlobal , App::PropertyLink) -TYPESYSTEM_SOURCE(App::PropertyLinkHidden , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkChild, App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkGlobal, App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyLinkHidden, App::PropertyLink) //************************************************************************** // Construction/Destruction PropertyLink::PropertyLink() = default; + PropertyLink::~PropertyLink() { resetLink(); @@ -635,74 +686,79 @@ PropertyLink::~PropertyLink() //************************************************************************** // Base class implementer -void PropertyLink::resetLink() { - //in case this property gets dynamically removed +void PropertyLink::resetLink() +{ + // in case this property gets dynamically removed #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if it is from a document object - if (_pcScope!=LinkScope::Hidden && - _pcLink && - getContainer() && - getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - { + if (_pcScope != LinkScope::Hidden && _pcLink && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - if (_pcLink) + if (_pcLink) { _pcLink->_removeBackLink(parent); + } } } #endif _pcLink = nullptr; } -void PropertyLink::setValue(App::DocumentObject * lValue) +void PropertyLink::setValue(App::DocumentObject* lValue) { auto parent = dynamic_cast(getContainer()); - if(!testFlag(LinkAllowExternal) && parent && lValue && parent->getDocument()!=lValue->getDocument()) + if (!testFlag(LinkAllowExternal) && parent && lValue + && parent->getDocument() != lValue->getDocument()) { throw Base::ValueError("PropertyLink does not support external object"); + } aboutToSetValue(); #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if it is from a document object - if (_pcScope!=LinkScope::Hidden && parent) { + if (_pcScope != LinkScope::Hidden && parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - if (_pcLink) + if (_pcLink) { _pcLink->_removeBackLink(parent); - if (lValue) + } + if (lValue) { lValue->_addBackLink(parent); + } } } #endif - _pcLink=lValue; + _pcLink = lValue; hasSetValue(); } -App::DocumentObject * PropertyLink::getValue() const +App::DocumentObject* PropertyLink::getValue() const { return _pcLink; } -App::DocumentObject * PropertyLink::getValue(Base::Type t) const +App::DocumentObject* PropertyLink::getValue(Base::Type t) const { return (_pcLink && _pcLink->getTypeId().isDerivedFrom(t)) ? _pcLink : nullptr; } -PyObject *PropertyLink::getPyObject() +PyObject* PropertyLink::getPyObject() { - if (_pcLink) + if (_pcLink) { return _pcLink->getPyObject(); - else + } + else { Py_Return; + } } -void PropertyLink::setPyObject(PyObject *value) +void PropertyLink::setPyObject(PyObject* value) { Base::PyTypeCheck(&value, &DocumentObjectPy::Type); if (value) { - DocumentObjectPy *pcObject = static_cast(value); + DocumentObjectPy* pcObject = static_cast(value); setValue(pcObject->getDocumentObjectPtr()); } else { @@ -710,12 +766,13 @@ void PropertyLink::setPyObject(PyObject *value) } } -void PropertyLink::Save (Base::Writer &writer) const +void PropertyLink::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "getExportName():"") <<"\"/>" << std::endl; + writer.Stream() << writer.ind() << "getExportName() : "") + << "\"/>" << std::endl; } -void PropertyLink::Restore(Base::XMLReader &reader) +void PropertyLink::Restore(Base::XMLReader& reader) { // read my element reader.readElement("Link"); @@ -723,7 +780,7 @@ void PropertyLink::Restore(Base::XMLReader &reader) std::string name = reader.getName(reader.getAttribute("value")); // Property not in a DocumentObject! - assert(getContainer()->isDerivedFrom() ); + assert(getContainer()->isDerivedFrom()); if (!name.empty()) { DocumentObject* parent = static_cast(getContainer()); @@ -733,12 +790,13 @@ void PropertyLink::Restore(Base::XMLReader &reader) if (!object) { if (reader.isVerbose()) { Base::Console().Warning("Lost link to '%s' while loading, maybe " - "an object was not loaded correctly\n",name.c_str()); + "an object was not loaded correctly\n", + name.c_str()); } } else if (parent == object) { if (reader.isVerbose()) { - Base::Console().Warning("Object '%s' links to itself, nullify it\n",name.c_str()); + Base::Console().Warning("Object '%s' links to itself, nullify it\n", name.c_str()); } object = nullptr; } @@ -750,58 +808,67 @@ void PropertyLink::Restore(Base::XMLReader &reader) } } -Property *PropertyLink::Copy() const +Property* PropertyLink::Copy() const { - PropertyLink *p= new PropertyLink(); + PropertyLink* p = new PropertyLink(); p->_pcLink = _pcLink; return p; } -void PropertyLink::Paste(const Property &from) +void PropertyLink::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLink::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLink::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } setValue(static_cast(from)._pcLink); } -void PropertyLink::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLink::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { (void)newStyle; (void)subs; - if((all||_pcScope!=LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) + if ((all || _pcScope != LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { objs.push_back(_pcLink); + } } -void PropertyLink::getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - bool all) const { - (void) subname; +void PropertyLink::getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + bool all) const +{ + (void)subname; if (!all && _pcScope == LinkScope::Hidden) { - return; // Don't get hidden links unless all is specified. + return; // Don't get hidden links unless all is specified. } if (obj && _pcLink == obj) { identifiers.emplace_back(*this); } } -void PropertyLink::breakLink(App::DocumentObject *obj, bool clear) { - if(_pcLink == obj || (clear && getContainer()==obj)) +void PropertyLink::breakLink(App::DocumentObject* obj, bool clear) +{ + if (_pcLink == obj || (clear && getContainer() == obj)) { setValue(nullptr); + } } -bool PropertyLink::adjustLink(const std::set &inList) { +bool PropertyLink::adjustLink(const std::set& inList) +{ (void)inList; return false; } -Property *PropertyLink::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLink::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLink(getContainer(),_pcLink,parent,oldObj,newObj); - if(res.first) { + auto res = tryReplaceLink(getContainer(), _pcLink, parent, oldObj, newObj); + if (res.first) { auto p = new PropertyLink(); p->_pcLink = res.first; return p; @@ -826,60 +893,64 @@ PropertyLinkList::PropertyLinkList() = default; PropertyLinkList::~PropertyLinkList() { - //in case this property gety dynamically removed + // in case this property gety dynamically removed #ifndef USE_OLD_DAG - //maintain the back link in the DocumentObject class - if (_pcScope!=LinkScope::Hidden && - !_lValueList.empty() && - getContainer() && - getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) - { + // maintain the back link in the DocumentObject class + if (_pcScope != LinkScope::Hidden && !_lValueList.empty() && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy)) { - for(auto *obj : _lValueList) { - if (obj) + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } } } #endif - } void PropertyLinkList::setSize(int newSize) { - for(int i=newSize;i<(int)_lValueList.size();++i) { + for (int i = newSize; i < (int)_lValueList.size(); ++i) { auto obj = _lValueList[i]; - if (!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } _nameMap.erase(obj->getNameInDocument()); #ifndef USE_OLD_DAG - if (_pcScope!=LinkScope::Hidden) + if (_pcScope != LinkScope::Hidden) { obj->_removeBackLink(static_cast(getContainer())); + } #endif } _lValueList.resize(newSize); } -void PropertyLinkList::setSize(int newSize, const_reference def) { +void PropertyLinkList::setSize(int newSize, const_reference def) +{ auto oldSize = getSize(); setSize(newSize); - for(auto i=oldSize;i=0 && idx<(int)_lValueList.size()) { +void PropertyLinkList::set1Value(int idx, DocumentObject* const& value) +{ + DocumentObject* obj = nullptr; + if (idx >= 0 && idx < (int)_lValueList.size()) { obj = _lValueList[idx]; - if(obj == value) + if (obj == value) { return; + } } - if(!value || !value->isAttachedToDocument()) + if (!value || !value->isAttachedToDocument()) { throw Base::ValueError("invalid document object"); + } _nameMap.clear(); @@ -888,109 +959,121 @@ void PropertyLinkList::set1Value(int idx, DocumentObject* const &value) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if(obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (obj) { obj->_removeBackLink(static_cast(getContainer())); - if(value) + } + if (value) { value->_addBackLink(static_cast(getContainer())); + } } } #endif - inherited::set1Value(idx,value); + inherited::set1Value(idx, value); } -void PropertyLinkList::setValues(const std::vector& lValue) { - if(lValue.size()==1 && !lValue[0]) { +void PropertyLinkList::setValues(const std::vector& value) +{ + if (value.size() == 1 && !value[0]) { // one null element means clear, as backward compatibility for old code setValues(std::vector()); return; } auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { - if(!obj || !obj->isAttachedToDocument()) + for (auto obj : value) { + if (!obj || !obj->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkList: invalid document object"); - if(!testFlag(LinkAllowExternal) && parent && parent->getDocument()!=obj->getDocument()) + } + if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) { throw Base::ValueError("PropertyLinkList does not support external object"); + } } _nameMap.clear(); #ifndef USE_OLD_DAG - //maintain the back link in the DocumentObject class + // maintain the back link in the DocumentObject class if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - for(auto *obj : lValue) { - if (obj) + for (auto* obj : value) { + if (obj) { obj->_addBackLink(parent); + } } } } #endif - inherited::setValues(lValue); + inherited::setValues(value); } -PyObject *PropertyLinkList::getPyObject() +PyObject* PropertyLinkList::getPyObject() { int count = getSize(); -#if 0//FIXME: Should switch to tuple +#if 0 // FIXME: Should switch to tuple Py::Tuple sequence(count); #else Py::List sequence(count); #endif - for (int i = 0; iisAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { sequence.setItem(i, Py::asObject(_lValueList[i]->getPyObject())); - else + } + else { sequence.setItem(i, Py::None()); + } } return Py::new_reference_to(sequence); } -DocumentObject *PropertyLinkList::getPyValue(PyObject *item) const +DocumentObject* PropertyLinkList::getPyValue(PyObject* item) const { Base::PyTypeCheck(&item, &DocumentObjectPy::Type); return item ? static_cast(item)->getDocumentObjectPtr() : nullptr; } -void PropertyLinkList::Save(Base::Writer &writer) const +void PropertyLinkList::Save(Base::Writer& writer) const { writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for (int i = 0; igetExportName() << "\"/>" << endl; - else + if (obj) { + writer.Stream() << writer.ind() << "getExportName() << "\"/>" + << endl; + } + else { writer.Stream() << writer.ind() << "" << endl; + } } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkList::Restore(Base::XMLReader &reader) +void PropertyLinkList::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); App::PropertyContainer* container = getContainer(); - if (!container) + if (!container) { throw Base::RuntimeError("Property is not part of a container"); + } if (!container->isDerivedFrom()) { std::stringstream str; - str << "Container is not a document object (" - << container->getTypeId().getName() << ")"; + str << "Container is not a document object (" << container->getTypeId().getName() << ")"; throw Base::TypeError(str.str()); } @@ -1006,11 +1089,13 @@ void PropertyLinkList::Restore(Base::XMLReader &reader) DocumentObject* father = static_cast(getContainer()); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : nullptr; - if (child) + if (child) { values.push_back(child); - else if (reader.isVerbose()) - FC_WARN("Lost link to " << (document?document->getName():"") << " " << name - << " while loading, maybe an object was not loaded correctly"); + } + else if (reader.isVerbose()) { + FC_WARN("Lost link to " << (document ? document->getName() : "") << " " << name + << " while loading, maybe an object was not loaded correctly"); + } } reader.readEndElement("LinkList"); @@ -1019,114 +1104,133 @@ void PropertyLinkList::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyLinkList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { std::vector links; bool copied = false; bool found = false; - for(auto it=_lValueList.begin();it!=_lValueList.end();++it) { - auto res = tryReplaceLink(getContainer(),*it,parent,oldObj,newObj); - if(res.first) { + for (auto it = _lValueList.begin(); it != _lValueList.end(); ++it) { + auto res = tryReplaceLink(getContainer(), *it, parent, oldObj, newObj); + if (res.first) { found = true; - if(!copied) { + if (!copied) { copied = true; - links.insert(links.end(),_lValueList.begin(),it); + links.insert(links.end(), _lValueList.begin(), it); } links.push_back(res.first); - } else if(*it == newObj) { + } + else if (*it == newObj) { // in case newObj already exists here, we shall remove all existing // entry, and insert it to take over oldObj's position. - if(!copied) { + if (!copied) { copied = true; - links.insert(links.end(),_lValueList.begin(),it); + links.insert(links.end(), _lValueList.begin(), it); } - }else if(copied) + } + else if (copied) { links.push_back(*it); + } } - if(!found) + if (!found) { return nullptr; - auto p= new PropertyLinkList(); + } + auto p = new PropertyLinkList(); p->_lValueList = std::move(links); return p; } -Property *PropertyLinkList::Copy() const +Property* PropertyLinkList::Copy() const { - PropertyLinkList *p = new PropertyLinkList(); + PropertyLinkList* p = new PropertyLinkList(); p->_lValueList = _lValueList; return p; } -void PropertyLinkList::Paste(const Property &from) +void PropertyLinkList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } setValues(static_cast(from)._lValueList); } unsigned int PropertyLinkList::getMemSize() const { - return static_cast(_lValueList.size() * sizeof(App::DocumentObject *)); + return static_cast(_lValueList.size() * sizeof(App::DocumentObject*)); } -DocumentObject *PropertyLinkList::find(const char *name, int *pindex) const { +DocumentObject* PropertyLinkList::find(const char* name, int* pindex) const +{ const int DONT_MAP_UNDER = 10; - if (!name) + if (!name) { return nullptr; - if(_lValueList.size() <= DONT_MAP_UNDER ) { + } + if (_lValueList.size() <= DONT_MAP_UNDER) { int index = -1; for (auto obj : _lValueList) { ++index; - if(obj && obj->getNameInDocument() - && boost::equals(name, obj->getNameInDocument())) { - if(pindex) + if (obj && obj->getNameInDocument() && boost::equals(name, obj->getNameInDocument())) { + if (pindex) { *pindex = index; + } return obj; } } return nullptr; } // We're using a map. Do we need to (re)create it? - if(_nameMap.empty() || _nameMap.size()>_lValueList.size()) { + if (_nameMap.empty() || _nameMap.size() > _lValueList.size()) { _nameMap.clear(); - for(int i=0;i<(int)_lValueList.size();++i) { + for (int i = 0; i < (int)_lValueList.size(); ++i) { auto obj = _lValueList[i]; - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { _nameMap[obj->getNameInDocument()] = i; + } } } // Now lookup up in that map auto it = _nameMap.find(name); - if(it == _nameMap.end()) + if (it == _nameMap.end()) { return nullptr; - if(pindex) *pindex = it->second; + } + if (pindex) { + *pindex = it->second; + } return _lValueList[it->second]; } -DocumentObject *PropertyLinkList::findUsingMap(const std::string &name, int *pindex) const { +DocumentObject* PropertyLinkList::findUsingMap(const std::string& name, int* pindex) const +{ if (_nameMap.size() == _lValueList.size()) { auto it = _nameMap.find(name); - if(it == _nameMap.end()) + if (it == _nameMap.end()) { return nullptr; - if(pindex) *pindex = it->second; + } + if (pindex) { + *pindex = it->second; + } return _lValueList[it->second]; } return find(name.c_str(), pindex); } -void PropertyLinkList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { (void)subs; (void)newStyle; - if(all||_pcScope!=LinkScope::Hidden) { - objs.reserve(objs.size()+_lValueList.size()); - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + if (all || _pcScope != LinkScope::Hidden) { + objs.reserve(objs.size() + _lValueList.size()); + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } } } @@ -1150,22 +1254,26 @@ void PropertyLinkList::getLinksTo(std::vector& identifier } } -void PropertyLinkList::breakLink(App::DocumentObject *obj, bool clear) { - if(clear && getContainer()==obj) { +void PropertyLinkList::breakLink(App::DocumentObject* obj, bool clear) +{ + if (clear && getContainer() == obj) { setValues({}); return; } std::vector values; values.reserve(_lValueList.size()); - for(auto o : _lValueList) { - if(o != obj) + for (auto o : _lValueList) { + if (o != obj) { values.push_back(o); + } } - if(values.size()!=_lValueList.size()) + if (values.size() != _lValueList.size()) { setValues(values); + } } -bool PropertyLinkList::adjustLink(const std::set &inList) { +bool PropertyLinkList::adjustLink(const std::set& inList) +{ (void)inList; return false; } @@ -1188,15 +1296,17 @@ PropertyLinkSub::PropertyLinkSub() = default; PropertyLinkSub::~PropertyLinkSub() { - //in case this property is dynamically removed + // in case this property is dynamically removed #ifndef USE_OLD_DAG - if (_pcLinkSub && getContainer() && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (_pcLinkSub && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if (_pcLinkSub) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (_pcLinkSub) { _pcLinkSub->_removeBackLink(parent); + } } } #endif @@ -1207,22 +1317,26 @@ void PropertyLinkSub::setSyncSubObject(bool enable) _Flags.set((std::size_t)LinkSyncSubObject, enable); } -void PropertyLinkSub::setValue(App::DocumentObject * lValue, - const std::vector &SubList, std::vector &&shadows) +void PropertyLinkSub::setValue(App::DocumentObject* lValue, + const std::vector& SubList, + std::vector&& shadows) { - setValue(lValue,std::vector(SubList),std::move(shadows)); + setValue(lValue, std::vector(SubList), std::move(shadows)); } -void PropertyLinkSub::setValue(App::DocumentObject * lValue, - std::vector &&subs, std::vector &&shadows) +void PropertyLinkSub::setValue(App::DocumentObject* lValue, + std::vector&& subs, + std::vector&& shadows) { auto parent = Base::freecad_dynamic_cast(getContainer()); if (lValue) { - if (!lValue->isAttachedToDocument()) + if (!lValue->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkSub: invalid document object"); + } if (!testFlag(LinkAllowExternal) && parent - && parent->getDocument() != lValue->getDocument()) + && parent->getDocument() != lValue->getDocument()) { throw Base::ValueError("PropertyLinkSub does not support external object"); + } } aboutToSetValue(); #ifndef USE_OLD_DAG @@ -1230,10 +1344,12 @@ void PropertyLinkSub::setValue(App::DocumentObject * lValue, // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { - if (_pcLinkSub) + if (_pcLinkSub) { _pcLinkSub->_removeBackLink(parent); - if (lValue) + } + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -1242,13 +1358,15 @@ void PropertyLinkSub::setValue(App::DocumentObject * lValue, if (shadows.size() == _cSubList.size()) { _ShadowSubList = std::move(shadows); onContainerRestored(); // re-register element references - } else + } + else { updateElementReference(nullptr); + } checkLabelReferences(_cSubList); hasSetValue(); } -App::DocumentObject * PropertyLinkSub::getValue() const +App::DocumentObject* PropertyLinkSub::getValue() const { return _pcLinkSub; } @@ -1258,17 +1376,21 @@ const std::vector& PropertyLinkSub::getSubValues() const return _cSubList; } -static inline const std::string &getSubNameWithStyle(const std::string &subName, - const PropertyLinkBase::ShadowSub &shadow, bool newStyle, std::string &tmp) +static inline const std::string& getSubNameWithStyle(const std::string& subName, + const PropertyLinkBase::ShadowSub& shadow, + bool newStyle, + std::string& tmp) { - if(!newStyle) { - if(!shadow.oldName.empty()) + if (!newStyle) { + if (!shadow.oldName.empty()) { return shadow.oldName; - }else if(!shadow.newName.empty()) { + } + } + else if (!shadow.newName.empty()) { if (Data::hasMissingElement(shadow.oldName.c_str())) { auto pos = shadow.newName.rfind('.'); if (pos != std::string::npos) { - tmp = shadow.newName.substr(0, pos+1); + tmp = shadow.newName.substr(0, pos + 1); tmp += shadow.oldName; return tmp; } @@ -1278,44 +1400,49 @@ static inline const std::string &getSubNameWithStyle(const std::string &subName, return subName; } -std::vector PropertyLinkSub::getSubValues(bool newStyle) const { +std::vector PropertyLinkSub::getSubValues(bool newStyle) const +{ assert(_cSubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_cSubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_cSubList[i],_ShadowSubList[i],newStyle,tmp)); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_cSubList[i], _ShadowSubList[i], newStyle, tmp)); + } return ret; } -std::vector PropertyLinkSub::getSubValuesStartsWith(const char* starter, bool newStyle) const +std::vector PropertyLinkSub::getSubValuesStartsWith(const char* starter, + bool newStyle) const { assert(_cSubList.size() == _ShadowSubList.size()); std::vector ret; std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) { - const auto &sub = getSubNameWithStyle(_cSubList[i],_ShadowSubList[i],newStyle,tmp); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + const auto& sub = getSubNameWithStyle(_cSubList[i], _ShadowSubList[i], newStyle, tmp); auto element = Data::findElementName(sub.c_str()); - if(element && boost::starts_with(element,starter)) + if (element && boost::starts_with(element, starter)) { ret.emplace_back(element); + } } return ret; } -App::DocumentObject * PropertyLinkSub::getValue(Base::Type t) const +App::DocumentObject* PropertyLinkSub::getValue(Base::Type t) const { return (_pcLinkSub && _pcLinkSub->getTypeId().isDerivedFrom(t)) ? _pcLinkSub : nullptr; } -PyObject *PropertyLinkSub::getPyObject() +PyObject* PropertyLinkSub::getPyObject() { Py::Tuple tup(2); Py::List list(static_cast(_cSubList.size())); if (_pcLinkSub) { tup[0] = Py::asObject(_pcLinkSub->getPyObject()); int i = 0; - for (auto &sub : getSubValues(testFlag(LinkNewElement))) + for (auto& sub : getSubValues(testFlag(LinkNewElement))) { list[i++] = Py::String(sub); + } tup[1] = list; return Py::new_reference_to(tup); } @@ -1324,200 +1451,253 @@ PyObject *PropertyLinkSub::getPyObject() } } -void PropertyLinkSub::setPyObject(PyObject *value) +void PropertyLinkSub::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObject = static_cast(value); + DocumentObjectPy* pcObject = static_cast(value); setValue(pcObject->getDocumentObjectPtr()); } else if (PyTuple_Check(value) || PyList_Check(value)) { Py::Sequence seq(value); - if(seq.size() == 0) + if (seq.size() == 0) { setValue(nullptr); - else if(seq.size()!=2) + } + else if (seq.size() != 2) { throw Base::ValueError("Expect input sequence of size 2"); + } else if (PyObject_TypeCheck(seq[0].ptr(), &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObj = static_cast(seq[0].ptr()); - static const char *errMsg = "type of second element in tuple must be str or sequence of str"; + DocumentObjectPy* pcObj = static_cast(seq[0].ptr()); + static const char* errMsg = + "type of second element in tuple must be str or sequence of str"; PropertyString propString; if (seq[1].isString()) { std::vector vals; propString.setPyObject(seq[1].ptr()); vals.emplace_back(propString.getValue()); - setValue(pcObj->getDocumentObjectPtr(),std::move(vals)); + setValue(pcObj->getDocumentObjectPtr(), std::move(vals)); } else if (seq[1].isSequence()) { Py::Sequence list(seq[1]); std::vector vals(list.size()); - unsigned int i=0; - for (Py::Sequence::iterator it = list.begin();it!=list.end();++it,++i) { - if(!(*it).isString()) + unsigned int i = 0; + for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it, ++i) { + if (!(*it).isString()) { throw Base::TypeError(errMsg); + } propString.setPyObject((*it).ptr()); vals[i] = propString.getValue(); } - setValue(pcObj->getDocumentObjectPtr(),std::move(vals)); + setValue(pcObj->getDocumentObjectPtr(), std::move(vals)); } else { throw Base::TypeError(errMsg); } } else { - std::string error = std::string("type of first element in tuple must be 'DocumentObject', not "); + std::string error = + std::string("type of first element in tuple must be 'DocumentObject', not "); error += seq[0].ptr()->ob_type->tp_name; throw Base::TypeError(error); } } - else if(Py_None == value) { + else if (Py_None == value) { setValue(nullptr); } else { - std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not "); + std::string error = std::string( + "type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } } -static bool updateLinkReference(App::PropertyLinkBase *prop, - App::DocumentObject *feature, bool reverse, bool notify, - App::DocumentObject *link, std::vector &subs, std::vector &mapped, - std::vector &shadows) +static bool updateLinkReference(App::PropertyLinkBase* prop, + App::DocumentObject* feature, + bool reverse, + bool notify, + App::DocumentObject* link, + std::vector& subs, + std::vector& mapped, + std::vector& shadows) { - if(!feature) { + if (!feature) { shadows.clear(); prop->unregisterElementReference(); } shadows.resize(subs.size()); - if(!link || !link->isAttachedToDocument()) + if (!link || !link->isAttachedToDocument()) { return false; + } auto owner = dynamic_cast(prop->getContainer()); - if(owner && owner->isRestoring()) + if (owner && owner->isRestoring()) { return false; - int i=0; + } + int i = 0; bool touched = false; - for(auto &sub : subs) { - if(prop->_updateElementReference( - feature,link,sub,shadows[i++],reverse,notify&&!touched)) + for (auto& sub : subs) { + if (prop->_updateElementReference(feature, + link, + sub, + shadows[i++], + reverse, + notify && !touched)) { touched = true; + } } - if(!touched) + if (!touched) { return false; - for(int idx : mapped) { - if(idx<(int)subs.size() && !shadows[idx].newName.empty()) + } + for (int idx : mapped) { + if (idx < (int)subs.size() && !shadows[idx].newName.empty()) { subs[idx] = shadows[idx].newName; + } } mapped.clear(); - if(owner && feature) + if (owner && feature) { owner->onUpdateElementReference(prop); + } return true; } -void PropertyLinkSub::afterRestore() { +void PropertyLinkSub::afterRestore() +{ _ShadowSubList.resize(_cSubList.size()); - if(!testFlag(LinkRestoreLabel) ||!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + if (!testFlag(LinkRestoreLabel) || !_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return; - setFlag(LinkRestoreLabel,false); - for(std::size_t i=0;i<_cSubList.size();++i) - restoreLabelReference(_pcLinkSub,_cSubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (std::size_t i = 0; i < _cSubList.size(); ++i) { + restoreLabelReference(_pcLinkSub, _cSubList[i], &_ShadowSubList[i]); + } } -void PropertyLinkSub::onContainerRestored() { +void PropertyLinkSub::onContainerRestored() +{ unregisterElementReference(); - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return; - for(std::size_t i=0;i<_cSubList.size();++i) - _registerElementReference(_pcLinkSub,_cSubList[i],_ShadowSubList[i]); + } + for (std::size_t i = 0; i < _cSubList.size(); ++i) { + _registerElementReference(_pcLinkSub, _cSubList[i], _ShadowSubList[i]); + } } -void PropertyLinkSub::updateElementReference(DocumentObject *feature, bool reverse, bool notify) { - if(!updateLinkReference(this,feature,reverse,notify,_pcLinkSub,_cSubList,_mapped,_ShadowSubList)) +void PropertyLinkSub::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!updateLinkReference(this, + feature, + reverse, + notify, + _pcLinkSub, + _cSubList, + _mapped, + _ShadowSubList)) { return; - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyLinkSub::referenceChanged() const { +bool PropertyLinkSub::referenceChanged() const +{ return !_mapped.empty(); } -std::string PropertyLinkBase::importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel) { - if(!reader.doNameMapping()) +std::string +PropertyLinkBase::importSubName(Base::XMLReader& reader, const char* sub, bool& restoreLabel) +{ + if (!reader.doNameMapping()) { return sub; + } std::ostringstream str; - for(const char *dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { - size_t count = dot-sub; - const char *tail = "."; - if(count && dot[-1] == '@') { + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { + size_t count = dot - sub; + const char* tail = "."; + if (count && dot[-1] == '@') { // tail=='@' means we are exporting a label reference. So retain // this marker so that the label can be restored in afterRestore(). tail = "@."; --count; restoreLabel = true; } - str << reader.getName(std::string(sub,count).c_str()) << tail; + str << reader.getName(std::string(sub, count).c_str()) << tail; } str << sub; return str.str(); } -const char *PropertyLinkBase::exportSubName(std::string &output, - const App::DocumentObject *obj, const char *sub, bool first_obj) +const char* PropertyLinkBase::exportSubName(std::string& output, + const App::DocumentObject* obj, + const char* sub, + bool first_obj) { std::ostringstream str; - const char *res = sub; + const char* res = sub; - if(!sub || !sub[0]) + if (!sub || !sub[0]) { return res; + } bool touched = false; - if(first_obj) { - auto dot = strchr(sub,'.'); - if(!dot) + if (first_obj) { + auto dot = strchr(sub, '.'); + if (!dot) { return res; - const char *hash; - for(hash=sub;hashisAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { doc = obj->getDocument(); + } } - if(!doc) { + if (!doc) { FC_ERR("Failed to get document for the first object in " << sub); return res; } - obj = doc->getObject(std::string(sub,dot-sub).c_str()); - if(!obj || !obj->isAttachedToDocument()) + obj = doc->getObject(std::string(sub, dot - sub).c_str()); + if (!obj || !obj->isAttachedToDocument()) { return res; - if(hash) { - if(!obj->isExporting()) + } + if (hash) { + if (!obj->isExporting()) { str << doc->getName() << '#'; - sub = hash+1; + } + sub = hash + 1; } - }else if(!obj || !obj->isAttachedToDocument()) + } + else if (!obj || !obj->isAttachedToDocument()) { return res; + } - for(const char *dot=strchr(sub,'.');dot;sub=dot+1,dot=strchr(sub,'.')) { + for (const char* dot = strchr(sub, '.'); dot; sub = dot + 1, dot = strchr(sub, '.')) { // name with trailing '.' - auto name = std::string(sub,dot-sub+1); - if(first_obj) + auto name = std::string(sub, dot - sub + 1); + if (first_obj) { first_obj = false; - else + } + else { obj = obj->getSubObject(name.c_str()); - if(!obj || !obj->isAttachedToDocument()) { - FC_WARN("missing sub object '" << name << "' in '" << sub <<"'"); + } + if (!obj || !obj->isAttachedToDocument()) { + FC_WARN("missing sub object '" << name << "' in '" << sub << "'"); break; } - if(obj->isExporting()) { - if(name[0] == '$') { - if(name.compare(1,name.size()-2,obj->Label.getValue())!=0) { + if (obj->isExporting()) { + if (name[0] == '$') { + if (name.compare(1, name.size() - 2, obj->Label.getValue()) != 0) { str << obj->getExportName(true) << "@."; touched = true; continue; } - } else if(name.compare(0,name.size()-1,obj->getNameInDocument())==0) { + } + else if (name.compare(0, name.size() - 1, obj->getNameInDocument()) == 0) { str << obj->getExportName(true) << '.'; touched = true; continue; @@ -1525,66 +1705,79 @@ const char *PropertyLinkBase::exportSubName(std::string &output, } str << name; } - if(!touched) + if (!touched) { return res; + } str << sub; output = str.str(); return output.c_str(); } -App::DocumentObject *PropertyLinkBase::tryImport(const App::Document *doc, - const App::DocumentObject *obj, const std::map &nameMap) +App::DocumentObject* PropertyLinkBase::tryImport(const App::Document* doc, + const App::DocumentObject* obj, + const std::map& nameMap) { - if(doc && obj && obj->isAttachedToDocument()) { + if (doc && obj && obj->isAttachedToDocument()) { auto it = nameMap.find(obj->getExportName(true)); - if(it!=nameMap.end()) { + if (it != nameMap.end()) { obj = doc->getObject(it->second.c_str()); - if(!obj) - FC_THROWM(Base::RuntimeError,"Cannot find import object " << it->second); + if (!obj) { + FC_THROWM(Base::RuntimeError, "Cannot find import object " << it->second); + } } } return const_cast(obj); } -std::string PropertyLinkBase::tryImportSubName(const App::DocumentObject *obj, const char *_subname, - const App::Document *doc, const std::map &nameMap) +std::string PropertyLinkBase::tryImportSubName(const App::DocumentObject* obj, + const char* _subname, + const App::Document* doc, + const std::map& nameMap) { - if(!doc || !obj || !obj->isAttachedToDocument()) + if (!doc || !obj || !obj->isAttachedToDocument()) { return {}; + } std::ostringstream ss; std::string subname(_subname); - char *sub = &subname[0]; - char *next = sub; - for(char *dot=strchr(next,'.');dot;next=dot+1,dot=strchr(next,'.')) { + char* sub = &subname[0]; + char* next = sub; + for (char* dot = strchr(next, '.'); dot; next = dot + 1, dot = strchr(next, '.')) { StringGuard guard(dot); auto sobj = obj->getSubObject(subname.c_str()); - if(!sobj) { + if (!sobj) { FC_ERR("Failed to restore label reference " << obj->getFullName() << '.' << subname); return {}; } dot[0] = 0; - if(next[0] == '$') { - if(strcmp(next+1,sobj->Label.getValue())!=0) + if (next[0] == '$') { + if (strcmp(next + 1, sobj->Label.getValue()) != 0) { continue; - } else if(strcmp(next,sobj->getNameInDocument())!=0) { + } + } + else if (strcmp(next, sobj->getNameInDocument()) != 0) { continue; } auto it = nameMap.find(sobj->getExportName(true)); - if(it == nameMap.end()) + if (it == nameMap.end()) { continue; + } auto imported = doc->getObject(it->second.c_str()); - if(!imported) + if (!imported) { FC_THROWM(RuntimeError, "Failed to find imported object " << it->second); - ss.write(sub,next-sub); - if(next[0] == '$') + } + ss.write(sub, next - sub); + if (next[0] == '$') { ss << '$' << imported->Label.getStrValue() << '.'; - else + } + else { ss << it->second << '.'; - sub = dot+1; + } + sub = dot + 1; } - if(sub!=subname.c_str()) + if (sub != subname.c_str()) { return ss.str(); + } return {}; } @@ -1646,54 +1839,58 @@ void PropertyLinkBase::_getLinksTo(std::vector& identifie #define IGNORE_SHADOW false -void PropertyLinkSub::Save (Base::Writer &writer) const +void PropertyLinkSub::Save(Base::Writer& writer) const { assert(_cSubList.size() == _ShadowSubList.size()); std::string internal_name; // it can happen that the object is still alive but is not part of the document anymore and thus // returns 0 - if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) + if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { internal_name = _pcLinkSub->getExportName(); - writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); auto owner = dynamic_cast(getContainer()); bool exporting = owner && owner->isExporting(); - for(unsigned int i = 0;i<_cSubList.size(); i++) { - const auto &shadow = _ShadowSubList[i]; + for (unsigned int i = 0; i < _cSubList.size(); i++) { + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_cSubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _cSubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << "\"/>" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkSub::Restore(Base::XMLReader &reader) +void PropertyLinkSub::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkSub"); @@ -1702,16 +1899,16 @@ void PropertyLinkSub::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); // Property not in a DocumentObject! - assert(getContainer()->isDerivedFrom() ); + assert(getContainer()->isDerivedFrom()); App::Document* document = static_cast(getContainer())->getDocument(); - DocumentObject *pcObject = nullptr; + DocumentObject* pcObject = nullptr; if (!name.empty()) { pcObject = document ? document->getObject(name.c_str()) : nullptr; if (!pcObject) { if (reader.isVerbose()) { - FC_WARN("Lost link to " << name - << " while loading, maybe an object was not loaded correctly"); + FC_WARN("Lost link to " + << name << " while loading, maybe an object was not loaded correctly"); } } } @@ -1719,107 +1916,126 @@ void PropertyLinkSub::Restore(Base::XMLReader &reader) std::vector mapped; std::vector values(count); std::vector shadows(count); - bool restoreLabel=false; + bool restoreLabel = false; // Sub may store '.' separated object names, so be aware of the possible mapping when import for (int i = 0; i < count; i++) { reader.readElement("Sub"); - shadows[i].oldName = importSubName(reader,reader.getAttribute("value"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + shadows[i].oldName = importSubName(reader, reader.getAttribute("value"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { values[i] = shadows[i].newName = - importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); - } else { + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); + } + else { values[i] = shadows[i].oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadows[i].newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadows[i].newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); + } } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); reader.readEndElement("LinkSub"); - if(pcObject) { - setValue(pcObject,std::move(values),std::move(shadows)); + if (pcObject) { + setValue(pcObject, std::move(values), std::move(shadows)); _mapped = std::move(mapped); } else { - setValue(nullptr); + setValue(nullptr); } } -template -std::vector updateLinkSubs(const App::DocumentObject *obj, - const std::vector &subs, Func *f, Args&&... args ) +template +std::vector updateLinkSubs(const App::DocumentObject* obj, + const std::vector& subs, + Func* f, + Args&&... args) { - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { return {}; + } std::vector res; - for(auto it=subs.begin();it!=subs.end();++it) { - const auto &sub = *it; - auto new_sub = (*f)(obj,sub.c_str(),std::forward(args)...); - if(new_sub.size()) { - if(res.empty()) { + for (auto it = subs.begin(); it != subs.end(); ++it) { + const auto& sub = *it; + auto new_sub = (*f)(obj, sub.c_str(), std::forward(args)...); + if (new_sub.size()) { + if (res.empty()) { res.reserve(subs.size()); - res.insert(res.end(),subs.begin(),it); + res.insert(res.end(), subs.begin(), it); } res.push_back(std::move(new_sub)); - }else if(!res.empty()) + } + else if (!res.empty()) { res.push_back(sub); + } } return res; } -Property *PropertyLinkSub::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyLinkSub::CopyOnImportExternal(const std::map& nameMap) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLinkSub,_cSubList, - &tryImportSubName,owner->getDocument(),nameMap); - auto linked = tryImport(owner->getDocument(),_pcLinkSub,nameMap); - if(subs.empty() && linked==_pcLinkSub) + auto subs = + updateLinkSubs(_pcLinkSub, _cSubList, &tryImportSubName, owner->getDocument(), nameMap); + auto linked = tryImport(owner->getDocument(), _pcLinkSub, nameMap); + if (subs.empty() && linked == _pcLinkSub) { return nullptr; + } - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = linked; - if(subs.empty()) + if (subs.empty()) { p->_cSubList = _cSubList; - else + } + else { p->_cSubList = std::move(subs); + } return p; } -Property *PropertyLinkSub::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyLinkSub::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLinkSub,_cSubList,&updateLabelReference,obj,ref,newLabel); - if(subs.empty()) + auto subs = updateLinkSubs(_pcLinkSub, _cSubList, &updateLabelReference, obj, ref, newLabel); + if (subs.empty()) { return nullptr; + } - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = _pcLinkSub; p->_cSubList = std::move(subs); return p; } -Property *PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLinkSubs(getContainer(),_pcLinkSub,parent,oldObj,newObj,_cSubList); - if(res.first) { - PropertyLinkSub *p= new PropertyLinkSub(); + auto res = tryReplaceLinkSubs(getContainer(), _pcLinkSub, parent, oldObj, newObj, _cSubList); + if (res.first) { + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = res.first; p->_cSubList = std::move(res.second); return p; @@ -1827,32 +2043,35 @@ Property *PropertyLinkSub::CopyOnLinkReplace(const App::DocumentObject *parent, return nullptr; } -Property *PropertyLinkSub::Copy() const +Property* PropertyLinkSub::Copy() const { - PropertyLinkSub *p= new PropertyLinkSub(); + PropertyLinkSub* p = new PropertyLinkSub(); p->_pcLinkSub = _pcLinkSub; p->_cSubList = _cSubList; p->_ShadowSubList = _ShadowSubList; return p; } -void PropertyLinkSub::Paste(const Property &from) +void PropertyLinkSub::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkSub::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkSub::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); - auto &link = static_cast(from); - setValue(link._pcLinkSub, link._cSubList, - std::vector(link._ShadowSubList)); + } + auto& link = static_cast(from); + setValue(link._pcLinkSub, link._cSubList, std::vector(link._ShadowSubList)); } -void PropertyLinkSub::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkSub::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - if(_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { + if (all || _pcScope != LinkScope::Hidden) { + if (_pcLinkSub && _pcLinkSub->isAttachedToDocument()) { objs.push_back(_pcLinkSub); - if(subs) + if (subs) { *subs = getSubValues(newStyle); + } } } } @@ -1869,57 +2088,70 @@ void PropertyLinkSub::getLinksTo(std::vector& identifiers } } -void PropertyLinkSub::breakLink(App::DocumentObject *obj, bool clear) { - if(obj == _pcLinkSub || (clear && getContainer()==obj)) +void PropertyLinkSub::breakLink(App::DocumentObject* obj, bool clear) +{ + if (obj == _pcLinkSub || (clear && getContainer() == obj)) { setValue(nullptr); + } } -static App::DocumentObject *adjustLinkSubs(App::PropertyLinkBase *prop, - const std::set &inList, - App::DocumentObject *link, std::vector &subs, - std::map > *links=nullptr) +static App::DocumentObject* +adjustLinkSubs(App::PropertyLinkBase* prop, + const std::set& inList, + App::DocumentObject* link, + std::vector& subs, + std::map>* links = nullptr) { - App::DocumentObject *newLink = nullptr; - for(auto &sub : subs) { + App::DocumentObject* newLink = nullptr; + for (auto& sub : subs) { size_t pos = sub.find('.'); - for(;pos!=std::string::npos;pos=sub.find('.',pos+1)) { - auto sobj = link->getSubObject(sub.substr(0,pos+1).c_str()); - if(!sobj || - (!prop->testFlag(PropertyLinkBase::LinkAllowExternal) && - sobj->getDocument()!=link->getDocument())) - { + for (; pos != std::string::npos; pos = sub.find('.', pos + 1)) { + auto sobj = link->getSubObject(sub.substr(0, pos + 1).c_str()); + if (!sobj + || (!prop->testFlag(PropertyLinkBase::LinkAllowExternal) + && sobj->getDocument() != link->getDocument())) { pos = std::string::npos; break; } - if(!newLink) { - if(inList.count(sobj)) + if (!newLink) { + if (inList.count(sobj)) { continue; + } newLink = sobj; - if(links) - (*links)[sobj].push_back(sub.substr(pos+1)); - else - sub = sub.substr(pos+1); - }else if(links) - (*links)[sobj].push_back(sub.substr(pos+1)); - else if(sobj == newLink) - sub = sub.substr(pos+1); + if (links) { + (*links)[sobj].push_back(sub.substr(pos + 1)); + } + else { + sub = sub.substr(pos + 1); + } + } + else if (links) { + (*links)[sobj].push_back(sub.substr(pos + 1)); + } + else if (sobj == newLink) { + sub = sub.substr(pos + 1); + } break; } - if(pos == std::string::npos) + if (pos == std::string::npos) { return nullptr; + } } return newLink; } -bool PropertyLinkSub::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyLinkSub::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - if(!_pcLinkSub || !_pcLinkSub->isAttachedToDocument() || !inList.count(_pcLinkSub)) + } + if (!_pcLinkSub || !_pcLinkSub->isAttachedToDocument() || !inList.count(_pcLinkSub)) { return false; + } auto subs = _cSubList; - auto link = adjustLinkSubs(this,inList,_pcLinkSub,subs); - if(link) { - setValue(link,std::move(subs)); + auto link = adjustLinkSubs(this, inList, _pcLinkSub, subs); + if (link) { + setValue(link, std::move(subs)); return true; } return false; @@ -1942,17 +2174,19 @@ PropertyLinkSubList::PropertyLinkSubList() = default; PropertyLinkSubList::~PropertyLinkSubList() { - //in case this property is dynamically removed + // in case this property is dynamically removed #ifndef USE_OLD_DAG - //maintain backlinks - if (!_lValueList.empty() && getContainer() && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + // maintain backlinks + if (!_lValueList.empty() && getContainer() + && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } } } @@ -1967,17 +2201,19 @@ void PropertyLinkSubList::setSyncSubObject(bool enable) void PropertyLinkSubList::verifyObject(App::DocumentObject* obj, App::DocumentObject* parent) { if (obj) { - if (!obj->isAttachedToDocument()) + if (!obj->isAttachedToDocument()) { throw Base::ValueError("PropertyLinkSubList: invalid document object"); - if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) + } + if (!testFlag(LinkAllowExternal) && parent && parent->getDocument() != obj->getDocument()) { throw Base::ValueError("PropertyLinkSubList does not support external object"); + } } } void PropertyLinkSubList::setSize(int newSize) { _lValueList.resize(newSize); - _lSubList .resize(newSize); + _lSubList.resize(newSize); _ShadowSubList.resize(newSize); } @@ -1986,23 +2222,25 @@ int PropertyLinkSubList::getSize() const return static_cast(_lValueList.size()); } -void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) +void PropertyLinkSubList::setValue(DocumentObject* lValue, const char* SubName) { auto parent = Base::freecad_dynamic_cast(getContainer()); verifyObject(lValue, parent); #ifndef USE_OLD_DAG - //maintain backlinks - if(parent) { + // maintain backlinks + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - for(auto *obj : _lValueList) { - if (obj) + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - if (lValue) + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -2010,9 +2248,9 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) if (lValue) { aboutToSetValue(); _lValueList.resize(1); - _lValueList[0]=lValue; + _lValueList[0] = lValue; _lSubList.resize(1); - _lSubList[0]=SubName; + _lSubList[0] = SubName; } else { aboutToSetValue(); @@ -2024,34 +2262,39 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName) hasSetValue(); } -void PropertyLinkSubList::setValues(const std::vector& lValue,const std::vector& lSubNames) +void PropertyLinkSubList::setValues(const std::vector& lValue, + const std::vector& lSubNames) { auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { + for (auto obj : lValue) { verifyObject(obj, parent); } - if (lValue.size() != lSubNames.size()) - throw Base::ValueError("PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + if (lValue.size() != lSubNames.size()) { + throw Base::ValueError( + "PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + } #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - for(auto *obj : lValue) { - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + for (auto* obj : lValue) { + if (obj) { obj->_addBackLink(parent); + } } } } @@ -2061,9 +2304,11 @@ void PropertyLinkSubList::setValues(const std::vector& lValue,c _lValueList = lValue; _lSubList.resize(lSubNames.size()); int i = 0; - for (std::vector::const_iterator it = lSubNames.begin();it!=lSubNames.end();++it,++i) { - if (*it) + for (std::vector::const_iterator it = lSubNames.begin(); it != lSubNames.end(); + ++it, ++i) { + if (*it) { _lSubList[i] = *it; + } } updateElementReference(nullptr); checkLabelReferences(_lSubList); @@ -2071,40 +2316,47 @@ void PropertyLinkSubList::setValues(const std::vector& lValue,c } void PropertyLinkSubList::setValues(const std::vector& lValue, - const std::vector& lSubNames, std::vector &&ShadowSubList) + const std::vector& lSubNames, + std::vector&& ShadowSubList) { setValues(std::vector(lValue), - std::vector(lSubNames),std::move(ShadowSubList)); + std::vector(lSubNames), + std::move(ShadowSubList)); } void PropertyLinkSubList::setValues(std::vector&& lValue, - std::vector&& lSubNames, std::vector &&ShadowSubList) + std::vector&& lSubNames, + std::vector&& ShadowSubList) { auto parent = Base::freecad_dynamic_cast(getContainer()); - for(auto obj : lValue) { + for (auto obj : lValue) { verifyObject(obj, parent); } - if (lValue.size() != lSubNames.size()) - throw Base::ValueError("PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + if (lValue.size() != lSubNames.size()) { + throw Base::ValueError( + "PropertyLinkSubList::setValues: size of subelements list != size of objects list"); + } #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - for(auto *obj : lValue) { - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + for (auto* obj : lValue) { + if (obj) { obj->_addBackLink(parent); + } } } } @@ -2113,37 +2365,41 @@ void PropertyLinkSubList::setValues(std::vector&& lValue, aboutToSetValue(); _lValueList = std::move(lValue); _lSubList = std::move(lSubNames); - if(ShadowSubList.size()==_lSubList.size()) { + if (ShadowSubList.size() == _lSubList.size()) { _ShadowSubList = std::move(ShadowSubList); onContainerRestored(); // re-register element references - } else + } + else { updateElementReference(nullptr); + } checkLabelReferences(_lSubList); hasSetValue(); } -void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector &SubList) +void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector& SubList) { auto parent = dynamic_cast(getContainer()); verifyObject(lValue, parent); #ifndef USE_OLD_DAG - //maintain backlinks. - if(parent) { + // maintain backlinks. + if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers - if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { + if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works - for(auto *obj : _lValueList) { - if (obj) + // object to ensure that this works + for (auto* obj : _lValueList) { + if (obj) { obj->_removeBackLink(parent); + } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - if (lValue) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + if (lValue) { lValue->_addBackLink(parent); + } } } #endif @@ -2167,39 +2423,43 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector &subs, bool reset) +void PropertyLinkSubList::addValue(App::DocumentObject* obj, + const std::vector& subs, + bool reset) { auto parent = Base::freecad_dynamic_cast(getContainer()); verifyObject(obj, parent); #ifndef USE_OLD_DAG - //maintain backlinks. + // maintain backlinks. if (parent) { // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers if (!parent->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { //_lValueList can contain items multiple times, but we trust the document - //object to ensure that this works + // object to ensure that this works if (reset) { - for(auto* value : _lValueList) { - if (value && value == obj) + for (auto* value : _lValueList) { + if (value && value == obj) { value->_removeBackLink(parent); + } } } - //maintain backlinks. lValue can contain items multiple times, but we trust the document - //object to ensure that the backlink is only added once - if (obj) + // maintain backlinks. lValue can contain items multiple times, but we trust the + // document object to ensure that the backlink is only added once + if (obj) { obj->_addBackLink(parent); + } } } #endif std::vector valueList; - std::vector subList; + std::vector subList; if (reset) { - for (std::size_t i=0; i<_lValueList.size(); i++) { + for (std::size_t i = 0; i < _lValueList.size(); i++) { if (_lValueList[i] != obj) { valueList.push_back(_lValueList[i]); subList.push_back(_lSubList[i]); @@ -2235,21 +2495,25 @@ const string PropertyLinkSubList::getPyReprString() const { assert(this->_lValueList.size() == this->_lSubList.size()); - if (this->_lValueList.empty()) + if (this->_lValueList.empty()) { return std::string("None"); + } std::stringstream strm; strm << "["; for (std::size_t i = 0; i < this->_lSubList.size(); i++) { - if (i>0) + if (i > 0) { strm << ",("; - else + } + else { strm << "("; + } App::DocumentObject* obj = this->_lValueList[i]; if (obj) { - strm << "App.getDocument('" << obj->getDocument()->getName() - << "').getObject('" << obj->getNameInDocument() << "')"; - } else { + strm << "App.getDocument('" << obj->getDocument()->getName() << "').getObject('" + << obj->getNameInDocument() << "')"; + } + else { strm << "None"; } strm << ","; @@ -2260,33 +2524,36 @@ const string PropertyLinkSubList::getPyReprString() const return strm.str(); } -DocumentObject *PropertyLinkSubList::getValue() const +DocumentObject* PropertyLinkSubList::getValue() const { App::DocumentObject* ret = nullptr; - //FIXME: cache this to avoid iterating each time, to improve speed + // FIXME: cache this to avoid iterating each time, to improve speed for (auto i : this->_lValueList) { - if (!ret) + if (!ret) { ret = i; - if (ret != i) + } + if (ret != i) { return nullptr; + } } return ret; } -int PropertyLinkSubList::removeValue(App::DocumentObject *lValue) +int PropertyLinkSubList::removeValue(App::DocumentObject* lValue) { assert(this->_lValueList.size() == this->_lSubList.size()); std::size_t num = std::count(this->_lValueList.begin(), this->_lValueList.end(), lValue); - if (num == 0) + if (num == 0) { return 0; + } std::vector links; std::vector subs; links.reserve(this->_lValueList.size() - num); subs.reserve(this->_lSubList.size() - num); - for (std::size_t i=0; i_lValueList.size(); ++i) { + for (std::size_t i = 0; i < this->_lValueList.size(); ++i) { if (this->_lValueList[i] != lValue) { links.push_back(this->_lValueList[i]); subs.push_back(this->_lSubList[i]); @@ -2301,13 +2568,17 @@ void PropertyLinkSubList::setSubListValues(const std::vector links; std::vector subs; - for (std::vector::const_iterator it = values.begin(); it != values.end(); ++it) { + for (std::vector::const_iterator it = values.begin(); + it != values.end(); + ++it) { if (it->second.empty()) { links.push_back(it->first); subs.emplace_back(); continue; } - for (std::vector::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { + for (std::vector::const_iterator jt = it->second.begin(); + jt != it->second.end(); + ++jt) { links.push_back(it->first); subs.push_back(*jt); } @@ -2318,22 +2589,27 @@ void PropertyLinkSubList::setSubListValues(const std::vector PropertyLinkSubList::getSubListValues(bool newStyle) const { std::vector values; - if (_lValueList.size() != _lSubList.size()) - throw Base::ValueError("PropertyLinkSubList::getSubListValues: size of subelements list != size of objects list"); + if (_lValueList.size() != _lSubList.size()) { + throw Base::ValueError("PropertyLinkSubList::getSubListValues: size of subelements list != " + "size of objects list"); + } assert(_ShadowSubList.size() == _lSubList.size()); for (std::size_t i = 0; i < _lValueList.size(); i++) { App::DocumentObject* link = _lValueList[i]; std::string sub; - if(newStyle && !_ShadowSubList[i].newName.empty()) + if (newStyle && !_ShadowSubList[i].newName.empty()) { sub = _ShadowSubList[i].newName; - else if(!newStyle && !_ShadowSubList[i].oldName.empty()) + } + else if (!newStyle && !_ShadowSubList[i].oldName.empty()) { sub = _ShadowSubList[i].oldName; - else + } + else { sub = _lSubList[i]; - if (values.empty() || values.back().first != link){ - //new object started, start a new subset. + } + if (values.empty() || values.back().first != link) { + // new object started, start a new subset. values.emplace_back(link, std::vector()); } values.back().second.push_back(sub); @@ -2341,16 +2617,16 @@ std::vector PropertyLinkSubList::getSubListValues(b return values; } -PyObject *PropertyLinkSubList::getPyObject() +PyObject* PropertyLinkSubList::getPyObject() { std::vector subLists = getSubListValues(); std::size_t count = subLists.size(); -#if 0//FIXME: Should switch to tuple +#if 0 // FIXME: Should switch to tuple Py::Tuple sequence(count); #else Py::List sequence(count); #endif - for (std::size_t i = 0; igetPyObject()); @@ -2367,164 +2643,199 @@ PyObject *PropertyLinkSubList::getPyObject() return Py::new_reference_to(sequence); } -void PropertyLinkSubList::setPyObject(PyObject *value) +void PropertyLinkSubList::setPyObject(PyObject* value) { - try { //try PropertyLinkSub syntax + try { // try PropertyLinkSub syntax PropertyLinkSub dummy; dummy.setPyObject(value); this->setValue(dummy.getValue(), dummy.getSubValues()); return; } - catch (...) {} + catch (...) { + } try { // try PropertyLinkList syntax PropertyLinkList dummy; dummy.setPyObject(value); - const auto &values = dummy.getValues(); + const auto& values = dummy.getValues(); std::vector subs(values.size()); - this->setValues(values,subs); + this->setValues(values, subs); return; - }catch(...) {} + } + catch (...) { + } - static const char *errMsg = + static const char* errMsg = "Expects sequence of items of type DocObj, (DocObj,SubName), or (DocObj, (SubName,...))"; - if (!PyTuple_Check(value) && !PyList_Check(value)) + if (!PyTuple_Check(value) && !PyList_Check(value)) { throw Base::TypeError(errMsg); + } Py::Sequence list(value); Py::Sequence::size_type size = list.size(); std::vector values; values.reserve(size); - std::vector SubNames; + std::vector SubNames; SubNames.reserve(size); - for (Py::Sequence::size_type i=0; i(seq[0].ptr())->getDocumentObjectPtr(); PropertyString propString; if (seq[1].isString()) { values.push_back(obj); propString.setPyObject(seq[1].ptr()); SubNames.emplace_back(propString.getValue()); - } else if (seq[1].isSequence()) { + } + else if (seq[1].isSequence()) { Py::Sequence list(seq[1]); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { - if(!(*it).isString()) + if (!(*it).isString()) { throw Base::TypeError(errMsg); + } values.push_back(obj); propString.setPyObject((*it).ptr()); SubNames.emplace_back(propString.getValue()); } - } else + } + else { throw Base::TypeError(errMsg); + } } - } else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { - DocumentObjectPy *pcObj; + } + else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) { + DocumentObjectPy* pcObj; pcObj = static_cast(*item); values.push_back(pcObj->getDocumentObjectPtr()); SubNames.emplace_back(); - } else + } + else { throw Base::TypeError(errMsg); + } } - setValues(values,SubNames); + setValues(values, SubNames); } -void PropertyLinkSubList::afterRestore() { +void PropertyLinkSubList::afterRestore() +{ assert(_lSubList.size() == _ShadowSubList.size()); - if(!testFlag(LinkRestoreLabel)) + if (!testFlag(LinkRestoreLabel)) { return; - setFlag(LinkRestoreLabel,false); - for(size_t i=0;i<_lSubList.size();++i) - restoreLabelReference(_lValueList[i],_lSubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (size_t i = 0; i < _lSubList.size(); ++i) { + restoreLabelReference(_lValueList[i], _lSubList[i], &_ShadowSubList[i]); + } } -void PropertyLinkSubList::onContainerRestored() { +void PropertyLinkSubList::onContainerRestored() +{ unregisterElementReference(); - for(size_t i=0;i<_lSubList.size();++i) - _registerElementReference(_lValueList[i],_lSubList[i],_ShadowSubList[i]); + for (size_t i = 0; i < _lSubList.size(); ++i) { + _registerElementReference(_lValueList[i], _lSubList[i], _ShadowSubList[i]); + } } -void PropertyLinkSubList::updateElementReference(DocumentObject *feature, bool reverse, bool notify) { - if(!feature) { +void PropertyLinkSubList::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!feature) { _ShadowSubList.clear(); unregisterElementReference(); } _ShadowSubList.resize(_lSubList.size()); auto owner = freecad_dynamic_cast(getContainer()); - if(owner && owner->isRestoring()) + if (owner && owner->isRestoring()) { return; - int i=0; + } + int i = 0; bool touched = false; - for(auto &sub : _lSubList) { + for (auto& sub : _lSubList) { auto obj = _lValueList[i]; - if(_updateElementReference(feature,obj,sub,_ShadowSubList[i++],reverse,notify&&!touched)) + if (_updateElementReference(feature, + obj, + sub, + _ShadowSubList[i++], + reverse, + notify && !touched)) { touched = true; + } } - if(!touched) + if (!touched) { return; + } std::vector mapped; mapped.reserve(_mapped.size()); - for(int idx : _mapped) { - if(idx<(int)_lSubList.size()) { - if(!_ShadowSubList[idx].newName.empty()) + for (int idx : _mapped) { + if (idx < (int)_lSubList.size()) { + if (!_ShadowSubList[idx].newName.empty()) { _lSubList[idx] = _ShadowSubList[idx].newName; - else + } + else { mapped.push_back(idx); + } } } _mapped.swap(mapped); - if(owner && feature) + if (owner && feature) { owner->onUpdateElementReference(this); - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyLinkSubList::referenceChanged() const{ +bool PropertyLinkSubList::referenceChanged() const +{ return !_mapped.empty(); } -void PropertyLinkSubList::Save (Base::Writer &writer) const +void PropertyLinkSubList::Save(Base::Writer& writer) const { assert(_lSubList.size() == _ShadowSubList.size()); int count = 0; - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { ++count; + } } - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); auto owner = dynamic_cast(getContainer()); bool exporting = owner && owner->isExporting(); for (int i = 0; i < getSize(); i++) { auto obj = _lValueList[i]; - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - const auto &shadow = _ShadowSubList[i]; + } + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_lSubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _lSubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "getExportName() << "\" sub=\""; - if(exporting) { + if (exporting) { std::string exportName; - writer.Stream() << encodeAttribute(exportSubName(exportName,obj,sub.c_str())); - if(!shadow.oldName.empty() && _lSubList[i]==shadow.newName) + writer.Stream() << encodeAttribute(exportSubName(exportName, obj, sub.c_str())); + if (!shadow.oldName.empty() && _lSubList[i] == shadow.newName) { writer.Stream() << "\" " ATTR_MAPPED "=\"1"; - } else { + } + } + else { writer.Stream() << encodeAttribute(sub); - if(!_lSubList[i].empty()) { - if(sub!=_lSubList[i]) { + if (!_lSubList[i].empty()) { + if (sub != _lSubList[i]) { // Stores the actual value that is shadowed. For new version FC, // we will restore this shadowed value instead. writer.Stream() << "\" " ATTR_SHADOWED "=\"" << encodeAttribute(_lSubList[i]); - }else if(!shadow.newName.empty()) { + } + else if (!shadow.newName.empty()) { // Here means the user set value is old style element name. // We shall then store the shadow somewhere else. writer.Stream() << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadow.newName); @@ -2535,10 +2846,10 @@ void PropertyLinkSubList::Save (Base::Writer &writer) const } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyLinkSubList::Restore(Base::XMLReader &reader) +void PropertyLinkSubList::Restore(Base::XMLReader& reader) { // read my element reader.readElement("LinkSubList"); @@ -2554,7 +2865,7 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) DocumentObject* father = dynamic_cast(getContainer()); App::Document* document = father ? father->getDocument() : nullptr; std::vector mapped; - bool restoreLabel=false; + bool restoreLabel = false; for (int i = 0; i < count; i++) { reader.readElement("Link"); std::string name = reader.getName(reader.getAttribute("obj")); @@ -2566,32 +2877,40 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader) if (child) { values.push_back(child); shadows.emplace_back(); - auto &shadow = shadows.back(); - shadow.oldName = importSubName(reader,reader.getAttribute("sub"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + auto& shadow = shadows.back(); + shadow.oldName = importSubName(reader, reader.getAttribute("sub"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); SubNames.push_back(shadow.newName); - }else{ + } + else { SubNames.push_back(shadow.oldName); - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); - } else if (reader.isVerbose()) + } + } + else if (reader.isVerbose()) { Base::Console().Warning("Lost link to '%s' while loading, maybe " - "an object was not loaded correctly\n",name.c_str()); + "an object was not loaded correctly\n", + name.c_str()); + } } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); reader.readEndElement("LinkSubList"); // assignment - setValues(values,SubNames,std::move(shadows)); + setValues(values, SubNames, std::move(shadows)); _mapped.swap(mapped); } -bool PropertyLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) +bool PropertyLinkSubList::upgrade(Base::XMLReader& reader, const char* typeName) { Base::Type type = Base::Type::fromName(typeName); if (type.isDerivedFrom(PropertyLink::getClassTypeId())) { @@ -2621,124 +2940,133 @@ bool PropertyLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) return false; } -Property *PropertyLinkSubList::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyLinkSubList::CopyOnImportExternal(const std::map& nameMap) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || _lValueList.size()!=_lSubList.size()) + if (!owner || !owner->getDocument() || _lValueList.size() != _lSubList.size()) { return nullptr; - std::vector values; + } + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto linked = tryImport(owner->getDocument(),value,nameMap); - auto new_sub = tryImportSubName(value,sub.c_str(),owner->getDocument(),nameMap); - if(linked!=value || !new_sub.empty()) { - if(values.empty()) { + auto linked = tryImport(owner->getDocument(), value, nameMap); + auto new_sub = tryImportSubName(value, sub.c_str(), owner->getDocument(), nameMap); + if (linked != value || !new_sub.empty()) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } values.push_back(linked); subs.push_back(std::move(new_sub)); - }else if(!values.empty()) { + } + else if (!values.empty()) { values.push_back(linked); subs.push_back(sub); } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyLinkSubList::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) + if (!owner || !owner->getDocument()) { return nullptr; - std::vector values; + } + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto new_sub = updateLabelReference(value,sub.c_str(),obj,ref,newLabel); - if(!new_sub.empty()) { - if(values.empty()) { + auto new_sub = updateLabelReference(value, sub.c_str(), obj, ref, newLabel); + if (!new_sub.empty()) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } values.push_back(value); subs.push_back(std::move(new_sub)); - }else if(!values.empty()) { + } + else if (!values.empty()) { values.push_back(value); subs.push_back(sub); } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - std::vector values; + std::vector values; std::vector subs; auto itSub = _lSubList.begin(); std::vector positions; - for(auto itValue=_lValueList.begin();itValue!=_lValueList.end();++itValue,++itSub) { + for (auto itValue = _lValueList.begin(); itValue != _lValueList.end(); ++itValue, ++itSub) { auto value = *itValue; - const auto &sub = *itSub; - if(!value || !value->isAttachedToDocument()) { - if(!values.empty()) { + const auto& sub = *itSub; + if (!value || !value->isAttachedToDocument()) { + if (!values.empty()) { values.push_back(value); subs.push_back(sub); } continue; } - auto res = tryReplaceLink(getContainer(),value,parent,oldObj,newObj,sub.c_str()); - if(res.first) { - if(values.empty()) { + auto res = tryReplaceLink(getContainer(), value, parent, oldObj, newObj, sub.c_str()); + if (res.first) { + if (values.empty()) { values.reserve(_lValueList.size()); - values.insert(values.end(),_lValueList.begin(),itValue); + values.insert(values.end(), _lValueList.begin(), itValue); subs.reserve(_lSubList.size()); - subs.insert(subs.end(),_lSubList.begin(),itSub); + subs.insert(subs.end(), _lSubList.begin(), itSub); } - if(res.first == newObj) { + if (res.first == newObj) { // check for duplication auto itS = subs.begin(); - for(auto itV=values.begin();itV!=values.end();) { - if(*itV == res.first && *itS == res.second) { + for (auto itV = values.begin(); itV != values.end();) { + if (*itV == res.first && *itS == res.second) { itV = values.erase(itV); itS = subs.erase(itS); - } else { + } + else { ++itV; ++itS; } @@ -2747,79 +3075,88 @@ Property *PropertyLinkSubList::CopyOnLinkReplace(const App::DocumentObject *pare } values.push_back(res.first); subs.push_back(std::move(res.second)); - }else if(!values.empty()) { + } + else if (!values.empty()) { bool duplicate = false; - if(value == newObj) { - for(auto pos : positions) { - if(sub == subs[pos]) { + if (value == newObj) { + for (auto pos : positions) { + if (sub == subs[pos]) { duplicate = true; break; } } } - if(!duplicate) { + if (!duplicate) { values.push_back(value); subs.push_back(sub); } } } - if(values.empty()) + if (values.empty()) { return nullptr; + } std::unique_ptr p(new PropertyLinkSubList); p->_lValueList = std::move(values); p->_lSubList = std::move(subs); return p.release(); } -Property *PropertyLinkSubList::Copy() const +Property* PropertyLinkSubList::Copy() const { - PropertyLinkSubList *p = new PropertyLinkSubList(); + PropertyLinkSubList* p = new PropertyLinkSubList(); p->_lValueList = _lValueList; - p->_lSubList = _lSubList; + p->_lSubList = _lSubList; p->_ShadowSubList = _ShadowSubList; return p; } -void PropertyLinkSubList::Paste(const Property &from) +void PropertyLinkSubList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); - auto &link = static_cast(from); - setValues(link._lValueList, link._lSubList, - std::vector(link._ShadowSubList)); + } + auto& link = static_cast(from); + setValues(link._lValueList, link._lSubList, std::vector(link._ShadowSubList)); } -unsigned int PropertyLinkSubList::getMemSize () const +unsigned int PropertyLinkSubList::getMemSize() const { - unsigned int size = static_cast(_lValueList.size() * sizeof(App::DocumentObject *)); - for(int i = 0;i(_lValueList.size() * sizeof(App::DocumentObject*)); + for (int i = 0; i < getSize(); i++) { + size += _lSubList[i].size(); + } + return size; } -std::vector PropertyLinkSubList::getSubValues(bool newStyle) const { +std::vector PropertyLinkSubList::getSubValues(bool newStyle) const +{ assert(_lSubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_ShadowSubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_lSubList[i],_ShadowSubList[i],newStyle,tmp)); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_lSubList[i], _ShadowSubList[i], newStyle, tmp)); + } return ret; } -void PropertyLinkSubList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyLinkSubList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - objs.reserve(objs.size()+_lValueList.size()); - for(auto obj : _lValueList) { - if(obj && obj->isAttachedToDocument()) + if (all || _pcScope != LinkScope::Hidden) { + objs.reserve(objs.size() + _lValueList.size()); + for (auto obj : _lValueList) { + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } - if(subs) { + if (subs) { auto _subs = getSubValues(newStyle); - subs->reserve(subs->size()+_subs.size()); - std::move(_subs.begin(),_subs.end(),std::back_inserter(*subs)); + subs->reserve(subs->size() + _subs.size()); + std::move(_subs.begin(), _subs.end(), std::back_inserter(*subs)); } } } @@ -2861,7 +3198,7 @@ void PropertyLinkSubList::getLinksTo(std::vector& identif const auto& shadow = _ShadowSubList[i]; App::SubObjectT sobjT(obj, shadow.newName.empty() ? shadow.oldName.c_str() - : shadow.newName.c_str()); + : shadow.newName.c_str()); if (sobjT.getSubObject() == subObject && sobjT.getOldElementName() == subElement) { identifiers.emplace_back(*this); continue; @@ -2870,62 +3207,70 @@ void PropertyLinkSubList::getLinksTo(std::vector& identif } } -void PropertyLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { +void PropertyLinkSubList::breakLink(App::DocumentObject* obj, bool clear) +{ std::vector values; std::vector subs; - if(clear && getContainer()==obj) { - setValues(values,subs); + if (clear && getContainer() == obj) { + setValues(values, subs); return; } - assert(_lValueList.size()==_lSubList.size()); + assert(_lValueList.size() == _lSubList.size()); values.reserve(_lValueList.size()); subs.reserve(_lSubList.size()); - int i=-1; - for(auto o : _lValueList) { + int i = -1; + for (auto o : _lValueList) { ++i; - if(o==obj) + if (o == obj) { continue; + } values.push_back(o); subs.push_back(_lSubList[i]); } - if(values.size()!=_lValueList.size()) - setValues(values,subs); + if (values.size() != _lValueList.size()) { + setValues(values, subs); + } } -bool PropertyLinkSubList::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyLinkSubList::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; + } auto subs = _lSubList; auto links = _lValueList; int idx = -1; bool touched = false; - for(std::string &sub : subs) { + for (std::string& sub : subs) { ++idx; - auto &link = links[idx]; - if(!link || !link->isAttachedToDocument() || !inList.count(link)) + auto& link = links[idx]; + if (!link || !link->isAttachedToDocument() || !inList.count(link)) { continue; + } touched = true; size_t pos = sub.find('.'); - for(;pos!=std::string::npos;pos=sub.find('.',pos+1)) { - auto sobj = link->getSubObject(sub.substr(0,pos+1).c_str()); - if(!sobj || sobj->getDocument()!=link->getDocument()) { + for (; pos != std::string::npos; pos = sub.find('.', pos + 1)) { + auto sobj = link->getSubObject(sub.substr(0, pos + 1).c_str()); + if (!sobj || sobj->getDocument() != link->getDocument()) { pos = std::string::npos; break; } - if(!inList.count(sobj)) { + if (!inList.count(sobj)) { link = sobj; - sub = sub.substr(pos+1); + sub = sub.substr(pos + 1); break; } } - if(pos == std::string::npos) + if (pos == std::string::npos) { return false; + } + } + if (touched) { + setValues(links, subs); } - if(touched) - setValues(links,subs); return touched; } @@ -2942,8 +3287,7 @@ bool PropertyLinkSubList::adjustLink(const std::set &inLis using DocInfoMap = std::map; DocInfoMap _DocInfoMap; -class App::DocInfo : - public std::enable_shared_from_this +class App::DocInfo: public std::enable_shared_from_this { public: using Connection = boost::signals2::scoped_connection; @@ -2955,11 +3299,13 @@ class App::DocInfo : DocInfoMap::iterator myPos; std::string myPath; - App::Document *pcDoc{nullptr}; + App::Document* pcDoc {nullptr}; std::set links; - static std::string getDocPath( - const char *filename, App::Document *pDoc, bool relative, QString *fullPath = nullptr) + static std::string getDocPath(const char* filename, + App::Document* pDoc, + bool relative, + QString* fullPath = nullptr) { bool absolute; // The path could be an URI, in that case @@ -2967,108 +3313,125 @@ class App::DocInfo : QString path = QString::fromUtf8(filename); if (path.startsWith(QLatin1String("https://"))) { // We do have an URI - if (fullPath) + if (fullPath) { *fullPath = path; - return std::string(filename); + } + return std::string(filename); } // make sure the filename is absolute path path = QDir::cleanPath(path); - if((absolute = QFileInfo(path).isAbsolute())) { - if(fullPath) + if ((absolute = QFileInfo(path).isAbsolute())) { + if (fullPath) { *fullPath = path; - if(!relative) + } + if (!relative) { return std::string(path.toUtf8().constData()); + } } - const char *docPath = pDoc->getFileName(); - if(!docPath || *docPath==0) + const char* docPath = pDoc->getFileName(); + if (!docPath || *docPath == 0) { throw Base::RuntimeError("Owner document not saved"); + } QDir docDir(QFileInfo(QString::fromUtf8(docPath)).absoluteDir()); - if(!absolute) { + if (!absolute) { path = QDir::cleanPath(docDir.absoluteFilePath(path)); - if(fullPath) + if (fullPath) { *fullPath = path; + } } - if(relative) + if (relative) { return std::string(docDir.relativeFilePath(path).toUtf8().constData()); - else + } + else { return std::string(path.toUtf8().constData()); + } } - static DocInfoPtr get(const char *filename, - App::Document *pDoc,PropertyXLink *l, const char *objName) + static DocInfoPtr + get(const char* filename, App::Document* pDoc, PropertyXLink* l, const char* objName) { QString path; - l->filePath = getDocPath(filename,pDoc,true,&path); + l->filePath = getDocPath(filename, pDoc, true, &path); FC_LOG("finding doc " << filename); auto it = _DocInfoMap.find(path); DocInfoPtr info; - if(it != _DocInfoMap.end()) { + if (it != _DocInfoMap.end()) { info = it->second; - if(!info->pcDoc) { + if (!info->pcDoc) { QString fullpath(info->getFullPath()); - if(fullpath.size() && - App::GetApplication().addPendingDocument( - fullpath.toUtf8().constData(),objName, - l->testFlag(PropertyLinkBase::LinkAllowPartial))==0) - { - for(App::Document *doc : App::GetApplication().getDocuments()) { - if(getFullPath(doc->getFileName()) == fullpath) { + if (fullpath.size() + && App::GetApplication().addPendingDocument( + fullpath.toUtf8().constData(), + objName, + l->testFlag(PropertyLinkBase::LinkAllowPartial)) + == 0) { + for (App::Document* doc : App::GetApplication().getDocuments()) { + if (getFullPath(doc->getFileName()) == fullpath) { info->attach(doc); break; } } } } - } else { + } + else { info = std::make_shared(); - auto ret = _DocInfoMap.insert(std::make_pair(path,info)); - info->init(ret.first,objName,l); + auto ret = _DocInfoMap.insert(std::make_pair(path, info)); + info->init(ret.first, objName, l); } - if(info->pcDoc) { + if (info->pcDoc) { // make sure to attach only external object auto owner = Base::freecad_dynamic_cast(l->getContainer()); - if(owner && owner->getDocument() == info->pcDoc) + if (owner && owner->getDocument() == info->pcDoc) { return info; + } } info->links.insert(l); return info; } - static QString getFullPath(const char *p) { + static QString getFullPath(const char* p) + { QString path = QString::fromUtf8(p); - if (path.isEmpty()) + if (path.isEmpty()) { return path; + } - if (path.startsWith(QLatin1String("https://"))) + if (path.startsWith(QLatin1String("https://"))) { return path; + } else { return QFileInfo(path).absoluteFilePath(); } } - QString getFullPath() const { + QString getFullPath() const + { QString path = myPos->first; - if (path.startsWith(QLatin1String("https://"))) + if (path.startsWith(QLatin1String("https://"))) { return path; + } else { return QFileInfo(myPos->first).absoluteFilePath(); } } - const char *filePath() const { + const char* filePath() const + { return myPath.c_str(); } - void deinit() { - FC_LOG("deinit " << (pcDoc?pcDoc->getName():filePath())); + void deinit() + { + FC_LOG("deinit " << (pcDoc ? pcDoc->getName() : filePath())); assert(links.empty()); connFinishRestoreDocument.disconnect(); connPendingReloadDocument.disconnect(); @@ -3083,132 +3446,151 @@ class App::DocInfo : pcDoc = nullptr; } - void init(DocInfoMap::iterator pos, const char *objName, PropertyXLink *l) { + void init(DocInfoMap::iterator pos, const char* objName, PropertyXLink* l) + { myPos = pos; myPath = myPos->first.toUtf8().constData(); - App::Application &app = App::GetApplication(); - //NOLINTBEGIN + App::Application& app = App::GetApplication(); + // NOLINTBEGIN connFinishRestoreDocument = app.signalFinishRestoreDocument.connect( - std::bind(&DocInfo::slotFinishRestoreDocument,this,sp::_1)); + std::bind(&DocInfo::slotFinishRestoreDocument, this, sp::_1)); connPendingReloadDocument = app.signalPendingReloadDocument.connect( - std::bind(&DocInfo::slotFinishRestoreDocument,this,sp::_1)); - connDeleteDocument = app.signalDeleteDocument.connect( - std::bind(&DocInfo::slotDeleteDocument,this,sp::_1)); - connSaveDocument = app.signalSaveDocument.connect( - std::bind(&DocInfo::slotSaveDocument,this,sp::_1)); - //NOLINTEND + std::bind(&DocInfo::slotFinishRestoreDocument, this, sp::_1)); + connDeleteDocument = + app.signalDeleteDocument.connect(std::bind(&DocInfo::slotDeleteDocument, this, sp::_1)); + connSaveDocument = + app.signalSaveDocument.connect(std::bind(&DocInfo::slotSaveDocument, this, sp::_1)); + // NOLINTEND QString fullpath(getFullPath()); - if(fullpath.isEmpty()) + if (fullpath.isEmpty()) { FC_ERR("document not found " << filePath()); - else{ - for(App::Document *doc : App::GetApplication().getDocuments()) { - if(getFullPath(doc->getFileName()) == fullpath) { - if(doc->testStatus(App::Document::PartialDoc) && !doc->getObject(objName)) + } + else { + for (App::Document* doc : App::GetApplication().getDocuments()) { + if (getFullPath(doc->getFileName()) == fullpath) { + if (doc->testStatus(App::Document::PartialDoc) && !doc->getObject(objName)) { break; + } attach(doc); return; } } FC_LOG("document pending " << filePath()); - app.addPendingDocument(fullpath.toUtf8().constData(),objName, - l->testFlag(PropertyLinkBase::LinkAllowPartial)); + app.addPendingDocument(fullpath.toUtf8().constData(), + objName, + l->testFlag(PropertyLinkBase::LinkAllowPartial)); } } - void attach(Document *doc) { + void attach(Document* doc) + { assert(!pcDoc); pcDoc = doc; FC_LOG("attaching " << doc->getName() << ", " << doc->getFileName()); - std::map > parentLinks; - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + std::map> parentLinks; + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; - if(link->_pcLink) + if (link->_pcLink) { continue; - if(link->parentProp) { + } + if (link->parentProp) { parentLinks[link->parentProp].push_back(link); continue; } auto obj = doc->getObject(link->objectName.c_str()); - if(obj) + if (obj) { link->restoreLink(obj); + } else if (doc->testStatus(App::Document::PartialDoc)) { - App::GetApplication().addPendingDocument( - doc->FileName.getValue(), - link->objectName.c_str(), - false); + App::GetApplication().addPendingDocument(doc->FileName.getValue(), + link->objectName.c_str(), + false); FC_WARN("reloading partial document '" << doc->FileName.getValue() - << "' due to object " << link->objectName); - } else + << "' due to object " << link->objectName); + } + else { FC_WARN("object '" << link->objectName << "' not found in document '" - << doc->getName() << "'"); + << doc->getName() << "'"); + } } - for(auto &v : parentLinks) { + for (auto& v : parentLinks) { v.first->setFlag(PropertyLinkBase::LinkRestoring); v.first->aboutToSetValue(); - for(auto link : v.second) { + for (auto link : v.second) { auto obj = doc->getObject(link->objectName.c_str()); - if(obj) + if (obj) { link->restoreLink(obj); + } else if (doc->testStatus(App::Document::PartialDoc)) { - App::GetApplication().addPendingDocument( - doc->FileName.getValue(), - link->objectName.c_str(), - false); - FC_WARN("reloading partial document '" << doc->FileName.getValue() - << "' due to object " << link->objectName); - } else + App::GetApplication().addPendingDocument(doc->FileName.getValue(), + link->objectName.c_str(), + false); + FC_WARN("reloading partial document '" + << doc->FileName.getValue() << "' due to object " << link->objectName); + } + else { FC_WARN("object '" << link->objectName << "' not found in document '" - << doc->getName() << "'"); + << doc->getName() << "'"); + } } v.first->hasSetValue(); - v.first->setFlag(PropertyLinkBase::LinkRestoring,false); + v.first->setFlag(PropertyLinkBase::LinkRestoring, false); } } - void remove(PropertyXLink *l) { + void remove(PropertyXLink* l) + { auto it = links.find(l); - if(it != links.end()) { + if (it != links.end()) { links.erase(it); - if(links.empty()) + if (links.empty()) { deinit(); + } } } - static void restoreDocument(const App::Document &doc) { + static void restoreDocument(const App::Document& doc) + { auto it = _DocInfoMap.find(getFullPath(doc.FileName.getValue())); - if(it==_DocInfoMap.end()) + if (it == _DocInfoMap.end()) { return; + } it->second->slotFinishRestoreDocument(doc); } - void slotFinishRestoreDocument(const App::Document &doc) { - if(pcDoc) + void slotFinishRestoreDocument(const App::Document& doc) + { + if (pcDoc) { return; + } QString fullpath(getFullPath()); - if(!fullpath.isEmpty() && getFullPath(doc.getFileName())==fullpath) + if (!fullpath.isEmpty() && getFullPath(doc.getFileName()) == fullpath) { attach(const_cast(&doc)); + } } - void slotSaveDocument(const App::Document &doc) { - if(!pcDoc) { + void slotSaveDocument(const App::Document& doc) + { + if (!pcDoc) { slotFinishRestoreDocument(doc); return; } - if(&doc!=pcDoc) + if (&doc != pcDoc) { return; + } QFileInfo info(myPos->first); QString path(info.absoluteFilePath()); - const char *filename = doc.getFileName(); + const char* filename = doc.getFileName(); QString docPath(getFullPath(filename)); - if(path.isEmpty() || path!=docPath) { + if (path.isEmpty() || path != docPath) { FC_LOG("document '" << doc.getName() << "' path changed"); auto me = shared_from_this(); - auto ret = _DocInfoMap.insert(std::make_pair(docPath,me)); - if(!ret.second) { + auto ret = _DocInfoMap.insert(std::make_pair(docPath, me)); + if (!ret.second) { // is that even possible? FC_WARN("document '" << doc.getName() << "' path exists, detach"); slotDeleteDocument(doc); @@ -3217,35 +3599,36 @@ class App::DocInfo : _DocInfoMap.erase(myPos); myPos = ret.first; - std::set tmp; + std::set tmp; tmp.swap(links); - for(auto link : tmp) { + for (auto link : tmp) { auto owner = static_cast(link->getContainer()); // adjust file path for each PropertyXLink - DocInfo::get(filename,owner->getDocument(),link,link->objectName.c_str()); + DocInfo::get(filename, owner->getDocument(), link, link->objectName.c_str()); } } // time stamp changed, touch the linking document. std::set docs; - for(auto link : links) { + for (auto link : links) { auto linkdoc = static_cast(link->getContainer())->getDocument(); auto ret = docs.insert(linkdoc); - if(ret.second) { + if (ret.second) { // This will signal the Gui::Document to call setModified(); - FC_LOG("touch document " << linkdoc->getName() - << " on time stamp change of " << link->getFullName()); + FC_LOG("touch document " << linkdoc->getName() << " on time stamp change of " + << link->getFullName()); linkdoc->Comment.touch(); } } } - void slotDeleteDocument(const App::Document &doc) { - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + void slotDeleteDocument(const App::Document& doc) + { + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->getDocument() == &doc) { + if (obj && obj->getDocument() == &doc) { links.erase(it); // must call unlink here, so that PropertyLink::resetLink can // remove back link before the owner object is marked as being @@ -3253,102 +3636,119 @@ class App::DocInfo : link->unlink(); } } - if(links.empty()) { + if (links.empty()) { deinit(); return; } - if(pcDoc!=&doc) + if (pcDoc != &doc) { return; - std::map > parentLinks; - for(auto link : links) { + } + std::map> parentLinks; + for (auto link : links) { link->setFlag(PropertyLinkBase::LinkDetached); - if(link->parentProp) + if (link->parentProp) { parentLinks[link->parentProp].push_back(link); - else + } + else { parentLinks[nullptr].push_back(link); + } } - for(auto &v : parentLinks) { - if(v.first) { + for (auto& v : parentLinks) { + if (v.first) { v.first->setFlag(PropertyLinkBase::LinkDetached); v.first->aboutToSetValue(); } - for(auto l : v.second) + for (auto l : v.second) { l->detach(); - if(v.first) { + } + if (v.first) { v.first->hasSetValue(); - v.first->setFlag(PropertyLinkBase::LinkDetached,false); + v.first->setFlag(PropertyLinkBase::LinkDetached, false); } } pcDoc = nullptr; } - bool hasXLink(const App::Document *doc) const{ - for(auto link : links) { + bool hasXLink(const App::Document* doc) const + { + for (auto link : links) { auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->getDocument() == doc) + if (obj && obj->getDocument() == doc) { return true; + } } return false; } - static void breakLinks(App::DocumentObject *obj, bool clear) { + static void breakLinks(App::DocumentObject* obj, bool clear) + { auto doc = obj->getDocument(); - for(auto itD=_DocInfoMap.begin(),itDNext=itD;itD!=_DocInfoMap.end();itD=itDNext) { + for (auto itD = _DocInfoMap.begin(), itDNext = itD; itD != _DocInfoMap.end(); + itD = itDNext) { ++itDNext; auto docInfo = itD->second; - if(docInfo->pcDoc != doc) + if (docInfo->pcDoc != doc) { continue; - auto &links = docInfo->links; + } + auto& links = docInfo->links; std::set parentLinks; - for(auto it=links.begin(),itNext=it;it!=links.end();it=itNext) { + for (auto it = links.begin(), itNext = it; it != links.end(); it = itNext) { ++itNext; auto link = *it; - if(link->_pcLink!=obj && !(clear && link->getContainer()==obj)) + if (link->_pcLink != obj && !(clear && link->getContainer() == obj)) { continue; - if(link->parentProp) + } + if (link->parentProp) { parentLinks.insert(link->parentProp); - else - link->breakLink(obj,clear); + } + else { + link->breakLink(obj, clear); + } + } + for (auto link : parentLinks) { + link->breakLink(obj, clear); } - for(auto link : parentLinks) - link->breakLink(obj,clear); } } }; -void PropertyLinkBase::breakLinks(App::DocumentObject *link, - const std::vector &objs, bool clear) +void PropertyLinkBase::breakLinks(App::DocumentObject* link, + const std::vector& objs, + bool clear) { std::vector props; - for(auto obj : objs) { + for (auto obj : objs) { props.clear(); obj->getPropertyList(props); - for(auto prop : props) { + for (auto prop : props) { auto linkProp = dynamic_cast(prop); - if(linkProp) - linkProp->breakLink(link,clear); + if (linkProp) { + linkProp->breakLink(link, clear); + } } } - DocInfo::breakLinks(link,clear); + DocInfo::breakLinks(link, clear); } //************************************************************************** // PropertyXLink //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLink , App::PropertyLink) +TYPESYSTEM_SOURCE(App::PropertyXLink, App::PropertyLink) -PropertyXLink::PropertyXLink(bool _allowPartial, PropertyLinkBase *parent) - :parentProp(parent) +PropertyXLink::PropertyXLink(bool _allowPartial, PropertyLinkBase* parent) + : parentProp(parent) { setAllowPartial(_allowPartial); setAllowExternal(true); setSyncSubObject(true); - if(parent) + if (parent) { setContainer(parent->getContainer()); + } } -PropertyXLink::~PropertyXLink() { +PropertyXLink::~PropertyXLink() +{ unlink(); } @@ -3357,8 +3757,9 @@ void PropertyXLink::setSyncSubObject(bool enable) _Flags.set((std::size_t)LinkSyncSubObject, enable); } -void PropertyXLink::unlink() { - if(docInfo) { +void PropertyXLink::unlink() +{ + if (docInfo) { docInfo->remove(this); docInfo.reset(); } @@ -3366,8 +3767,9 @@ void PropertyXLink::unlink() { resetLink(); } -void PropertyXLink::detach() { - if(docInfo && _pcLink) { +void PropertyXLink::detach() +{ + if (docInfo && _pcLink) { aboutToSetValue(); resetLink(); updateElementReference(nullptr); @@ -3375,214 +3777,245 @@ void PropertyXLink::detach() { } } -void PropertyXLink::aboutToSetValue() { - if(parentProp) +void PropertyXLink::aboutToSetValue() +{ + if (parentProp) { parentProp->aboutToSetChildValue(*this); - else + } + else { PropertyLinkBase::aboutToSetValue(); + } } -void PropertyXLink::hasSetValue() { - if(parentProp) +void PropertyXLink::hasSetValue() +{ + if (parentProp) { parentProp->hasSetChildValue(*this); - else + } + else { PropertyLinkBase::hasSetValue(); + } } -void PropertyXLink::setSubName(const char *subname) +void PropertyXLink::setSubName(const char* subname) { std::vector subs; - if(subname && subname[0]) + if (subname && subname[0]) { subs.emplace_back(subname); + } aboutToSetValue(); setSubValues(std::move(subs)); hasSetValue(); } -void PropertyXLink::setSubValues(std::vector &&subs, - std::vector &&shadows) +void PropertyXLink::setSubValues(std::vector&& subs, std::vector&& shadows) { _SubList = std::move(subs); _ShadowSubList.clear(); - if(shadows.size() == _SubList.size()) { + if (shadows.size() == _SubList.size()) { _ShadowSubList = std::move(shadows); - onContainerRestored(); // re-register element references - } else + onContainerRestored(); // re-register element references + } + else { updateElementReference(nullptr); + } checkLabelReferences(_SubList); } -void PropertyXLink::setValue(App::DocumentObject * lValue) { - setValue(lValue,nullptr); +void PropertyXLink::setValue(App::DocumentObject* lValue) +{ + setValue(lValue, nullptr); } -void PropertyXLink::setValue(App::DocumentObject * lValue, const char *subname) +void PropertyXLink::setValue(App::DocumentObject* lValue, const char* subname) { std::vector subs; - if(subname && subname[0]) + if (subname && subname[0]) { subs.emplace_back(subname); - setValue(lValue,std::move(subs)); + } + setValue(lValue, std::move(subs)); } -void PropertyXLink::restoreLink(App::DocumentObject *lValue) { +void PropertyXLink::restoreLink(App::DocumentObject* lValue) +{ assert(!_pcLink && lValue && docInfo); auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { throw Base::RuntimeError("invalid container"); + } bool touched = owner->isTouched(); - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); setFlag(LinkRestoring); aboutToSetValue(); #ifndef USE_OLD_DAG - if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) + if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { lValue->_addBackLink(owner); + } #endif - _pcLink=lValue; + _pcLink = lValue; updateElementReference(nullptr); hasSetValue(); - setFlag(LinkRestoring,false); + setFlag(LinkRestoring, false); - if(!touched && - owner->isTouched() && - docInfo && - docInfo->pcDoc && - stamp==docInfo->pcDoc->LastModifiedDate.getValue()) - { + if (!touched && owner->isTouched() && docInfo && docInfo->pcDoc + && stamp == docInfo->pcDoc->LastModifiedDate.getValue()) { owner->purgeTouched(); } } -void PropertyXLink::setValue(App::DocumentObject *lValue, - std::vector &&subs, std::vector &&shadows) +void PropertyXLink::setValue(App::DocumentObject* lValue, + std::vector&& subs, + std::vector&& shadows) { - if(_pcLink==lValue && _SubList==subs) + if (_pcLink == lValue && _SubList == subs) { return; + } - if(lValue && (!lValue->isAttachedToDocument() || !lValue->getDocument())) { + if (lValue && (!lValue->isAttachedToDocument() || !lValue->getDocument())) { throw Base::ValueError("Invalid object"); - return; } auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { throw Base::RuntimeError("invalid container"); + } - if(lValue == owner) + if (lValue == owner) { throw Base::ValueError("self linking"); + } aboutToSetValue(); DocInfoPtr info; - const char *name = ""; - if(lValue) { + const char* name = ""; + if (lValue) { name = lValue->getNameInDocument(); - if(lValue->getDocument() != owner->getDocument()) { - if(!docInfo || lValue->getDocument()!=docInfo->pcDoc) - { - const char *filename = lValue->getDocument()->getFileName(); - if(!filename || *filename==0) + if (lValue->getDocument() != owner->getDocument()) { + if (!docInfo || lValue->getDocument() != docInfo->pcDoc) { + const char* filename = lValue->getDocument()->getFileName(); + if (!filename || *filename == 0) { throw Base::RuntimeError("Linked document not saved"); + } FC_LOG("xlink set to new document " << lValue->getDocument()->getName()); - info = DocInfo::get(filename,owner->getDocument(),this,name); + info = DocInfo::get(filename, owner->getDocument(), this, name); assert(info && info->pcDoc == lValue->getDocument()); - }else + } + else { info = docInfo; + } } } - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); #ifndef USE_OLD_DAG - if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) { - if(_pcLink) + if (!owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { + if (_pcLink) { _pcLink->_removeBackLink(owner); - if(lValue) + } + if (lValue) { lValue->_addBackLink(owner); + } } #endif - if(docInfo!=info) { + if (docInfo != info) { unlink(); docInfo = info; } - if(!docInfo) + if (!docInfo) { filePath.clear(); - _pcLink=lValue; - if(docInfo && docInfo->pcDoc) - stamp=docInfo->pcDoc->LastModifiedDate.getValue(); + } + _pcLink = lValue; + if (docInfo && docInfo->pcDoc) { + stamp = docInfo->pcDoc->LastModifiedDate.getValue(); + } objectName = name; - setSubValues(std::move(subs),std::move(shadows)); + setSubValues(std::move(subs), std::move(shadows)); hasSetValue(); } -void PropertyXLink::setValue(std::string &&filename, std::string &&name, - std::vector &&subs, std::vector &&shadows) +void PropertyXLink::setValue(std::string&& filename, + std::string&& name, + std::vector&& subs, + std::vector&& shadows) { - if(name.empty()) { - setValue(nullptr,std::move(subs),std::move(shadows)); + if (name.empty()) { + setValue(nullptr, std::move(subs), std::move(shadows)); return; } auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { throw Base::RuntimeError("invalid container"); + } - DocumentObject *pObject=nullptr; + DocumentObject* pObject = nullptr; DocInfoPtr info; - if(!filename.empty()) { + if (!filename.empty()) { owner->getDocument()->signalLinkXsetValue(filename); - info = DocInfo::get(filename.c_str(),owner->getDocument(),this,name.c_str()); - if(info->pcDoc) + info = DocInfo::get(filename.c_str(), owner->getDocument(), this, name.c_str()); + if (info->pcDoc) { pObject = info->pcDoc->getObject(name.c_str()); - }else + } + } + else { pObject = owner->getDocument()->getObject(name.c_str()); + } - if(pObject) { - setValue(pObject,std::move(subs),std::move(shadows)); + if (pObject) { + setValue(pObject, std::move(subs), std::move(shadows)); return; } - setFlag(LinkDetached,false); + setFlag(LinkDetached, false); aboutToSetValue(); #ifndef USE_OLD_DAG - if (_pcLink && !owner->testStatus(ObjectStatus::Destroy) && _pcScope!=LinkScope::Hidden) + if (_pcLink && !owner->testStatus(ObjectStatus::Destroy) && _pcScope != LinkScope::Hidden) { _pcLink->_removeBackLink(owner); + } #endif _pcLink = nullptr; - if(docInfo!=info) { + if (docInfo != info) { unlink(); docInfo = info; } - if(!docInfo) + if (!docInfo) { filePath.clear(); - if(docInfo && docInfo->pcDoc) - stamp=docInfo->pcDoc->LastModifiedDate.getValue(); + } + if (docInfo && docInfo->pcDoc) { + stamp = docInfo->pcDoc->LastModifiedDate.getValue(); + } objectName = std::move(name); - setSubValues(std::move(subs),std::move(shadows)); + setSubValues(std::move(subs), std::move(shadows)); hasSetValue(); } -void PropertyXLink::setValue(App::DocumentObject *link, - const std::vector &subs, std::vector &&shadows) +void PropertyXLink::setValue(App::DocumentObject* link, + const std::vector& subs, + std::vector&& shadows) { - setValue(link,std::vector(subs),std::move(shadows)); + setValue(link, std::vector(subs), std::move(shadows)); } -App::Document *PropertyXLink::getDocument() const { - return docInfo?docInfo->pcDoc:nullptr; +App::Document* PropertyXLink::getDocument() const +{ + return docInfo ? docInfo->pcDoc : nullptr; } -const char *PropertyXLink::getDocumentPath() const { - return docInfo?docInfo->filePath():filePath.c_str(); +const char* PropertyXLink::getDocumentPath() const +{ + return docInfo ? docInfo->filePath() : filePath.c_str(); } -const char *PropertyXLink::getObjectName() const { +const char* PropertyXLink::getObjectName() const +{ return objectName.c_str(); } -bool PropertyXLink::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName,App::PropertyLinkGlobal::getClassTypeId().getName())==0 || - strcmp(typeName,App::PropertyLink::getClassTypeId().getName())==0 || - strcmp(typeName,App::PropertyLinkChild::getClassTypeId().getName())==0) - { +bool PropertyXLink::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, App::PropertyLinkGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, App::PropertyLink::getClassTypeId().getName()) == 0 + || strcmp(typeName, App::PropertyLinkChild::getClassTypeId().getName()) == 0) { PropertyLink::Restore(reader); return true; } @@ -3590,209 +4023,256 @@ bool PropertyXLink::upgrade(Base::XMLReader &reader, const char *typeName) { return false; } -int PropertyXLink::checkRestore(std::string *msg) const { - if(!docInfo) { - if(!_pcLink && !objectName.empty()) { +int PropertyXLink::checkRestore(std::string* msg) const +{ + if (!docInfo) { + if (!_pcLink && !objectName.empty()) { // this condition means linked object not found - if(msg) { + if (msg) { std::ostringstream ss; ss << "Link not restored" << std::endl; ss << "Object: " << objectName; - if(!filePath.empty()) + if (!filePath.empty()) { ss << std::endl << "File: " << filePath; + } *msg = ss.str(); } return 2; } return 0; } - if(!_pcLink) { - if (testFlag(LinkSilentRestore)) + if (!_pcLink) { + if (testFlag(LinkSilentRestore)) { return 0; - if(testFlag(LinkAllowPartial) && - (!docInfo->pcDoc || - docInfo->pcDoc->testStatus(App::Document::PartialDoc))) - { + } + if (testFlag(LinkAllowPartial) + && (!docInfo->pcDoc || docInfo->pcDoc->testStatus(App::Document::PartialDoc))) { return 0; } - if(msg) { + if (msg) { std::ostringstream ss; ss << "Link not restored" << std::endl; ss << "Linked object: " << objectName; - if(docInfo->pcDoc) + if (docInfo->pcDoc) { ss << std::endl << "Linked document: " << docInfo->pcDoc->Label.getValue(); - else if(!filePath.empty()) + } + else if (!filePath.empty()) { ss << std::endl << "Linked file: " << filePath; + } *msg = ss.str(); } return 2; } - if(!docInfo->pcDoc || stamp==docInfo->pcDoc->LastModifiedDate.getValue()) + if (!docInfo->pcDoc || stamp == docInfo->pcDoc->LastModifiedDate.getValue()) { return 0; + } - if(msg) { + if (msg) { std::ostringstream ss; - ss << "Time stamp changed on link " - << _pcLink->getFullName(); + ss << "Time stamp changed on link " << _pcLink->getFullName(); *msg = ss.str(); } return 1; } -void PropertyXLink::afterRestore() { +void PropertyXLink::afterRestore() +{ assert(_SubList.size() == _ShadowSubList.size()); - if(!testFlag(LinkRestoreLabel) || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!testFlag(LinkRestoreLabel) || !_pcLink || !_pcLink->isAttachedToDocument()) { return; - setFlag(LinkRestoreLabel,false); - for(size_t i=0;i<_SubList.size();++i) - restoreLabelReference(_pcLink,_SubList[i],&_ShadowSubList[i]); + } + setFlag(LinkRestoreLabel, false); + for (size_t i = 0; i < _SubList.size(); ++i) { + restoreLabelReference(_pcLink, _SubList[i], &_ShadowSubList[i]); + } } -void PropertyXLink::onContainerRestored() { - if(!_pcLink || !_pcLink->isAttachedToDocument()) +void PropertyXLink::onContainerRestored() +{ + if (!_pcLink || !_pcLink->isAttachedToDocument()) { return; - for(size_t i=0;i<_SubList.size();++i) - _registerElementReference(_pcLink,_SubList[i],_ShadowSubList[i]); + } + for (size_t i = 0; i < _SubList.size(); ++i) { + _registerElementReference(_pcLink, _SubList[i], _ShadowSubList[i]); + } } -void PropertyXLink::updateElementReference(DocumentObject *feature,bool reverse,bool notify) { - if(!updateLinkReference(this,feature,reverse,notify,_pcLink,_SubList,_mapped,_ShadowSubList)) +void PropertyXLink::updateElementReference(DocumentObject* feature, bool reverse, bool notify) +{ + if (!updateLinkReference(this, + feature, + reverse, + notify, + _pcLink, + _SubList, + _mapped, + _ShadowSubList)) { return; - if(notify) + } + if (notify) { hasSetValue(); + } } -bool PropertyXLink::referenceChanged() const{ +bool PropertyXLink::referenceChanged() const +{ return !_mapped.empty(); } -void PropertyXLink::Save (Base::Writer &writer) const { - auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument()) +void PropertyXLink::Save(Base::Writer& writer) const +{ + auto owner = dynamic_cast(getContainer()); + if (!owner || !owner->getDocument()) { return; + } assert(_SubList.size() == _ShadowSubList.size()); auto exporting = owner->isExporting(); - if(_pcLink && exporting && _pcLink->isExporting()) { + if (_pcLink && exporting && _pcLink->isExporting()) { // this means, we are exporting the owner and the linked object together. // Lets save the export name writer.Stream() << writer.ind() << "getExportName(); - }else { - const char *path = filePath.c_str(); + } + else { + const char* path = filePath.c_str(); std::string _path; - if(exporting) { + if (exporting) { // Here means we are exporting the owner but not exporting the // linked object. Try to use absolute file path for easy transition // into document at different directory - if(docInfo) + if (docInfo) { _path = docInfo->filePath(); + } else { auto pDoc = owner->getDocument(); - const char *docPath = pDoc->getFileName(); - if(docPath && docPath[0]) { - if(!filePath.empty()) - _path = DocInfo::getDocPath(filePath.c_str(),pDoc,false); - else + const char* docPath = pDoc->getFileName(); + if (docPath && docPath[0]) { + if (!filePath.empty()) { + _path = DocInfo::getDocPath(filePath.c_str(), pDoc, false); + } + else { _path = docPath; - }else + } + } + else { FC_WARN("PropertyXLink export without saving the document"); + } } - if(!_path.empty()) + if (!_path.empty()) { path = _path.c_str(); + } } - writer.Stream() << writer.ind() - << "pcDoc?docInfo->pcDoc->LastModifiedDate.getValue():"") - << "\" name=\"" << objectName; - + writer.Stream() << writer.ind() << "pcDoc ? docInfo->pcDoc->LastModifiedDate.getValue() + : "") + << "\" name=\"" << objectName; } - if(testFlag(LinkAllowPartial)) + if (testFlag(LinkAllowPartial)) { writer.Stream() << "\" partial=\"1"; + } - if(_SubList.empty()) { + if (_SubList.empty()) { writer.Stream() << "\"/>" << std::endl; - } else if(_SubList.size() == 1) { - const auto &subName = _SubList[0]; - const auto &shadowSub = _ShadowSubList[0]; - const auto &sub = shadowSub.oldName.empty()?subName:shadowSub.oldName; - if(exporting) { + } + else if (_SubList.size() == 1) { + const auto& subName = _SubList[0]; + const auto& shadowSub = _ShadowSubList[0]; + const auto& sub = shadowSub.oldName.empty() ? subName : shadowSub.oldName; + if (exporting) { std::string exportName; - writer.Stream() << "\" sub=\"" << - encodeAttribute(exportSubName(exportName,_pcLink,sub.c_str())); - if(!shadowSub.oldName.empty() && shadowSub.newName==subName) + writer.Stream() << "\" sub=\"" + << encodeAttribute(exportSubName(exportName, _pcLink, sub.c_str())); + if (!shadowSub.oldName.empty() && shadowSub.newName == subName) { writer.Stream() << "\" " ATTR_MAPPED "=\"1"; - }else{ + } + } + else { writer.Stream() << "\" sub=\"" << encodeAttribute(sub); - if(!sub.empty()) { - if(sub!=subName) + if (!sub.empty()) { + if (sub != subName) { writer.Stream() << "\" " ATTR_SHADOWED "=\"" << encodeAttribute(subName); - else if(!shadowSub.newName.empty()) - writer.Stream() << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadowSub.newName); + } + else if (!shadowSub.newName.empty()) { + writer.Stream() + << "\" " ATTR_SHADOW "=\"" << encodeAttribute(shadowSub.newName); + } } } writer.Stream() << "\"/>" << std::endl; - }else { - writer.Stream() <<"\" count=\"" << _SubList.size() << "\">" << std::endl; + } + else { + writer.Stream() << "\" count=\"" << _SubList.size() << "\">" << std::endl; writer.incInd(); - for(unsigned int i = 0;i<_SubList.size(); i++) { - const auto &shadow = _ShadowSubList[i]; + for (unsigned int i = 0; i < _SubList.size(); i++) { + const auto& shadow = _ShadowSubList[i]; // shadow.oldName stores the old style element name. For backward // compatibility reason, we shall store the old name into attribute // 'value' whenever possible. - const auto &sub = shadow.oldName.empty()?_SubList[i]:shadow.oldName; + const auto& sub = shadow.oldName.empty() ? _SubList[i] : shadow.oldName; writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << "\"/>" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } } -void PropertyXLink::Restore(Base::XMLReader &reader) +void PropertyXLink::Restore(Base::XMLReader& reader) { // read my element reader.readElement("XLink"); - std::string stampAttr,file; - if(reader.hasAttribute("stamp")) + std::string stampAttr, file; + if (reader.hasAttribute("stamp")) { stampAttr = reader.getAttribute("stamp"); - if(reader.hasAttribute("file")) + } + if (reader.hasAttribute("file")) { file = reader.getAttribute("file"); + } setFlag(LinkAllowPartial, - reader.hasAttribute("partial") && - reader.getAttributeAsInteger("partial")); + reader.hasAttribute("partial") && reader.getAttributeAsInteger("partial")); std::string name; - if(file.empty()) + if (file.empty()) { name = reader.getName(reader.getAttribute("name")); - else + } + else { name = reader.getAttribute("name"); + } assert(getContainer()->isDerivedFrom()); - DocumentObject *object = nullptr; - if(!name.empty() && file.empty()) { + DocumentObject* object = nullptr; + if (!name.empty() && file.empty()) { DocumentObject* parent = static_cast(getContainer()); - Document *document = parent->getDocument(); + Document* document = parent->getDocument(); object = document ? document->getObject(name.c_str()) : nullptr; - if(!object) { - if(reader.isVerbose()) { - FC_WARN("Lost link to '" << name << "' while loading, maybe " - "an object was not loaded correctly"); + if (!object) { + if (reader.isVerbose()) { + FC_WARN("Lost link to '" << name + << "' while loading, maybe " + "an object was not loaded correctly"); } } } @@ -3801,117 +4281,139 @@ void PropertyXLink::Restore(Base::XMLReader &reader) std::vector shadows; std::vector mapped; bool restoreLabel = false; - if(reader.hasAttribute("sub")) { - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute("sub")) { + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(0); + } subs.emplace_back(); - auto &subname = subs.back(); + auto& subname = subs.back(); shadows.emplace_back(); - auto &shadow = shadows.back(); - shadow.oldName = importSubName(reader,reader.getAttribute("sub"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) - subname = shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + auto& shadow = shadows.back(); + shadow.oldName = importSubName(reader, reader.getAttribute("sub"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { + subname = shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); + } else { subname = shadow.oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadow.newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadow.newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - }else if(reader.hasAttribute("count")) { + } + else if (reader.hasAttribute("count")) { int count = reader.getAttributeAsInteger("count"); subs.resize(count); shadows.resize(count); for (int i = 0; i < count; i++) { reader.readElement("Sub"); - shadows[i].oldName = importSubName(reader,reader.getAttribute("value"),restoreLabel); - if(reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) + shadows[i].oldName = importSubName(reader, reader.getAttribute("value"), restoreLabel); + if (reader.hasAttribute(ATTR_SHADOWED) && !IGNORE_SHADOW) { subs[i] = shadows[i].newName = - importSubName(reader,reader.getAttribute(ATTR_SHADOWED),restoreLabel); + importSubName(reader, reader.getAttribute(ATTR_SHADOWED), restoreLabel); + } else { subs[i] = shadows[i].oldName; - if(reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) - shadows[i].newName = importSubName(reader,reader.getAttribute(ATTR_SHADOW),restoreLabel); + if (reader.hasAttribute(ATTR_SHADOW) && !IGNORE_SHADOW) { + shadows[i].newName = + importSubName(reader, reader.getAttribute(ATTR_SHADOW), restoreLabel); + } } - if(reader.hasAttribute(ATTR_MAPPED)) + if (reader.hasAttribute(ATTR_MAPPED)) { mapped.push_back(i); + } } reader.readEndElement("XLink"); } - setFlag(LinkRestoreLabel,restoreLabel); + setFlag(LinkRestoreLabel, restoreLabel); if (name.empty()) { setValue(nullptr); return; } - if(!file.empty() || (!object && !name.empty())) { + if (!file.empty() || (!object && !name.empty())) { this->stamp = stampAttr; - setValue(std::move(file),std::move(name),std::move(subs),std::move(shadows)); - }else - setValue(object,std::move(subs),std::move(shadows)); + setValue(std::move(file), std::move(name), std::move(subs), std::move(shadows)); + } + else { + setValue(object, std::move(subs), std::move(shadows)); + } _mapped = std::move(mapped); } -Property *PropertyXLink::CopyOnImportExternal( - const std::map &nameMap) const +Property* +PropertyXLink::CopyOnImportExternal(const std::map& nameMap) const { auto owner = Base::freecad_dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) { return nullptr; + } - auto subs = updateLinkSubs(_pcLink,_SubList, - &tryImportSubName,owner->getDocument(),nameMap); - auto linked = tryImport(owner->getDocument(),_pcLink,nameMap); - if(subs.empty() && linked==_pcLink) + auto subs = updateLinkSubs(_pcLink, _SubList, &tryImportSubName, owner->getDocument(), nameMap); + auto linked = tryImport(owner->getDocument(), _pcLink, nameMap); + if (subs.empty() && linked == _pcLink) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,linked,&subs); + copyTo(*p, linked, &subs); return p.release(); } -Property *PropertyXLink::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyXLink::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { - auto res = tryReplaceLinkSubs(getContainer(),_pcLink,parent,oldObj,newObj,_SubList); - if(!res.first) + auto res = tryReplaceLinkSubs(getContainer(), _pcLink, parent, oldObj, newObj, _SubList); + if (!res.first) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,res.first,&res.second); + copyTo(*p, res.first, &res.second); return p.release(); } -Property *PropertyXLink::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyXLink::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) + if (!owner || !owner->getDocument() || !_pcLink || !_pcLink->isAttachedToDocument()) { return nullptr; - auto subs = updateLinkSubs(_pcLink,_SubList,&updateLabelReference,obj,ref,newLabel); - if(subs.empty()) + } + auto subs = updateLinkSubs(_pcLink, _SubList, &updateLabelReference, obj, ref, newLabel); + if (subs.empty()) { return nullptr; + } std::unique_ptr p(new PropertyXLink); - copyTo(*p,_pcLink,&subs); + copyTo(*p, _pcLink, &subs); return p.release(); } -void PropertyXLink::copyTo(PropertyXLink &other, - DocumentObject *linked, std::vector *subs) const +void PropertyXLink::copyTo(PropertyXLink& other, + DocumentObject* linked, + std::vector* subs) const { - if(!linked) + if (!linked) { linked = _pcLink; - if(linked && linked->isAttachedToDocument()) { + } + if (linked && linked->isAttachedToDocument()) { other.docName = linked->getDocument()->getName(); other.objectName = linked->getNameInDocument(); other.docInfo.reset(); other.filePath.clear(); - }else{ + } + else { other.objectName = objectName; other.docName.clear(); other.docInfo = docInfo; other.filePath = filePath; } - if(subs) + if (subs) { other._SubList = std::move(*subs); + } else { other._SubList = _SubList; other._ShadowSubList = _ShadowSubList; @@ -3919,136 +4421,157 @@ void PropertyXLink::copyTo(PropertyXLink &other, other._Flags = _Flags; } -Property *PropertyXLink::Copy() const +Property* PropertyXLink::Copy() const { std::unique_ptr p(new PropertyXLink); copyTo(*p); return p.release(); } -void PropertyXLink::Paste(const Property &from) +void PropertyXLink::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyXLink::getClassTypeId())) + if (!from.isDerivedFrom(PropertyXLink::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } - const auto &other = static_cast(from); - if(!other.docName.empty()) { + const auto& other = static_cast(from); + if (!other.docName.empty()) { auto doc = GetApplication().getDocument(other.docName.c_str()); - if(!doc) { + if (!doc) { FC_WARN("Document '" << other.docName << "' not found"); return; } auto obj = doc->getObject(other.objectName.c_str()); - if(!obj) { + if (!obj) { FC_WARN("Object '" << other.docName << '#' << other.objectName << "' not found"); return; } - setValue(obj,std::vector(other._SubList), + setValue(obj, + std::vector(other._SubList), std::vector(other._ShadowSubList)); - } else - setValue(std::string(other.filePath),std::string(other.objectName), + } + else { + setValue(std::string(other.filePath), + std::string(other.objectName), std::vector(other._SubList), std::vector(other._ShadowSubList)); - setFlag(LinkAllowPartial,other.testFlag(LinkAllowPartial)); + } + setFlag(LinkAllowPartial, other.testFlag(LinkAllowPartial)); } -bool PropertyXLink::supportXLink(const App::Property *prop) { - return prop->isDerivedFrom(PropertyXLink::getClassTypeId()) || - prop->isDerivedFrom(PropertyXLinkSubList::getClassTypeId()) || - prop->isDerivedFrom(PropertyXLinkContainer::getClassTypeId()); +bool PropertyXLink::supportXLink(const App::Property* prop) +{ + return prop->isDerivedFrom(PropertyXLink::getClassTypeId()) + || prop->isDerivedFrom(PropertyXLinkSubList::getClassTypeId()) + || prop->isDerivedFrom(PropertyXLinkContainer::getClassTypeId()); } -bool PropertyXLink::hasXLink(const App::Document *doc) { - for(auto &v : _DocInfoMap) { - if(v.second->hasXLink(doc)) +bool PropertyXLink::hasXLink(const App::Document* doc) +{ + for (auto& v : _DocInfoMap) { + if (v.second->hasXLink(doc)) { return true; + } } return false; } -bool PropertyXLink::hasXLink( - const std::vector &objs, std::vector *unsaved) +bool PropertyXLink::hasXLink(const std::vector& objs, + std::vector* unsaved) { std::set docs; bool ret = false; - for(auto o : objs) { - if(o && o->isAttachedToDocument() && docs.insert(o->getDocument()).second) { - if(!hasXLink(o->getDocument())) + for (auto o : objs) { + if (o && o->isAttachedToDocument() && docs.insert(o->getDocument()).second) { + if (!hasXLink(o->getDocument())) { continue; - if(!unsaved) + } + if (!unsaved) { return true; + } ret = true; - if(!o->getDocument()->isSaved()) + if (!o->getDocument()->isSaved()) { unsaved->push_back(o->getDocument()); + } } } return ret; } -void PropertyXLink::restoreDocument(const App::Document &doc) { +void PropertyXLink::restoreDocument(const App::Document& doc) +{ DocInfo::restoreDocument(doc); } -std::map > -PropertyXLink::getDocumentOutList(App::Document *doc) { - std::map > ret; - for(auto &v : _DocInfoMap) { - for(auto link : v.second->links) { - if(!v.second->pcDoc - || link->getScope() == LinkScope::Hidden - || link->testStatus(Property::PropTransient) - || link->testStatus(Property::Transient) - || link->testStatus(Property::PropNoPersist)) +std::map> +PropertyXLink::getDocumentOutList(App::Document* doc) +{ + std::map> ret; + for (auto& v : _DocInfoMap) { + for (auto link : v.second->links) { + if (!v.second->pcDoc || link->getScope() == LinkScope::Hidden + || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) { continue; + } auto obj = dynamic_cast(link->getContainer()); - if(!obj || !obj->isAttachedToDocument() || !obj->getDocument()) + if (!obj || !obj->isAttachedToDocument() || !obj->getDocument()) { continue; - if(doc && obj->getDocument()!=doc) + } + if (doc && obj->getDocument() != doc) { continue; + } ret[obj->getDocument()].insert(v.second->pcDoc); } } return ret; } -std::map > -PropertyXLink::getDocumentInList(App::Document *doc) { - std::map > ret; - for(auto &v : _DocInfoMap) { - if(!v.second->pcDoc || (doc && doc!=v.second->pcDoc)) +std::map> +PropertyXLink::getDocumentInList(App::Document* doc) +{ + std::map> ret; + for (auto& v : _DocInfoMap) { + if (!v.second->pcDoc || (doc && doc != v.second->pcDoc)) { continue; - auto &docs = ret[v.second->pcDoc]; - for(auto link : v.second->links) { - if(link->getScope() == LinkScope::Hidden - || link->testStatus(Property::PropTransient) - || link->testStatus(Property::Transient) - || link->testStatus(Property::PropNoPersist)) + } + auto& docs = ret[v.second->pcDoc]; + for (auto link : v.second->links) { + if (link->getScope() == LinkScope::Hidden || link->testStatus(Property::PropTransient) + || link->testStatus(Property::Transient) + || link->testStatus(Property::PropNoPersist)) { continue; + } auto obj = dynamic_cast(link->getContainer()); - if(obj && obj->isAttachedToDocument() && obj->getDocument()) + if (obj && obj->isAttachedToDocument() && obj->getDocument()) { docs.insert(obj->getDocument()); + } } } return ret; } -PyObject *PropertyXLink::getPyObject() +PyObject* PropertyXLink::getPyObject() { - if(!_pcLink) + if (!_pcLink) { Py_Return; - const auto &subs = getSubValues(false); - if(subs.empty()) + } + const auto& subs = getSubValues(false); + if (subs.empty()) { return _pcLink->getPyObject(); + } Py::Tuple ret(2); - ret.setItem(0,Py::Object(_pcLink->getPyObject(),true)); + ret.setItem(0, Py::Object(_pcLink->getPyObject(), true)); PropertyString propString; if (subs.size() == 1) { propString.setValue(subs.front()); - ret.setItem(1,Py::asObject(propString.getPyObject())); - } else { + ret.setItem(1, Py::asObject(propString.getPyObject())); + } + else { Py::List list(subs.size()); int i = 0; - for (auto &sub : subs) { + for (auto& sub : subs) { propString.setValue(sub); list[i++] = Py::asObject(propString.getPyObject()); } @@ -4057,66 +4580,85 @@ PyObject *PropertyXLink::getPyObject() return Py::new_reference_to(ret); } -void PropertyXLink::setPyObject(PyObject *value) { - if(PySequence_Check(value)) { +void PropertyXLink::setPyObject(PyObject* value) +{ + if (PySequence_Check(value)) { Py::Sequence seq(value); - if(seq.size()!=2) + if (seq.size() != 2) { throw Base::ValueError("Expect input sequence of size 2"); + } std::vector subs; Py::Object pyObj(seq[0].ptr()); Py::Object pySub(seq[1].ptr()); - if(pyObj.isNone()) { + if (pyObj.isNone()) { setValue(nullptr); return; - } else if(!PyObject_TypeCheck(pyObj.ptr(), &DocumentObjectPy::Type)) + } + else if (!PyObject_TypeCheck(pyObj.ptr(), &DocumentObjectPy::Type)) { throw Base::TypeError("Expect the first element to be of 'DocumentObject'"); + } PropertyString propString; - if(pySub.isString()) { + if (pySub.isString()) { propString.setPyObject(pySub.ptr()); subs.push_back(propString.getStrValue()); - } else if (pySub.isSequence()) { + } + else if (pySub.isSequence()) { Py::Sequence seq(pySub); subs.reserve(seq.size()); - for(Py_ssize_t i=0;i(pyObj.ptr())->getDocumentObjectPtr(), std::move(subs)); - } else if(PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { + } + setValue(static_cast(pyObj.ptr())->getDocumentObjectPtr(), + std::move(subs)); + } + else if (PyObject_TypeCheck(value, &(DocumentObjectPy::Type))) { setValue(static_cast(value)->getDocumentObjectPtr()); - } else if (Py_None == value) { + } + else if (Py_None == value) { setValue(nullptr); - } else { - throw Base::TypeError("type must be 'DocumentObject', 'None', or '(DocumentObject, SubName)' or " - "'DocumentObject, [SubName..])"); + } + else { + throw Base::TypeError( + "type must be 'DocumentObject', 'None', or '(DocumentObject, SubName)' or " + "'DocumentObject, [SubName..])"); } } -const char *PropertyXLink::getSubName(bool newStyle) const { - if(_SubList.empty() || _ShadowSubList.empty()) +const char* PropertyXLink::getSubName(bool newStyle) const +{ + if (_SubList.empty() || _ShadowSubList.empty()) { return ""; - return getSubNameWithStyle(_SubList[0],_ShadowSubList[0],newStyle,tmpShadow).c_str(); + } + return getSubNameWithStyle(_SubList[0], _ShadowSubList[0], newStyle, tmpShadow).c_str(); } -void PropertyXLink::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyXLink::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if((all||_pcScope!=LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { + if ((all || _pcScope != LinkScope::Hidden) && _pcLink && _pcLink->isAttachedToDocument()) { objs.push_back(_pcLink); - if(subs && _SubList.size()==_ShadowSubList.size()) + if (subs && _SubList.size() == _ShadowSubList.size()) { *subs = getSubValues(newStyle); + } } } -void PropertyXLink::getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - bool all) const { +void PropertyXLink::getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + bool all) const +{ if (all || _pcScope != LinkScope::Hidden) { if (obj && obj == _pcLink) { _getLinksTo(identifiers, obj, subname, _SubList, _ShadowSubList); @@ -4124,58 +4666,66 @@ void PropertyXLink::getLinksTo(std::vector &identifiers, } } -bool PropertyXLink::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyXLink::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - if(!_pcLink || !_pcLink->isAttachedToDocument() || !inList.count(_pcLink)) + } + if (!_pcLink || !_pcLink->isAttachedToDocument() || !inList.count(_pcLink)) { return false; + } auto subs = _SubList; - auto link = adjustLinkSubs(this,inList,_pcLink,subs); - if(link) { - setValue(link,std::move(subs)); + auto link = adjustLinkSubs(this, inList, _pcLink, subs); + if (link) { + setValue(link, std::move(subs)); return true; } return false; } -std::vector PropertyXLink::getSubValues(bool newStyle) const { +std::vector PropertyXLink::getSubValues(bool newStyle) const +{ assert(_SubList.size() == _ShadowSubList.size()); std::vector ret; ret.reserve(_SubList.size()); std::string tmp; - for(size_t i=0;i<_ShadowSubList.size();++i) - ret.push_back(getSubNameWithStyle(_SubList[i],_ShadowSubList[i],newStyle,tmp)); + for (size_t i = 0; i < _ShadowSubList.size(); ++i) { + ret.push_back(getSubNameWithStyle(_SubList[i], _ShadowSubList[i], newStyle, tmp)); + } return ret; } -std::vector PropertyXLink::getSubValuesStartsWith(const char* starter, bool newStyle) const +std::vector PropertyXLink::getSubValuesStartsWith(const char* starter, + bool newStyle) const { (void)newStyle; std::vector temp; - for(const auto & it : _SubList) { - if(strncmp(starter, it.c_str(), strlen(starter)) == 0) { + for (const auto& it : _SubList) { + if (strncmp(starter, it.c_str(), strlen(starter)) == 0) { temp.push_back(it); } } return temp; } -void PropertyXLink::setAllowPartial(bool enable) { - setFlag(LinkAllowPartial,enable); - if(enable) +void PropertyXLink::setAllowPartial(bool enable) +{ + setFlag(LinkAllowPartial, enable); + if (enable) { return; + } auto owner = dynamic_cast(getContainer()); - if(!owner) + if (!owner) { return; - if(!App::GetApplication().isRestoring() && - !owner->getDocument()->isPerformingTransaction() && - !_pcLink && docInfo && !filePath.empty() && !objectName.empty() && - (!docInfo->pcDoc || docInfo->pcDoc->testStatus(Document::PartialDoc))) - { - auto path = docInfo->getDocPath(filePath.c_str(),owner->getDocument(),false); - if(!path.empty()) + } + if (!App::GetApplication().isRestoring() && !owner->getDocument()->isPerformingTransaction() + && !_pcLink && docInfo && !filePath.empty() && !objectName.empty() + && (!docInfo->pcDoc || docInfo->pcDoc->testStatus(Document::PartialDoc))) { + auto path = docInfo->getDocPath(filePath.c_str(), owner->getDocument(), false); + if (!path.empty()) { App::GetApplication().openDocument(path.c_str()); + } } } @@ -4183,42 +4733,41 @@ void PropertyXLink::setAllowPartial(bool enable) { // PropertyXLinkSub //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkSub , App::PropertyXLink) +TYPESYSTEM_SOURCE(App::PropertyXLinkSub, App::PropertyXLink) TYPESYSTEM_SOURCE(App::PropertyXLinkSubHidden, App::PropertyXLinkSub) -PropertyXLinkSub::PropertyXLinkSub(bool allowPartial, PropertyLinkBase *parent) - :PropertyXLink(allowPartial,parent) -{ - -} +PropertyXLinkSub::PropertyXLinkSub(bool allowPartial, PropertyLinkBase* parent) + : PropertyXLink(allowPartial, parent) +{} PropertyXLinkSub::~PropertyXLinkSub() = default; -bool PropertyXLinkSub::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName, PropertyLinkSubGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSub::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubChild::getClassTypeId().getName())==0) - { +bool PropertyXLinkSub::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, PropertyLinkSubGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSub::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubChild::getClassTypeId().getName()) == 0) { App::PropertyLinkSub linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); - setValue(linkProp.getValue(),linkProp.getSubValues()); + setValue(linkProp.getValue(), linkProp.getSubValues()); return true; } - return PropertyXLink::upgrade(reader,typeName); + return PropertyXLink::upgrade(reader, typeName); } -PyObject *PropertyXLinkSub::getPyObject() +PyObject* PropertyXLinkSub::getPyObject() { - if(!_pcLink) + if (!_pcLink) { Py_Return; + } Py::Tuple ret(2); - ret.setItem(0,Py::Object(_pcLink->getPyObject(),true)); - const auto &subs = getSubValues(false); + ret.setItem(0, Py::Object(_pcLink->getPyObject(), true)); + const auto& subs = getSubValues(false); Py::List list(subs.size()); int i = 0; PropertyString propString; - for (auto &sub : subs) { + for (auto& sub : subs) { propString.setValue(sub); list[i++] = Py::asObject(propString.getPyObject()); } @@ -4230,7 +4779,7 @@ PyObject *PropertyXLinkSub::getPyObject() // PropertyXLinkSubList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkSubList , App::PropertyLinkBase) +TYPESYSTEM_SOURCE(App::PropertyXLinkSubList, App::PropertyLinkBase) //************************************************************************** // Construction/Destruction @@ -4254,32 +4803,34 @@ int PropertyXLinkSubList::getSize() const return static_cast(_Links.size()); } -void PropertyXLinkSubList::setValue(DocumentObject* lValue,const char* SubName) +void PropertyXLinkSubList::setValue(DocumentObject* lValue, const char* SubName) { - std::map > values; - if(lValue) { - auto &subs = values[lValue]; - if(SubName) + std::map> values; + if (lValue) { + auto& subs = values[lValue]; + if (SubName) { subs.emplace_back(SubName); + } } setValues(std::move(values)); } -void PropertyXLinkSubList::setValues( - const std::vector& lValue, - const std::vector& lSubNames) -{ -#define CHECK_SUB_SIZE(_l,_r) do{\ - if(_l.size()!=_r.size())\ - FC_THROWM(Base::ValueError, "object and subname size mismatch");\ - }while(0) - CHECK_SUB_SIZE(lValue,lSubNames); - std::map > values; - int i=0; - for(auto &obj : lValue) { - const char *sub = lSubNames[i++]; - if(sub) +void PropertyXLinkSubList::setValues(const std::vector& lValue, + const std::vector& lSubNames) +{ +#define CHECK_SUB_SIZE(_l, _r) \ + do { \ + if (_l.size() != _r.size()) \ + FC_THROWM(Base::ValueError, "object and subname size mismatch"); \ + } while (0) + CHECK_SUB_SIZE(lValue, lSubNames); + std::map> values; + int i = 0; + for (auto& obj : lValue) { + const char* sub = lSubNames[i++]; + if (sub) { values[obj].emplace_back(sub); + } } setValues(std::move(values)); } @@ -4287,44 +4838,47 @@ void PropertyXLinkSubList::setValues( void PropertyXLinkSubList::setValues(const std::vector& lValue, const std::vector& lSubNames) { - CHECK_SUB_SIZE(lValue,lSubNames); - std::map > values; - int i=0; - for(auto &obj : lValue) + CHECK_SUB_SIZE(lValue, lSubNames); + std::map> values; + int i = 0; + for (auto& obj : lValue) { values[obj].push_back(lSubNames[i++]); + } setValues(std::move(values)); } -void PropertyXLinkSubList::setSubListValues(const std::vector &svalues) { - std::map > values; - for(auto &v : svalues) { - auto &s = values[v.first]; - s.reserve(s.size()+v.second.size()); - s.insert(s.end(),v.second.begin(),v.second.end()); +void PropertyXLinkSubList::setSubListValues(const std::vector& svalues) +{ + std::map> values; + for (auto& v : svalues) { + auto& s = values[v.first]; + s.reserve(s.size() + v.second.size()); + s.insert(s.end(), v.second.begin(), v.second.end()); } setValues(std::move(values)); } void PropertyXLinkSubList::setValues( - const std::map > &values) + const std::map>& values) { - setValues(std::map >(values)); + setValues(std::map>(values)); } void PropertyXLinkSubList::setValues( - std::map > &&values) + std::map>&& values) { - for(auto &v : values) { - if(!v.first || !v.first->isAttachedToDocument()) - FC_THROWM(Base::ValueError,"invalid document object"); + for (auto& v : values) { + if (!v.first || !v.first->isAttachedToDocument()) { + FC_THROWM(Base::ValueError, "invalid document object"); + } } atomic_change guard(*this); - for(auto it=_Links.begin(),itNext=it;it!=_Links.end();it=itNext) { + for (auto it = _Links.begin(), itNext = it; it != _Links.end(); it = itNext) { ++itNext; auto iter = values.find(it->getValue()); - if(iter == values.end()) { + if (iter == values.end()) { _Links.erase(it); continue; } @@ -4332,105 +4886,118 @@ void PropertyXLinkSubList::setValues( values.erase(iter); } - for(auto &v : values) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); - _Links.back().setValue(v.first,std::move(v.second)); + for (auto& v : values) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); + _Links.back().setValue(v.first, std::move(v.second)); } guard.tryInvoke(); } -void PropertyXLinkSubList::addValue(App::DocumentObject *obj, - const std::vector &subs, bool reset) +void PropertyXLinkSubList::addValue(App::DocumentObject* obj, + const std::vector& subs, + bool reset) { - addValue(obj,std::vector(subs),reset); + addValue(obj, std::vector(subs), reset); } -void PropertyXLinkSubList::addValue(App::DocumentObject *obj, - std::vector &&subs, bool reset) { +void PropertyXLinkSubList::addValue(App::DocumentObject* obj, + std::vector&& subs, + bool reset) +{ - if(!obj || !obj->isAttachedToDocument()) - FC_THROWM(Base::ValueError,"invalid document object"); + if (!obj || !obj->isAttachedToDocument()) { + FC_THROWM(Base::ValueError, "invalid document object"); + } - for(auto &l : _Links) { - if(l.getValue() == obj) { + for (auto& l : _Links) { + if (l.getValue() == obj) { auto s = l.getSubValues(); - if(s.empty() || reset) + if (s.empty() || reset) { l.setSubValues(std::move(subs)); + } else { - s.reserve(s.size()+subs.size()); - std::move(subs.begin(),subs.end(),std::back_inserter(s)); + s.reserve(s.size() + subs.size()); + std::move(subs.begin(), subs.end(), std::back_inserter(s)); l.setSubValues(std::move(s)); } return; } } atomic_change guard(*this); - _Links.emplace_back(testFlag(LinkAllowPartial),this); - _Links.back().setValue(obj,std::move(subs)); + _Links.emplace_back(testFlag(LinkAllowPartial), this); + _Links.back().setValue(obj, std::move(subs)); guard.tryInvoke(); } -void PropertyXLinkSubList::setValue(DocumentObject *lValue, const std::vector &SubList) +void PropertyXLinkSubList::setValue(DocumentObject* lValue, const std::vector& SubList) { - std::map > values; - if(lValue) + std::map> values; + if (lValue) { values[lValue] = SubList; + } setValues(std::move(values)); } -void PropertyXLinkSubList::setValues(const std::vector &values) { +void PropertyXLinkSubList::setValues(const std::vector& values) +{ atomic_change guard(*this); _Links.clear(); - for(auto obj : values) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); + for (auto obj : values) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().setValue(obj); } guard.tryInvoke(); } void PropertyXLinkSubList::set1Value(int idx, - DocumentObject *value, - const std::vector &SubList) + DocumentObject* value, + const std::vector& SubList) { - if(idx < -1 || idx > getSize()) + if (idx < -1 || idx > getSize()) { throw Base::RuntimeError("index out of bound"); + } - if(idx < 0 || idx+1 == getSize()) { - if(SubList.empty()) { - addValue(value,SubList); + if (idx < 0 || idx + 1 == getSize()) { + if (SubList.empty()) { + addValue(value, SubList); return; } atomic_change guard(*this); - _Links.emplace_back(testFlag(LinkAllowPartial),this); + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().setValue(value); guard.tryInvoke(); return; } auto it = _Links.begin(); - for(;idx;--idx) + for (; idx; --idx) { ++it; - it->setValue(value,SubList); + } + it->setValue(value, SubList); } const string PropertyXLinkSubList::getPyReprString() const { - if (_Links.empty()) + if (_Links.empty()) { return std::string("None"); + } std::ostringstream ss; ss << '['; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - ss << "(App.getDocument('" << obj->getDocument()->getName() - << "').getObject('" << obj->getNameInDocument() << "'), ("; - const auto &subs = link.getSubValues(); - if(subs.empty()) + } + ss << "(App.getDocument('" << obj->getDocument()->getName() << "').getObject('" + << obj->getNameInDocument() << "'), ("; + const auto& subs = link.getSubValues(); + if (subs.empty()) { ss << "''"; - else{ - for(auto &sub : subs) + } + else { + for (auto& sub : subs) { ss << "'" << sub << "',"; + } } ss << ")), "; } @@ -4438,20 +5005,22 @@ const string PropertyXLinkSubList::getPyReprString() const return ss.str(); } -DocumentObject *PropertyXLinkSubList::getValue() const +DocumentObject* PropertyXLinkSubList::getValue() const { - if(!_Links.empty()) + if (!_Links.empty()) { return _Links.begin()->getValue(); + } return nullptr; } -int PropertyXLinkSubList::removeValue(App::DocumentObject *lValue) +int PropertyXLinkSubList::removeValue(App::DocumentObject* lValue) { - atomic_change guard(*this,false); + atomic_change guard(*this, false); int ret = 0; - for(auto it=_Links.begin();it!=_Links.end();) { - if(it->getValue() != lValue) + for (auto it = _Links.begin(); it != _Links.end();) { + if (it->getValue() != lValue) { ++it; + } else { guard.aboutToChange(); it = _Links.erase(it); @@ -4462,18 +5031,19 @@ int PropertyXLinkSubList::removeValue(App::DocumentObject *lValue) return ret; } -PyObject *PropertyXLinkSubList::getPyObject() +PyObject* PropertyXLinkSubList::getPyObject() { Py::List list; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } Py::Tuple tup(2); tup[0] = Py::asObject(obj->getPyObject()); - const auto &subs = link.getSubValues(); + const auto& subs = link.getSubValues(); Py::Tuple items(subs.size()); for (std::size_t j = 0; j < subs.size(); j++) { items[j] = Py::String(subs[j]); @@ -4484,178 +5054,209 @@ PyObject *PropertyXLinkSubList::getPyObject() return Py::new_reference_to(list); } -void PropertyXLinkSubList::setPyObject(PyObject *value) +void PropertyXLinkSubList::setPyObject(PyObject* value) { - try { //try PropertyLinkSub syntax + try { // try PropertyLinkSub syntax PropertyLinkSub dummy; dummy.setAllowExternal(true); dummy.setPyObject(value); this->setValue(dummy.getValue(), dummy.getSubValues()); return; } - catch (Base::Exception&) {} + catch (Base::Exception&) { + } - if (!PyTuple_Check(value) && !PyList_Check(value)) - throw Base::TypeError("Invalid type. Accepts (DocumentObject, (subname...)) or sequence of such type."); + if (!PyTuple_Check(value) && !PyList_Check(value)) { + throw Base::TypeError( + "Invalid type. Accepts (DocumentObject, (subname...)) or sequence of such type."); + } Py::Sequence seq(value); - std::map > values; + std::map> values; try { - for(Py_ssize_t i=0;i" << endl; + } + writer.Stream() << "\">" << endl; writer.incInd(); - for(auto &l : _Links) + for (auto& l : _Links) { l.Save(writer); + } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyXLinkSubList::Restore(Base::XMLReader &reader) +void PropertyXLinkSubList::Restore(Base::XMLReader& reader) { reader.readElement("XLinkSubList"); setFlag(LinkAllowPartial, - reader.hasAttribute("partial") && - reader.getAttributeAsInteger("partial")); + reader.hasAttribute("partial") && reader.getAttributeAsInteger("partial")); int count = reader.getAttributeAsInteger("count"); - atomic_change guard(*this,false); + atomic_change guard(*this, false); _Links.clear(); - for(int i=0;i &nameMap) const +Property* +PropertyXLinkSubList::CopyOnImportExternal(const std::map& nameMap) const { std::unique_ptr copy; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { + for (; it != _Links.end(); ++it) { copy.reset(it->CopyOnImportExternal(nameMap)); - if(copy) break; + if (copy) { + break; + } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { + for (auto iter = _Links.begin(); iter != it; ++iter) { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } p->_Links.emplace_back(); static_cast(*copy).copyTo(p->_Links.back()); - for(++it;it!=_Links.end();++it) { + for (++it; it != _Links.end(); ++it) { p->_Links.emplace_back(); copy.reset(it->CopyOnImportExternal(nameMap)); - if(copy) + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const +Property* PropertyXLinkSubList::CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const { std::unique_ptr copy; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { - copy.reset(it->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) break; + for (; it != _Links.end(); ++it) { + copy.reset(it->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { + break; + } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { + for (auto iter = _Links.begin(); iter != it; ++iter) { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } p->_Links.emplace_back(); static_cast(*copy).copyTo(p->_Links.back()); - for(++it;it!=_Links.end();++it) { + for (++it; it != _Links.end(); ++it) { p->_Links.emplace_back(); - copy.reset(it->CopyOnLabelChange(obj,ref,newLabel)); - if(copy) + copy.reset(it->CopyOnLabelChange(obj, ref, newLabel)); + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const +Property* PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const { std::unique_ptr copy; - PropertyXLinkSub *copied = nullptr; + PropertyXLinkSub* copied = nullptr; std::set subs; auto it = _Links.begin(); - for(;it!=_Links.end();++it) { - copy.reset(it->CopyOnLinkReplace(parent,oldObj,newObj)); - if(copy) { + for (; it != _Links.end(); ++it) { + copy.reset(it->CopyOnLinkReplace(parent, oldObj, newObj)); + if (copy) { copied = static_cast(copy.get()); - if(copied->getValue() == newObj) { - for(auto &sub : copied->getSubValues()) + if (copied->getValue() == newObj) { + for (auto& sub : copied->getSubValues()) { subs.insert(sub); + } } break; } } - if(!copy) + if (!copy) { return nullptr; + } std::unique_ptr p(new PropertyXLinkSubList); - for(auto iter=_Links.begin();iter!=it;++iter) { - if(iter->getValue()==newObj && copied->getValue()==newObj) { + for (auto iter = _Links.begin(); iter != it; ++iter) { + if (iter->getValue() == newObj && copied->getValue() == newObj) { // merge subnames in case new object already exists - for(auto &sub : iter->getSubValues()) { - if(subs.insert(sub).second) + for (auto& sub : iter->getSubValues()) { + if (subs.insert(sub).second) { copied->_SubList.push_back(sub); + } } - } else { + } + else { p->_Links.emplace_back(); iter->copyTo(p->_Links.back()); } @@ -4663,113 +5264,128 @@ Property *PropertyXLinkSubList::CopyOnLinkReplace(const App::DocumentObject *par p->_Links.emplace_back(); copied->copyTo(p->_Links.back()); copied = &p->_Links.back(); - for(++it;it!=_Links.end();++it) { - if((it->getValue()==newObj||it->getValue()==oldObj) - && copied->getValue()==newObj) - { + for (++it; it != _Links.end(); ++it) { + if ((it->getValue() == newObj || it->getValue() == oldObj) + && copied->getValue() == newObj) { // merge subnames in case new object already exists - for(auto &sub : it->getSubValues()) { - if(subs.insert(sub).second) + for (auto& sub : it->getSubValues()) { + if (subs.insert(sub).second) { copied->_SubList.push_back(sub); + } } continue; } p->_Links.emplace_back(); - copy.reset(it->CopyOnLinkReplace(parent,oldObj,newObj)); - if(copy) + copy.reset(it->CopyOnLinkReplace(parent, oldObj, newObj)); + if (copy) { static_cast(*copy).copyTo(p->_Links.back()); - else + } + else { it->copyTo(p->_Links.back()); + } } return p.release(); } -Property *PropertyXLinkSubList::Copy() const +Property* PropertyXLinkSubList::Copy() const { - PropertyXLinkSubList *p = new PropertyXLinkSubList(); - for(auto &l : _Links) { - p->_Links.emplace_back(testFlag(LinkAllowPartial),p); + PropertyXLinkSubList* p = new PropertyXLinkSubList(); + for (auto& l : _Links) { + p->_Links.emplace_back(testFlag(LinkAllowPartial), p); l.copyTo(p->_Links.back()); } return p; } -void PropertyXLinkSubList::Paste(const Property &from) +void PropertyXLinkSubList::Paste(const Property& from) { - if(!from.isDerivedFrom(PropertyXLinkSubList::getClassTypeId())) + if (!from.isDerivedFrom(PropertyXLinkSubList::getClassTypeId())) { throw Base::TypeError("Incompatible property to paste to"); + } aboutToSetValue(); _Links.clear(); - for(auto &l : static_cast(from)._Links) { - _Links.emplace_back(testFlag(LinkAllowPartial),this); + for (auto& l : static_cast(from)._Links) { + _Links.emplace_back(testFlag(LinkAllowPartial), this); _Links.back().Paste(l); } hasSetValue(); } -unsigned int PropertyXLinkSubList::getMemSize () const +unsigned int PropertyXLinkSubList::getMemSize() const { - unsigned int size=0; - for(auto &l : _Links) + unsigned int size = 0; + for (auto& l : _Links) { size += l.getMemSize(); - return size; + } + return size; } -const std::vector &PropertyXLinkSubList::getSubValues(App::DocumentObject *obj) const { - for(auto &l : _Links) { - if(l.getValue() == obj) +const std::vector& PropertyXLinkSubList::getSubValues(App::DocumentObject* obj) const +{ + for (auto& l : _Links) { + if (l.getValue() == obj) { return l.getSubValues(); + } } FC_THROWM(Base::RuntimeError, "object not found"); } -std::vector PropertyXLinkSubList::getSubValues(App::DocumentObject *obj, bool newStyle) const { - for(auto &l : _Links) { - if(l.getValue() == obj) +std::vector PropertyXLinkSubList::getSubValues(App::DocumentObject* obj, + bool newStyle) const +{ + for (auto& l : _Links) { + if (l.getValue() == obj) { return l.getSubValues(newStyle); + } } return {}; } -void PropertyXLinkSubList::getLinks(std::vector &objs, - bool all, std::vector *subs, bool newStyle) const +void PropertyXLinkSubList::getLinks(std::vector& objs, + bool all, + std::vector* subs, + bool newStyle) const { - if(all||_pcScope!=LinkScope::Hidden) { - if(!subs) { - objs.reserve(objs.size()+_Links.size()); - for(auto &l : _Links) { + if (all || _pcScope != LinkScope::Hidden) { + if (!subs) { + objs.reserve(objs.size() + _Links.size()); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } return; } - size_t count=0; - for(auto &l : _Links) { + size_t count = 0; + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { count += std::max((int)l.getSubValues().size(), 1); + } } - if(!count) { - objs.reserve(objs.size()+_Links.size()); - for(auto &l : _Links) { + if (!count) { + objs.reserve(objs.size() + _Links.size()); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) + if (obj && obj->isAttachedToDocument()) { objs.push_back(obj); + } } return; } - objs.reserve(objs.size()+count); - subs->reserve(subs->size()+count); - for(auto &l : _Links) { + objs.reserve(objs.size() + count); + subs->reserve(subs->size() + count); + for (auto& l : _Links) { auto obj = l.getValue(); - if(obj && obj->isAttachedToDocument()) { + if (obj && obj->isAttachedToDocument()) { auto subnames = l.getSubValues(newStyle); - if (subnames.empty()) + if (subnames.empty()) { subnames.emplace_back(""); - for(auto &sub : subnames) { + } + for (auto& sub : subnames) { objs.push_back(obj); subs->push_back(std::move(sub)); } @@ -4837,7 +5453,7 @@ void PropertyXLinkSubList::getLinksTo(std::vector& identi const char* subname, bool all) const { - if ( ! all && _pcScope != LinkScope::Hidden) { + if (!all && _pcScope != LinkScope::Hidden) { return; } for (auto& l : _Links) { @@ -4847,14 +5463,15 @@ void PropertyXLinkSubList::getLinksTo(std::vector& identi } } -void PropertyXLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { - if(clear && getContainer()==obj) { +void PropertyXLinkSubList::breakLink(App::DocumentObject* obj, bool clear) +{ + if (clear && getContainer() == obj) { setValue(nullptr); return; } - atomic_change guard(*this,false); - for(auto &l : _Links) { - if(l.getValue() == obj) { + atomic_change guard(*this, false); + for (auto& l : _Links) { + if (l.getValue() == obj) { guard.aboutToChange(); l.setValue(nullptr); } @@ -4862,98 +5479,111 @@ void PropertyXLinkSubList::breakLink(App::DocumentObject *obj, bool clear) { guard.tryInvoke(); } -bool PropertyXLinkSubList::adjustLink(const std::set &inList) { - if (_pcScope==LinkScope::Hidden) +bool PropertyXLinkSubList::adjustLink(const std::set& inList) +{ + if (_pcScope == LinkScope::Hidden) { return false; - std::map > values; + } + std::map> values; bool touched = false; - int count=0; - for(auto &l : _Links) { + int count = 0; + for (auto& l : _Links) { auto obj = l.getValue(); - if(!obj || !obj->isAttachedToDocument()) { + if (!obj || !obj->isAttachedToDocument()) { ++count; continue; } - if(inList.count(obj) && adjustLinkSubs(this,inList,obj,l._SubList,&values)) + if (inList.count(obj) && adjustLinkSubs(this, inList, obj, l._SubList, &values)) { touched = true; + } } - if(touched) { + if (touched) { decltype(_Links) tmp; - if(count) { + if (count) { // XLink allows detached state, i.e. with closed external document. So // we need to preserve empty link - for(auto it=_Links.begin(),itNext=it;it!=_Links.end();it=itNext) { + for (auto it = _Links.begin(), itNext = it; it != _Links.end(); it = itNext) { ++itNext; - if(!it->getValue()) - tmp.splice(tmp.end(),_Links,it); + if (!it->getValue()) { + tmp.splice(tmp.end(), _Links, it); + } } } setValues(std::move(values)); - _Links.splice(_Links.end(),tmp); + _Links.splice(_Links.end(), tmp); } return touched; } -int PropertyXLinkSubList::checkRestore(std::string *msg) const { - for(auto &l : _Links) { +int PropertyXLinkSubList::checkRestore(std::string* msg) const +{ + for (auto& l : _Links) { int res; - if((res = l.checkRestore(msg))) + if ((res = l.checkRestore(msg))) { return res; + } } return 0; } -bool PropertyXLinkSubList::upgrade(Base::XMLReader &reader, const char *typeName) { - if(strcmp(typeName, PropertyLinkListGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkList::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkListChild::getClassTypeId().getName())==0) - { +bool PropertyXLinkSubList::upgrade(Base::XMLReader& reader, const char* typeName) +{ + if (strcmp(typeName, PropertyLinkListGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkList::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkListChild::getClassTypeId().getName()) == 0) { PropertyLinkList linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); setValues(linkProp.getValues()); return true; - } else if (strcmp(typeName, PropertyLinkSubListGlobal::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubList::getClassTypeId().getName())==0 || - strcmp(typeName, PropertyLinkSubListChild::getClassTypeId().getName())==0) - { + } + else if (strcmp(typeName, PropertyLinkSubListGlobal::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubList::getClassTypeId().getName()) == 0 + || strcmp(typeName, PropertyLinkSubListChild::getClassTypeId().getName()) == 0) { PropertyLinkSubList linkProp; linkProp.setContainer(getContainer()); linkProp.Restore(reader); - std::map > values; - const auto &objs = linkProp.getValues(); - const auto &subs = linkProp.getSubValues(); + std::map> values; + const auto& objs = linkProp.getValues(); + const auto& subs = linkProp.getSubValues(); assert(objs.size() == subs.size()); - for(size_t i=0;i PropertyXLinkSubList::getValues() const { std::vector xLinks; getLinks(xLinks); - return(xLinks); + return (xLinks); } //************************************************************************** // PropertyXLinkList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyXLinkList , App::PropertyXLinkSubList) +TYPESYSTEM_SOURCE(App::PropertyXLinkList, App::PropertyXLinkSubList) //************************************************************************** // Construction/Destruction @@ -4977,36 +5607,40 @@ PropertyXLinkList::PropertyXLinkList() = default; PropertyXLinkList::~PropertyXLinkList() = default; -PyObject *PropertyXLinkList::getPyObject() +PyObject* PropertyXLinkList::getPyObject() { - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - if(link.hasSubName()) + } + if (link.hasSubName()) { return PropertyXLinkSubList::getPyObject(); + } } Py::List list; - for(auto &link : _Links) { + for (auto& link : _Links) { auto obj = link.getValue(); - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; + } list.append(Py::asObject(obj->getPyObject())); } return Py::new_reference_to(list); } -void PropertyXLinkList::setPyObject(PyObject *value) +void PropertyXLinkList::setPyObject(PyObject* value) { - try { //try PropertyLinkList syntax + try { // try PropertyLinkList syntax PropertyLinkList dummy; dummy.setAllowExternal(true); dummy.setPyObject(value); this->setValues(dummy.getValues()); return; } - catch (Base::Exception&) {} + catch (Base::Exception&) { + } PropertyXLinkSubList::setPyObject(value); } @@ -5014,31 +5648,37 @@ void PropertyXLinkList::setPyObject(PyObject *value) //************************************************************************** // PropertyXLinkContainer //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyXLinkContainer , App::PropertyLinkBase) +TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyXLinkContainer, App::PropertyLinkBase) -PropertyXLinkContainer::PropertyXLinkContainer() { +PropertyXLinkContainer::PropertyXLinkContainer() +{ _pcScope = LinkScope::Global; _LinkRestored = false; } PropertyXLinkContainer::~PropertyXLinkContainer() = default; -void PropertyXLinkContainer::afterRestore() { +void PropertyXLinkContainer::afterRestore() +{ _DocMap.clear(); - if(!_XLinkRestores) + if (!_XLinkRestores) { return; + } _Deps.clear(); - for(auto &info : *_XLinkRestores) { + for (auto& info : *_XLinkRestores) { auto obj = info.xlink->getValue(); - if(!obj) + if (!obj) { continue; - if(!info.docName.empty()) { - if(info.docName != obj->getDocument()->getName()) + } + if (!info.docName.empty()) { + if (info.docName != obj->getDocument()->getName()) { _DocMap[info.docName] = obj->getDocument()->getName(); - if(info.docLabel != obj->getDocument()->Label.getValue()) + } + if (info.docLabel != obj->getDocument()->Label.getValue()) { _DocMap[App::quote(info.docLabel)] = obj->getDocument()->Label.getValue(); + } } - if(_Deps.insert(std::make_pair(obj,info.xlink->getScope()==LinkScope::Hidden)).second) { + if (_Deps.insert(std::make_pair(obj, info.xlink->getScope() == LinkScope::Hidden)).second) { _XLinks[obj->getFullName()] = std::move(info.xlink); onAddDep(obj); } @@ -5046,253 +5686,292 @@ void PropertyXLinkContainer::afterRestore() { _XLinkRestores.reset(); } -void PropertyXLinkContainer::breakLink(App::DocumentObject *obj, bool clear) { - if(!obj || !obj->isAttachedToDocument()) +void PropertyXLinkContainer::breakLink(App::DocumentObject* obj, bool clear) +{ + if (!obj || !obj->isAttachedToDocument()) { return; + } auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; - if(!clear || obj!=owner) { + } + if (!clear || obj != owner) { auto it = _Deps.find(obj); - if(it == _Deps.end()) + if (it == _Deps.end()) { return; + } aboutToSetValue(); onBreakLink(obj); - if (obj->getDocument() != owner->getDocument()) + if (obj->getDocument() != owner->getDocument()) { _XLinks.erase(obj->getFullName()); - else if (!it->second) + } + else if (!it->second) { obj->_removeBackLink(owner); + } _Deps.erase(it); onRemoveDep(obj); hasSetValue(); return; } - if(obj!=owner) + if (obj != owner) { return; - for(auto &v : _Deps) { + } + for (auto& v : _Deps) { auto key = v.first; - if(!key || !key->isAttachedToDocument()) + if (!key || !key->isAttachedToDocument()) { continue; + } onBreakLink(key); - if(!v.second && key->getDocument()==owner->getDocument()) + if (!v.second && key->getDocument() == owner->getDocument()) { key->_removeBackLink(owner); + } } _XLinks.clear(); _Deps.clear(); } -int PropertyXLinkContainer::checkRestore(std::string *msg) const { - if(_LinkRestored) { - for(auto &v : _XLinks) { +int PropertyXLinkContainer::checkRestore(std::string* msg) const +{ + if (_LinkRestored) { + for (auto& v : _XLinks) { int res = v.second->checkRestore(msg); - if(res) + if (res) { return res; + } } } return 0; } -void PropertyXLinkContainer::Save (Base::Writer &writer) const { +void PropertyXLinkContainer::Save(Base::Writer& writer) const +{ writer.Stream() << writer.ind() << " docSet; + std::map docSet; auto owner = Base::freecad_dynamic_cast(getContainer()); - if(owner && !owner->isExporting()) { + if (owner && !owner->isExporting()) { // Document name and label can change on restore, we shall record the // current document name and label and pair it with the associated // xlink, so that we can restore them correctly. - int i=-1; - for(auto &v : _XLinks) { + int i = -1; + for (auto& v : _XLinks) { ++i; auto obj = v.second->getValue(); - if(obj && obj->getDocument()) - docSet.insert(std::make_pair(obj->getDocument(),i)); + if (obj && obj->getDocument()) { + docSet.insert(std::make_pair(obj->getDocument(), i)); + } } - if(!docSet.empty()) + if (!docSet.empty()) { writer.Stream() << "\" docs=\"" << docSet.size(); + } } std::ostringstream ss; int hidden = 0; - int i=-1; - for(auto &v : _XLinks) { + int i = -1; + for (auto& v : _XLinks) { ++i; - if(v.second->getScope() == LinkScope::Hidden) { + if (v.second->getScope() == LinkScope::Hidden) { ss << i << ' '; ++hidden; } } - if(hidden) + if (hidden) { writer.Stream() << "\" hidden=\"" << ss.str(); + } writer.Stream() << "\">" << std::endl; writer.incInd(); - for(auto &v : docSet) { + for (auto& v : docSet) { writer.Stream() << writer.ind() << "getName() - << "\" label=\"" << encodeAttribute(v.first->Label.getValue()) - << "\" index=\"" << v.second << "\"/>" << std::endl; + << "name=\"" << v.first->getName() << "\" label=\"" + << encodeAttribute(v.first->Label.getValue()) << "\" index=\"" << v.second + << "\"/>" << std::endl; } - for(auto &v : _XLinks) + for (auto& v : _XLinks) { v.second->Save(writer); + } writer.decInd(); writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyXLinkContainer::Restore(Base::XMLReader &reader) { +void PropertyXLinkContainer::Restore(Base::XMLReader& reader) +{ reader.readElement("XLinks"); auto count = reader.getAttributeAsUnsigned("count"); _XLinkRestores = std::make_unique>(count); - if(reader.hasAttribute("hidden")) { + if (reader.hasAttribute("hidden")) { std::istringstream iss(reader.getAttribute("hidden")); int index; - while(iss >> index) { - if(index>=0 && index(count)) + while (iss >> index) { + if (index >= 0 && index < static_cast(count)) { _XLinkRestores->at(index).hidden = true; + } } } - if(reader.hasAttribute("docs")) { + if (reader.hasAttribute("docs")) { auto docCount = reader.getAttributeAsUnsigned("docs"); _DocMap.clear(); - for(unsigned i=0;i=count) { + if (index >= count) { FC_ERR(propertyName(this) << " invalid document map entry"); continue; } - auto &info = _XLinkRestores->at(index); + auto& info = _XLinkRestores->at(index); info.docName = reader.getAttribute("name"); info.docLabel = reader.getAttribute("label"); } } - for(auto &info : *_XLinkRestores) { + for (auto& info : *_XLinkRestores) { info.xlink.reset(createXLink()); - if(info.hidden) + if (info.hidden) { info.xlink->setScope(LinkScope::Hidden); + } info.xlink->Restore(reader); } reader.readEndElement("XLinks"); } -void PropertyXLinkContainer::aboutToSetChildValue(App::Property &prop) { +void PropertyXLinkContainer::aboutToSetChildValue(App::Property& prop) +{ auto xlink = dynamic_cast(&prop); - if(xlink && xlink->testFlag(LinkDetached)) { + if (xlink && xlink->testFlag(LinkDetached)) { auto obj = const_cast(xlink->getValue()); - if(_Deps.erase(obj)) { + if (_Deps.erase(obj)) { _onBreakLink(xlink->getValue()); onRemoveDep(obj); } } } -void PropertyXLinkContainer::onBreakLink(DocumentObject *) { -} +void PropertyXLinkContainer::onBreakLink(DocumentObject*) +{} -void PropertyXLinkContainer::_onBreakLink(DocumentObject *obj) { +void PropertyXLinkContainer::_onBreakLink(DocumentObject* obj) +{ try { onBreakLink(obj); - } catch (Base::Exception &e) { + } + catch (Base::Exception& e) { e.ReportException(); FC_ERR("Exception on breaking link property " << getFullName()); - } catch (std::exception &e) { + } + catch (std::exception& e) { FC_ERR("Exception on breaking link property " << getFullName() << ": " << e.what()); - } catch (...) { + } + catch (...) { FC_ERR("Exception on breaking link property " << getFullName()); } } -PropertyXLink *PropertyXLinkContainer::createXLink() { - return new PropertyXLink(false,this); +PropertyXLink* PropertyXLinkContainer::createXLink() +{ + return new PropertyXLink(false, this); } -bool PropertyXLinkContainer::isLinkedToDocument(const App::Document &doc) const { +bool PropertyXLinkContainer::isLinkedToDocument(const App::Document& doc) const +{ auto iter = _XLinks.lower_bound(doc.getName()); - if(iter != _XLinks.end()) { + if (iter != _XLinks.end()) { size_t len = strlen(doc.getName()); - return iter->first.size()>len - && iter->first[len] == '#' - && boost::starts_with(iter->first,doc.getName()); + return iter->first.size() > len && iter->first[len] == '#' + && boost::starts_with(iter->first, doc.getName()); } return false; } -void PropertyXLinkContainer::updateDeps(std::map &&newDeps) { +void PropertyXLinkContainer::updateDeps(std::map&& newDeps) +{ auto owner = Base::freecad_dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; + } newDeps.erase(owner); - for(auto &v : newDeps) { + for (auto& v : newDeps) { auto obj = v.first; - if(obj && obj->isAttachedToDocument()) { + if (obj && obj->isAttachedToDocument()) { auto it = _Deps.find(obj); - if(it != _Deps.end()) { - if(v.second != it->second) { - if(v.second) + if (it != _Deps.end()) { + if (v.second != it->second) { + if (v.second) { obj->_removeBackLink(owner); - else + } + else { obj->_addBackLink(owner); + } } _Deps.erase(it); continue; } - if(owner->getDocument()!=obj->getDocument()) { - auto &xlink = _XLinks[obj->getFullName()]; - if(!xlink) { + if (owner->getDocument() != obj->getDocument()) { + auto& xlink = _XLinks[obj->getFullName()]; + if (!xlink) { xlink.reset(createXLink()); xlink->setValue(obj); } - xlink->setScope(v.second?LinkScope::Hidden:LinkScope::Global); + xlink->setScope(v.second ? LinkScope::Hidden : LinkScope::Global); } - else if(!v.second) + else if (!v.second) { obj->_addBackLink(owner); + } onAddDep(obj); } } - for(auto &v : _Deps) { + for (auto& v : _Deps) { auto obj = v.first; - if(!obj || !obj->isAttachedToDocument()) + if (!obj || !obj->isAttachedToDocument()) { continue; - if(obj->getDocument()==owner->getDocument()) { - if(!v.second) + } + if (obj->getDocument() == owner->getDocument()) { + if (!v.second) { obj->_removeBackLink(owner); - }else + } + } + else { _XLinks.erase(obj->getFullName()); + } onRemoveDep(obj); } _Deps = std::move(newDeps); _LinkRestored = testFlag(LinkRestoring); - if(!_LinkRestored && !testFlag(LinkDetached)) { - for(auto it=_XLinks.begin(),itNext=it;it!=_XLinks.end();it=itNext) { + if (!_LinkRestored && !testFlag(LinkDetached)) { + for (auto it = _XLinks.begin(), itNext = it; it != _XLinks.end(); it = itNext) { ++itNext; - if(!it->second->getValue()) + if (!it->second->getValue()) { _XLinks.erase(it); + } } } } -void PropertyXLinkContainer::clearDeps() { +void PropertyXLinkContainer::clearDeps() +{ auto owner = dynamic_cast(getContainer()); - if(!owner || !owner->isAttachedToDocument()) + if (!owner || !owner->isAttachedToDocument()) { return; + } #ifndef USE_OLD_DAG if (!owner->testStatus(ObjectStatus::Destroy)) { - for(auto &v : _Deps) { + for (auto& v : _Deps) { auto obj = v.first; - if(!v.second && obj && obj->isAttachedToDocument() && obj->getDocument()==owner->getDocument()) + if (!v.second && obj && obj->isAttachedToDocument() + && obj->getDocument() == owner->getDocument()) { obj->_removeBackLink(owner); + } } } #endif @@ -5301,11 +5980,14 @@ void PropertyXLinkContainer::clearDeps() { _LinkRestored = false; } -void PropertyXLinkContainer::getLinks(std::vector &objs, - bool all, std::vector * /*subs*/, bool /*newStyle*/) const +void PropertyXLinkContainer::getLinks(std::vector& objs, + bool all, + std::vector* /*subs*/, + bool /*newStyle*/) const { - for(auto &v : _Deps) { - if(all || !v.second) + for (auto& v : _Deps) { + if (all || !v.second) { objs.push_back(v.first); + } } } diff --git a/src/App/PropertyLinks.h b/src/App/PropertyLinks.h index 63f8a71dc8ce..edf2d6b09821 100644 --- a/src/App/PropertyLinks.h +++ b/src/App/PropertyLinks.h @@ -33,7 +33,8 @@ #include "Property.h" -namespace Base { +namespace Base +{ class Writer; } @@ -51,13 +52,13 @@ class PropertyXLink; /** * @brief Defines different scopes for which a link can be valid - * The scopes defined in this enum describe the different possibilities of where a link can point to. - * Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none. - * Child: links are valid within the same or any sub GeoFeatureGroup - * Global: all possible links are valid - * Hidden: links are not included in dependency calculation + * The scopes defined in this enum describe the different possibilities of where a link can point + * to. Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in + * none. Child: links are valid within the same or any sub GeoFeatureGroup Global: all possible + * links are valid Hidden: links are not included in dependency calculation */ -enum class LinkScope { +enum class LinkScope +{ Local, Child, Global, @@ -66,43 +67,51 @@ enum class LinkScope { /** * @brief Enables scope handling for links - * This class is a base for all link properties and enables them to handle scopes of the linked objects. - * The possible scopes are defined by LinkScope enum class. The default value is Local. - * The scope of a property is not saved in the document. It is a value that needs to be fixed when - * the object holding the property is loaded. That is possible with two methods: + * This class is a base for all link properties and enables them to handle scopes of the linked + * objects. The possible scopes are defined by LinkScope enum class. The default value is Local. The + * scope of a property is not saved in the document. It is a value that needs to be fixed when the + * object holding the property is loaded. That is possible with two methods: * 1. Set the scope value in the constructor of the link property * 2. Use setScope to change the scope in the constructor of the link property * * The second option is only available in c++, not in python, as setscope is not exposed. It would - * not make sense to expose it there, as restoring python objects does not call the constructor again. - * Hence in python the only way to create a LinkProperty with different scope than local is to use a - * specialized property for that. In c++ existing properties can simply be changed via setScope in the - * objects constructor. + * not make sense to expose it there, as restoring python objects does not call the constructor + * again. Hence in python the only way to create a LinkProperty with different scope than local is + * to use a specialized property for that. In c++ existing properties can simply be changed via + * setScope in the objects constructor. */ -class AppExport ScopedLink { +class AppExport ScopedLink +{ public: /** * @brief Set the links scope - * Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and - * all Childs or to all objects within the Glocal scope. + * Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this + * and all Childs or to all objects within the Glocal scope. */ - void setScope(LinkScope scope) {_pcScope = scope;}; + void setScope(LinkScope scope) + { + _pcScope = scope; + } /** * @brief Get the links scope * Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and * all Childs or to all objects within the Glocal scope. */ - LinkScope getScope() const {return _pcScope;}; - + LinkScope getScope() const + { + return _pcScope; + } + protected: LinkScope _pcScope = LinkScope::Local; }; /// Parent class of all link type properties -class AppExport PropertyLinkBase : public Property, public ScopedLink +class AppExport PropertyLinkBase: public Property, public ScopedLink { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: using ShadowSub = ElementNamePair; @@ -121,8 +130,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * * @sa _updateElementReference() */ - virtual void updateElementReference(App::DocumentObject *feature, - bool reverse=false, bool notify=false) + virtual void + updateElementReference(App::DocumentObject* feature, bool reverse = false, bool notify = false) { (void)feature; (void)reverse; @@ -138,7 +147,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @param reset: if true, then calls unregisterLabelReference() before * registering */ - void registerLabelReferences(std::vector &&labels, bool reset=true); + void registerLabelReferences(std::vector&& labels, bool reset = true); /** Check subnames for label registration * @@ -149,13 +158,14 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * Check the give subname references and extract any label reference * inside (by calling getLabelReferences()), and register them. */ - void checkLabelReferences(const std::vector &subs, bool reset=true); + void checkLabelReferences(const std::vector& subs, bool reset = true); /// Clear internal label references registration void unregisterLabelReferences(); /// Test if the element reference has changed after restore - virtual bool referenceChanged() const { + virtual bool referenceChanged() const + { return false; } @@ -166,7 +176,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @return For external linked object, return 2 in case the link is * missing, and 1 if the time stamp has changed. */ - virtual int checkRestore(std::string *msg=nullptr) const { + virtual int checkRestore(std::string* msg = nullptr) const + { (void)msg; return 0; } @@ -180,8 +191,10 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @param sub: if given, then return subname references. * @param newStyle: whether to return new or old style subname reference */ - virtual void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const = 0; + virtual void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const = 0; /** Obtain identifiers from this link property that link to a given object * @param identifiers: holds the returned identifier to reference the given object @@ -191,10 +204,10 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * this LinkScope. If false, then return only if the LinkScope * is not hidden. */ - virtual void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const = 0; + virtual void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const = 0; /** Called to reset this link property * @@ -203,7 +216,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * * @sa breakLinks() */ - virtual void breakLink(App::DocumentObject *obj, bool clear) = 0; + virtual void breakLink(App::DocumentObject* obj, bool clear) = 0; /** Called to adjust the link to avoid potential cyclic dependency * @@ -214,7 +227,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * This function tries to correct the link to avoid any (sub)object inside * in-list. If the adjustment is impossible, exception will be raised */ - virtual bool adjustLink(const std::set &inList) = 0; + virtual bool adjustLink(const std::set& inList) = 0; /** Return a copy of the property if the link replacement affects this property * @@ -228,8 +241,9 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @return Return a copy of the property that is adjusted for the link * replacement operation. */ - virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const = 0; + virtual Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const = 0; /** Return a copy of the property if any changes caused by importing external linked object * @@ -240,7 +254,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * affected. The copy will later be assgiend to this property by calling its * Paste(). */ - virtual Property *CopyOnImportExternal(const std::map &nameMap) const { + virtual Property* CopyOnImportExternal(const std::map& nameMap) const + { (void)nameMap; return nullptr; } @@ -254,8 +269,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @return Returns a copy of the property if its link reference is affected. * The copy will later be assgiend to this property by calling its Paste(). */ - virtual Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const + virtual Property* + CopyOnLabelChange(App::DocumentObject* obj, const std::string& ref, const char* newLabel) const { (void)obj; (void)ref; @@ -264,44 +279,48 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink } /// Helper function to return all linked objects of this property - std::vector linkedObjects(bool all=false) const { + std::vector linkedObjects(bool all = false) const + { std::vector ret; - getLinks(ret,all); + getLinks(ret, all); return ret; } /// Helper function to return linked objects using an std::inserter template - void getLinkedObjects(T &inserter, bool all=false) const { + void getLinkedObjects(T& inserter, bool all = false) const + { std::vector ret; - getLinks(ret,all); - std::copy(ret.begin(),ret.end(),inserter); + getLinks(ret, all); + std::copy(ret.begin(), ret.end(), inserter); } /// Helper function to return a map of linked object and its subname references - void getLinkedElements(std::map > &elements, - bool newStyle=true, bool all=false) const + void getLinkedElements(std::map>& elements, + bool newStyle = true, + bool all = false) const { std::vector ret; std::vector subs; - getLinks(ret,all,&subs,newStyle); - assert(ret.size()==subs.size()); - int i=0; - for(auto obj : ret) + getLinks(ret, all, &subs, newStyle); + assert(ret.size() == subs.size()); + int i = 0; + for (auto obj : ret) { elements[obj].push_back(subs[i++]); + } } /// Helper function to return a map of linked object and its subname references - std::map > - linkedElements(bool newStyle=true, bool all=false) const + std::map> linkedElements(bool newStyle = true, + bool all = false) const { - std::map > ret; - getLinkedElements(ret,newStyle,all); + std::map> ret; + getLinkedElements(ret, newStyle, all); return ret; } //@} - bool isSame(const Property &other) const override; + bool isSame(const Property& other) const override; /** Enable/disable temporary holding external object without throwing exception * @@ -334,10 +353,13 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * through the group will be broken. This helper function is used to check * and correct any link sub reference. */ - static std::pair tryReplaceLink( - const App::PropertyContainer *owner, App::DocumentObject *obj, - const App::DocumentObject *parent, App::DocumentObject *oldObj, - App::DocumentObject *newObj, const char *sub=nullptr); + static std::pair + tryReplaceLink(const App::PropertyContainer* owner, + App::DocumentObject* obj, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj, + const char* sub = nullptr); /** Helper function to check and replace a link with multiple subname references * @@ -353,19 +375,19 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * pair.first will be NULL * @sa tryReplaceLink() */ - static std::pair > - tryReplaceLinkSubs( const App::PropertyContainer *owner, - App::DocumentObject *obj, - const App::DocumentObject *parent, - App::DocumentObject *oldObj, - App::DocumentObject *newObj, - const std::vector &subs); + static std::pair> + tryReplaceLinkSubs(const App::PropertyContainer* owner, + App::DocumentObject* obj, + const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj, + const std::vector& subs); /// Update all element references in all link properties of \a feature - static void updateElementReferences(DocumentObject *feature, bool reverse=false); + static void updateElementReferences(DocumentObject* feature, bool reverse = false); /// Obtain link properties that contain element references to a given object - static const std::unordered_set& getElementReferences(DocumentObject *); + static const std::unordered_set& getElementReferences(DocumentObject*); /** Helper function for update individual element reference * @@ -383,9 +405,12 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * This helper function is to be called by each link property in the event of * geometry element reference change due to geometry model changes. */ - bool _updateElementReference(App::DocumentObject *feature, - App::DocumentObject *obj, std::string &sub, ShadowSub &shadow, - bool reverse, bool notify=false); + bool _updateElementReference(App::DocumentObject* feature, + App::DocumentObject* obj, + std::string& sub, + ShadowSub& shadow, + bool reverse, + bool notify = false); /** Helper function to register geometry element reference * @@ -396,7 +421,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * Search for any geometry element reference inside the subname, and * register for future update in case of geometry model update. */ - void _registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow); + void _registerElementReference(App::DocumentObject* obj, std::string& sub, ShadowSub& shadow); /** Helper function for breaking link properties * @@ -406,7 +431,9 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * * App::Document::breakDependency() calls this function to break the link property */ - static void breakLinks(App::DocumentObject *link, const std::vector &objs, bool clear); + static void breakLinks(App::DocumentObject* link, + const std::vector& objs, + bool clear); /** Helper function for link import operation * @@ -423,8 +450,10 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * the API CopyOnImportExternal(). This function helps to rewrite subname * reference to point to the correct sub objects that are imported. */ - static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub, - const App::Document *doc, const std::map &nameMap); + static std::string tryImportSubName(const App::DocumentObject* obj, + const char* sub, + const App::Document* doc, + const std::map& nameMap); /** Helper function for link import operation * @@ -438,8 +467,9 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * This function searches for the name map and tries to find the imported * object from the given source object. */ - static App::DocumentObject *tryImport(const App::Document *doc, const App::DocumentObject *obj, - const std::map &nameMap); + static App::DocumentObject* tryImport(const App::Document* doc, + const App::DocumentObject* obj, + const std::map& nameMap); /** Helper function to export a subname reference * @@ -463,8 +493,10 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * restoreLabelReference() can be used together to restore the reference * during import. */ - static const char *exportSubName(std::string &output, - const App::DocumentObject *obj, const char *subname, bool first_obj=false); + static const char* exportSubName(std::string& output, + const App::DocumentObject* obj, + const char* subname, + bool first_obj = false); /** Helper function to import a subname reference * @@ -481,7 +513,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * after restore, by calling restoreLabelReference() in property's * afterRestore(). */ - static std::string importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel); + static std::string importSubName(Base::XMLReader& reader, const char* sub, bool& restoreLabel); /** Helper function to restore label references during import * @@ -503,7 +535,9 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * afterRestore() function, which calls this function to do the string * parsing. */ - static void restoreLabelReference(const App::DocumentObject *obj, std::string &sub, ShadowSub *shadow=nullptr); + static void restoreLabelReference(const App::DocumentObject* obj, + std::string& sub, + ShadowSub* shadow = nullptr); /** Helper function to extract labels from a subname reference * @@ -515,7 +549,7 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * This function is used to extract label from subname reference for * registering of label changes. */ - static void getLabelReferences(std::vector &labels, const char *subname); + static void getLabelReferences(std::vector& labels, const char* subname); /** Helper function to collect changed property when an object re-label * @@ -525,8 +559,8 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * @return return a map from the affected property to a copy of it with * updated subname references */ - static std::vector > > updateLabelReferences( - App::DocumentObject *obj, const char *newLabel); + static std::vector>> + updateLabelReferences(App::DocumentObject* obj, const char* newLabel); /** Helper function to update subname reference on label change * @@ -547,47 +581,56 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * called, the sub object can still be reached using the original label * references, but not the new labels. */ - static std::string updateLabelReference(const App::DocumentObject *linked, const char *subname, - App::DocumentObject *obj, const std::string &ref, const char *newLabel); + static std::string updateLabelReference(const App::DocumentObject* linked, + const char* subname, + App::DocumentObject* obj, + const std::string& ref, + const char* newLabel); //@} - enum LinkFlags { + enum LinkFlags + { LinkAllowExternal, LinkDetached, LinkRestoring, LinkAllowPartial, LinkRestoreLabel, - LinkSyncSubObject, // used by DlgPropertyLink - LinkNewElement, // return new element name in getPyObject - LinkSilentRestore, // do not report error on restore (e.g. missing external link) + LinkSyncSubObject, // used by DlgPropertyLink + LinkNewElement, // return new element name in getPyObject + LinkSilentRestore, // do not report error on restore (e.g. missing external link) }; - inline bool testFlag(int flag) const { + inline bool testFlag(int flag) const + { return _Flags.test((std::size_t)flag); } - virtual void setAllowPartial(bool enable) { (void)enable; } + virtual void setAllowPartial(bool enable) + { + (void)enable; + } void setReturnNewElement(bool enable); void setSilentRestore(bool enable); - boost::signals2::signal signalUpdateElementReference; + boost::signals2::signal + signalUpdateElementReference; protected: void hasSetValue() override; protected: std::bitset<32> _Flags; - inline void setFlag(int flag, bool value=true) { - _Flags.set((std::size_t)flag,value); + inline void setFlag(int flag, bool value = true) + { + _Flags.set((std::size_t)flag, value); } - void _getLinksTo( - std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - const std::vector &subs, - const std::vector &shadows) const; + void _getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + const std::vector& subs, + const std::vector& shadows) const; private: std::set _LabelRefs; @@ -599,10 +642,10 @@ class AppExport PropertyLinkBase : public Property, public ScopedLink * property is scope aware, meaning it does define which objects are allowed to be linked depending * of the GeoFeatureGroup where it is in. Default is Local. * - * @note Links that are invalid in respect to the scope of this property is set to are not rejected. - * They are only detected to be invalid and prevent the feature from recomputing. + * @note Links that are invalid in respect to the scope of this property is set to are not + * rejected. They are only detected to be invalid and prevent the feature from recomputing. */ -class AppExport PropertyLink : public PropertyLinkBase +class AppExport PropertyLink: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -623,98 +666,121 @@ class AppExport PropertyLink : public PropertyLinkBase /** Sets the property */ - virtual void setValue(App::DocumentObject *); + virtual void setValue(App::DocumentObject*); /** This method returns the linked DocumentObject */ - App::DocumentObject * getValue() const; + App::DocumentObject* getValue() const; /** Returns the link type checked */ - App::DocumentObject * getValue(Base::Type t) const; + App::DocumentObject* getValue(Base::Type t) const; - /** Returns the link type checked + /** Returns the link type checked */ - template - inline _type getValue() const { + template + inline _type getValue() const + { return _pcLink ? dynamic_cast<_type>(_pcLink) : 0; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override { - return sizeof(App::DocumentObject *); + unsigned int getMemSize() const override + { + return sizeof(App::DocumentObject*); } const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } + { + return "Gui::PropertyEditor::PropertyLinkItem"; + } + + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void breakLink(App::DocumentObject* obj, bool clear) override; - void breakLink(App::DocumentObject *obj, bool clear) override; + bool adjustLink(const std::set& inList) override; - bool adjustLink(const std::set &inList) override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; protected: - App::DocumentObject *_pcLink{nullptr}; + App::DocumentObject* _pcLink {nullptr}; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkChild : public PropertyLink +class AppExport PropertyLinkChild: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkChild() {_pcScope = LinkScope::Child;} + PropertyLinkChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkGlobal : public PropertyLink +class AppExport PropertyLinkGlobal: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkHidden : public PropertyLink +class AppExport PropertyLinkHidden: public PropertyLink { TYPESYSTEM_HEADER(); + public: - PropertyLinkHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkHidden() + { + _pcScope = LinkScope::Hidden; + } }; class AppExport PropertyLinkListBase: public PropertyLinkBase, public PropertyListsBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: - void setPyObject(PyObject *obj) override { + void setPyObject(PyObject* obj) override + { _setPyObject(obj); } }; -class AppExport PropertyLinkList : - public PropertyListsT, PropertyLinkListBase> +class AppExport PropertyLinkList + : public PropertyListsT, PropertyLinkListBase> { TYPESYSTEM_HEADER_WITH_OVERRIDE(); - using inherited = PropertyListsT,PropertyLinkListBase>; + using inherited = + PropertyListsT, PropertyLinkListBase>; public: /** @@ -733,43 +799,48 @@ class AppExport PropertyLinkList : void setSize(int newSize, const_reference def) override; /** Sets the property - */ - void setValues(const std::vector&) override; + */ + void setValues(const std::vector& value) override; - void set1Value(int idx, DocumentObject * const &value) override; + void set1Value(int idx, DocumentObject* const& value) override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save(Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; unsigned int getMemSize() const override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - DocumentObject *findUsingMap(const std::string &, int *pindex=nullptr) const; - DocumentObject *find(const char *sub, int *pindex=nullptr) const; + DocumentObject* findUsingMap(const std::string&, int* pindex = nullptr) const; + DocumentObject* find(const char* sub, int* pindex = nullptr) const; protected: - DocumentObject *getPyValue(PyObject *item) const override; + DocumentObject* getPyValue(PyObject* item) const override; protected: mutable std::map _nameMap; @@ -777,29 +848,41 @@ class AppExport PropertyLinkList : /** The general Link Property with Child scope */ -class AppExport PropertyLinkListChild : public PropertyLinkList +class AppExport PropertyLinkListChild: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListChild() {_pcScope = LinkScope::Child;} + PropertyLinkListChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkListGlobal : public PropertyLinkList +class AppExport PropertyLinkListGlobal: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkListGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkListHidden : public PropertyLinkList +class AppExport PropertyLinkListHidden: public PropertyLinkList { TYPESYSTEM_HEADER(); + public: - PropertyLinkListHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkListHidden() + { + _pcScope = LinkScope::Hidden; + } }; /** the Link Property with sub elements @@ -808,7 +891,7 @@ class AppExport PropertyLinkListHidden : public PropertyLinkList * are stored as names, which can be resolved by the * ComplexGeoDataType interface to concrete sub objects. */ -class AppExport PropertyLinkSub : public PropertyLinkBase +class AppExport PropertyLinkSub: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -830,123 +913,149 @@ class AppExport PropertyLinkSub : public PropertyLinkBase /** Sets the property */ - void setValue(App::DocumentObject *,const std::vector &SubList, - std::vector &&ShadowSubList={}); - void setValue(App::DocumentObject *,std::vector &&SubList={}, - std::vector &&ShadowSubList={}); + void setValue(App::DocumentObject*, + const std::vector& SubList, + std::vector&& ShadowSubList = {}); + void setValue(App::DocumentObject*, + std::vector&& SubList = {}, + std::vector&& ShadowSubList = {}); /** This method returns the linked DocumentObject */ - App::DocumentObject * getValue() const; + App::DocumentObject* getValue() const; /// return the list of sub elements const std::vector& getSubValues() const; /// return the list of sub elements with mapped names - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } std::vector getSubValues(bool newStyle) const; /// return the list of sub elements starts with a special string - std::vector getSubValuesStartsWith(const char*, bool newStyle=false) const; + std::vector getSubValuesStartsWith(const char*, bool newStyle = false) const; /** Returns the link type checked */ - App::DocumentObject * getValue(Base::Type t) const; + App::DocumentObject* getValue(Base::Type t) const; - /** Returns the link type checked + /** Returns the link type checked */ - template - inline _type getValue() const { + template + inline _type getValue() const + { return _pcLinkSub ? dynamic_cast<_type>(_pcLinkSub) : 0; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } + { + return "Gui::PropertyEditor::PropertyLinkItem"; + } /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const override; + Property* CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - unsigned int getMemSize () const override { - return sizeof(App::DocumentObject *); + unsigned int getMemSize() const override + { + return sizeof(App::DocumentObject*); } - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; void setSyncSubObject(bool enable); + protected: - App::DocumentObject* _pcLinkSub{nullptr}; + App::DocumentObject* _pcLinkSub {nullptr}; std::vector _cSubList; std::vector _ShadowSubList; std::vector _mapped; - bool _restoreLabel{false}; + bool _restoreLabel {false}; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkSubChild : public PropertyLinkSub +class AppExport PropertyLinkSubChild: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubChild() {_pcScope = LinkScope::Child;} + PropertyLinkSubChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkSubGlobal : public PropertyLinkSub +class AppExport PropertyLinkSubGlobal: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkSubGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkSubHidden : public PropertyLinkSub +class AppExport PropertyLinkSubHidden: public PropertyLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkSubHidden() + { + _pcScope = LinkScope::Hidden; + } }; -class AppExport PropertyLinkSubList : public PropertyLinkBase +class AppExport PropertyLinkSubList: public PropertyLinkBase { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - using SubSet = std::pair >; + using SubSet = std::pair>; /** * A constructor. * A more elaborate description of the constructor. @@ -968,22 +1077,28 @@ class AppExport PropertyLinkSubList : public PropertyLinkBase /** Sets the property. * setValue(0, whatever) clears the property */ - void setValue(DocumentObject*,const char*); - void setValues(const std::vector&,const std::vector&); - void setValues(const std::vector&,const std::vector&, - std::vector &&ShadowSubList={}); - void setValues(std::vector&&, std::vector &&subs, - std::vector &&ShadowSubList={}); + void setValue(DocumentObject*, const char*); + void setValues(const std::vector&, const std::vector&); + void setValues(const std::vector&, + const std::vector&, + std::vector&& ShadowSubList = {}); + void setValues(std::vector&&, + std::vector&& subs, + std::vector&& ShadowSubList = {}); /** * @brief setValue: PropertyLinkSub-compatible overload * @param SubList */ - void setValue(App::DocumentObject *lValue, const std::vector &SubList=std::vector()); + void setValue(App::DocumentObject* lValue, + const std::vector& SubList = std::vector()); - void addValue(App::DocumentObject *obj, const std::vector &SubList={}, bool reset = false); + void addValue(App::DocumentObject* obj, + const std::vector& SubList = {}, + bool reset = false); - const std::vector &getValues() const { + const std::vector& getValues() const + { return _lValueList; } @@ -997,13 +1112,15 @@ class AppExport PropertyLinkSubList : public PropertyLinkBase */ DocumentObject* getValue() const; - const std::vector &getSubValues() const { + const std::vector& getSubValues() const + { return _lSubList; } std::vector getSubValues(bool newStyle) const; - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } @@ -1011,194 +1128,236 @@ class AppExport PropertyLinkSubList : public PropertyLinkBase * @brief Removes all occurrences of \a lValue in the property * together with its sub-elements and returns the number of entries removed. */ - int removeValue(App::DocumentObject *lValue); + int removeValue(App::DocumentObject* lValue); void setSubListValues(const std::vector&); - std::vector getSubListValues(bool newStyle=false) const; + std::vector getSubListValues(bool newStyle = false) const; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - bool upgrade(Base::XMLReader &reader, const char *typeName); + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + bool upgrade(Base::XMLReader& reader, const char* typeName); - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const override; + Property* CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; void setSyncSubObject(bool enable); private: - void verifyObject(App::DocumentObject *, App::DocumentObject *); + void verifyObject(App::DocumentObject*, App::DocumentObject*); private: - //FIXME: Do not make two independent lists because this will lead to some inconsistencies! + // FIXME: Do not make two independent lists because this will lead to some inconsistencies! std::vector _lValueList; - std::vector _lSubList; + std::vector _lSubList; std::vector _ShadowSubList; std::vector _mapped; }; /** The general Link Property with Child scope */ -class AppExport PropertyLinkSubListChild : public PropertyLinkSubList +class AppExport PropertyLinkSubListChild: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListChild() {_pcScope = LinkScope::Child;} + PropertyLinkSubListChild() + { + _pcScope = LinkScope::Child; + } }; /** The general Link Property with Global scope */ -class AppExport PropertyLinkSubListGlobal : public PropertyLinkSubList +class AppExport PropertyLinkSubListGlobal: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListGlobal() {_pcScope = LinkScope::Global;} + PropertyLinkSubListGlobal() + { + _pcScope = LinkScope::Global; + } }; /** The general Link Property that are hidden from dependency checking */ -class AppExport PropertyLinkSubListHidden : public PropertyLinkSubList +class AppExport PropertyLinkSubListHidden: public PropertyLinkSubList { TYPESYSTEM_HEADER(); + public: - PropertyLinkSubListHidden() {_pcScope = LinkScope::Hidden;} + PropertyLinkSubListHidden() + { + _pcScope = LinkScope::Hidden; + } }; class PropertyXLinkSubList; /** Link to an (sub)object in the same or different document */ -class AppExport PropertyXLink : public PropertyLinkGlobal +class AppExport PropertyXLink: public PropertyLinkGlobal { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - explicit PropertyXLink(bool allowPartial=false, PropertyLinkBase *parent=nullptr); + explicit PropertyXLink(bool allowPartial = false, PropertyLinkBase* parent = nullptr); ~PropertyXLink() override; - PropertyLinkBase *parent() const { return parentProp; } + PropertyLinkBase* parent() const + { + return parentProp; + } void afterRestore() override; void onContainerRestored() override; - void setValue(App::DocumentObject *) override; - void setValue(App::DocumentObject *, const char *subname); + void setValue(App::DocumentObject*) override; + void setValue(App::DocumentObject*, const char* subname); - void setValue(std::string &&filePath, std::string &&objectName, std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setValue(std::string&& filePath, + std::string&& objectName, + std::vector&& SubList, + std::vector&& ShadowSubList = {}); - void setValue(App::DocumentObject *,std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setValue(App::DocumentObject*, + std::vector&& SubList, + std::vector&& ShadowSubList = {}); - void setValue(App::DocumentObject *,const std::vector &SubList, - std::vector &&ShadowSubList={}); + void setValue(App::DocumentObject*, + const std::vector& SubList, + std::vector&& ShadowSubList = {}); - void setSubValues(std::vector &&SubList, - std::vector &&ShadowSubList = {}); + void setSubValues(std::vector&& SubList, + std::vector&& ShadowSubList = {}); - const char *getSubName(bool newStyle=true) const; - void setSubName(const char *subname); + const char* getSubName(bool newStyle = true) const; + void setSubName(const char* subname); - bool hasSubName() const {return !_SubList.empty();} + bool hasSubName() const + { + return !_SubList.empty(); + } - App::Document *getDocument() const; - const char *getDocumentPath() const; - const char *getObjectName() const; + App::Document* getDocument() const; + const char* getDocumentPath() const; + const char* getObjectName() const; - int checkRestore(std::string *msg=nullptr) const override; + int checkRestore(std::string* msg = nullptr) const override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; /// Return a copy of the property if any changes caused by importing external object - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const override; + Property* CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; friend class DocInfo; - static bool supportXLink(const App::Property *prop); - static bool hasXLink(const App::Document *doc); - static bool hasXLink(const std::vector &objs, std::vector *unsaved=nullptr); - static std::map > getDocumentOutList(App::Document *doc=nullptr); - static std::map > getDocumentInList(App::Document *doc=nullptr); - static void restoreDocument(const App::Document &doc); + static bool supportXLink(const App::Property* prop); + static bool hasXLink(const App::Document* doc); + static bool hasXLink(const std::vector& objs, + std::vector* unsaved = nullptr); + static std::map> + getDocumentOutList(App::Document* doc = nullptr); + static std::map> + getDocumentInList(App::Document* doc = nullptr); + static void restoreDocument(const App::Document& doc); - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - const std::vector& getSubValues() const { + const std::vector& getSubValues() const + { return _SubList; } - const std::vector &getShadowSubs() const { + const std::vector& getShadowSubs() const + { return _ShadowSubList; } std::vector getSubValues(bool newStyle) const; - std::vector getSubValuesStartsWith(const char*, bool newStyle=false) const; + std::vector getSubValuesStartsWith(const char*, bool newStyle = false) const; void setAllowPartial(bool enable) override; - const char *getFilePath() const { + const char* getFilePath() const + { return filePath.c_str(); } - virtual bool upgrade(Base::XMLReader &reader, const char *typeName); + virtual bool upgrade(Base::XMLReader& reader, const char* typeName); void setSyncSubObject(bool enable); @@ -1206,9 +1365,11 @@ class AppExport PropertyXLink : public PropertyLinkGlobal void unlink(); void detach(); - void restoreLink(App::DocumentObject *); + void restoreLink(App::DocumentObject*); - void copyTo(PropertyXLink &other, App::DocumentObject *linked=nullptr, std::vector *subs=nullptr) const; + void copyTo(PropertyXLink& other, + App::DocumentObject* linked = nullptr, + std::vector* subs = nullptr) const; void aboutToSetValue() override; @@ -1225,47 +1386,55 @@ class AppExport PropertyXLink : public PropertyLinkGlobal std::vector _SubList; std::vector _ShadowSubList; std::vector _mapped; - PropertyLinkBase *parentProp; + PropertyLinkBase* parentProp; mutable std::string tmpShadow; }; /** Link to one or more (sub)object from the same or different document */ -class AppExport PropertyXLinkSub: public PropertyXLink { +class AppExport PropertyXLinkSub: public PropertyXLink +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - explicit PropertyXLinkSub(bool allowPartial=false, PropertyLinkBase *parent=nullptr); + explicit PropertyXLinkSub(bool allowPartial = false, PropertyLinkBase* parent = nullptr); ~PropertyXLinkSub() override; - bool upgrade(Base::XMLReader &reader, const char *typeName) override; + bool upgrade(Base::XMLReader& reader, const char* typeName) override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkItem"; } + { + return "Gui::PropertyEditor::PropertyLinkItem"; + } }; /** The PropertyXLinkSub that is hidden from dependency checking */ -class AppExport PropertyXLinkSubHidden : public PropertyXLinkSub +class AppExport PropertyXLinkSubHidden: public PropertyXLinkSub { TYPESYSTEM_HEADER(); + public: - PropertyXLinkSubHidden() { _pcScope = LinkScope::Hidden; } + PropertyXLinkSubHidden() + { + _pcScope = LinkScope::Hidden; + } }; /** Link to one or more (sub)object(s) of one or more object(s) from the same or different document */ -class AppExport PropertyXLinkSubList: public PropertyLinkBase - , public AtomicPropertyChangeInterface +class AppExport PropertyXLinkSubList: public PropertyLinkBase, + public AtomicPropertyChangeInterface { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - using atomic_change = typename AtomicPropertyChangeInterface::AtomicPropertyChange; + using atomic_change = + typename AtomicPropertyChangeInterface::AtomicPropertyChange; friend atomic_change; PropertyXLinkSubList(); @@ -1279,23 +1448,26 @@ class AppExport PropertyXLinkSubList: public PropertyLinkBase /** Sets the property. * setValue(0, whatever) clears the property */ - void setValue(DocumentObject*,const char*); + void setValue(DocumentObject*, const char*); void setValues(const std::vector&); - void set1Value(int idx, DocumentObject *value, const std::vector &SubList={}); + void set1Value(int idx, DocumentObject* value, const std::vector& SubList = {}); - void setValues(const std::vector&,const std::vector&); - void setValues(const std::vector&,const std::vector&); - void setValues(std::map > &&); - void setValues(const std::map > &); + void setValues(const std::vector&, const std::vector&); + void setValues(const std::vector&, const std::vector&); + void setValues(std::map>&&); + void setValues(const std::map>&); - void addValue(App::DocumentObject *obj, const std::vector &SubList={}, bool reset=false); - void addValue(App::DocumentObject *obj, std::vector &&SubList={}, bool reset=false); + void addValue(App::DocumentObject* obj, + const std::vector& SubList = {}, + bool reset = false); + void + addValue(App::DocumentObject* obj, std::vector&& SubList = {}, bool reset = false); /** * @brief setValue: PropertyLinkSub-compatible overload * @param SubList */ - void setValue(App::DocumentObject *lValue, const std::vector &SubList={}); + void setValue(App::DocumentObject* lValue, const std::vector& SubList = {}); std::vector getValues() const; @@ -1303,81 +1475,89 @@ class AppExport PropertyXLinkSubList: public PropertyLinkBase DocumentObject* getValue() const; - const std::vector &getSubValues(App::DocumentObject *obj) const; + const std::vector& getSubValues(App::DocumentObject* obj) const; - std::vector getSubValues(App::DocumentObject *obj, bool newStyle) const; + std::vector getSubValues(App::DocumentObject* obj, bool newStyle) const; - const std::vector &getShadowSubs(App::DocumentObject *obj) const; + const std::vector& getShadowSubs(App::DocumentObject* obj) const; /** * @brief Removes all occurrences of \a lValue in the property * together with its sub-elements and returns the number of entries removed. */ - int removeValue(App::DocumentObject *lValue); + int removeValue(App::DocumentObject* lValue); void setSubListValues(const std::vector&); - const std::list &getSubListValues() const { + const std::list& getSubListValues() const + { return _Links; } - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* value) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyLinkListItem"; } + { + return "Gui::PropertyEditor::PropertyLinkListItem"; + } - Property *CopyOnImportExternal(const std::map &nameMap) const override; + Property* + CopyOnImportExternal(const std::map& nameMap) const override; - Property *CopyOnLabelChange(App::DocumentObject *obj, - const std::string &ref, const char *newLabel) const override; + Property* CopyOnLabelChange(App::DocumentObject* obj, + const std::string& ref, + const char* newLabel) const override; - Property *CopyOnLinkReplace(const App::DocumentObject *parent, - App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; + Property* CopyOnLinkReplace(const App::DocumentObject* parent, + App::DocumentObject* oldObj, + App::DocumentObject* newObj) const override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - void updateElementReference( - DocumentObject *feature,bool reverse=false, bool notify=false) override; + void updateElementReference(DocumentObject* feature, + bool reverse = false, + bool notify = false) override; bool referenceChanged() const override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - void getLinksTo(std::vector &identifiers, - App::DocumentObject *obj, - const char *subname=nullptr, - bool all=false) const override; + void getLinksTo(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname = nullptr, + bool all = false) const override; - void breakLink(App::DocumentObject *obj, bool clear) override; + void breakLink(App::DocumentObject* obj, bool clear) override; - bool adjustLink(const std::set &inList) override; + bool adjustLink(const std::set& inList) override; - bool upgrade(Base::XMLReader &reader, const char *typeName); + bool upgrade(Base::XMLReader& reader, const char* typeName); - int checkRestore(std::string *msg=nullptr) const override; + int checkRestore(std::string* msg = nullptr) const override; void setAllowPartial(bool enable) override; - void hasSetChildValue(Property &) override; - void aboutToSetChildValue(Property &) override; + void hasSetChildValue(Property&) override; + void aboutToSetChildValue(Property&) override; void setSyncSubObject(bool enable); protected: - void _getLinksToList( - std::vector &identifiers, - App::DocumentObject *obj, - const char *subname, - const std::vector &subs, - const std::vector &shadows) const; + void _getLinksToList(std::vector& identifiers, + App::DocumentObject* obj, + const char* subname, + const std::vector& subs, + const std::vector& shadows) const; protected: std::list _Links; @@ -1390,15 +1570,16 @@ class AppExport PropertyXLinkSubList: public PropertyLinkBase * their getPyObject(). PropertyXLinkList will return a list of object is * there is no sub-object/sub-elements in the property. */ -class AppExport PropertyXLinkList: public PropertyXLinkSubList { +class AppExport PropertyXLinkList: public PropertyXLinkSubList +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: PropertyXLinkList(); ~PropertyXLinkList() override; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; }; @@ -1406,50 +1587,57 @@ class AppExport PropertyXLinkList: public PropertyXLinkSubList { * * @sa See PropertyExpressionEngine for example usage */ -class AppExport PropertyXLinkContainer : public PropertyLinkBase { +class AppExport PropertyXLinkContainer: public PropertyLinkBase +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: PropertyXLinkContainer(); ~PropertyXLinkContainer() override; void afterRestore() override; - int checkRestore(std::string *msg=nullptr) const override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - void breakLink(App::DocumentObject *obj, bool clear) override; - void getLinks(std::vector &objs, - bool all=false, std::vector *subs=nullptr, bool newStyle=true) const override; + int checkRestore(std::string* msg = nullptr) const override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + void breakLink(App::DocumentObject* obj, bool clear) override; + void getLinks(std::vector& objs, + bool all = false, + std::vector* subs = nullptr, + bool newStyle = true) const override; - bool isLinkedToDocument(const App::Document &doc) const; + bool isLinkedToDocument(const App::Document& doc) const; protected: - void aboutToSetChildValue(App::Property &prop) override; - virtual PropertyXLink *createXLink(); - virtual void onBreakLink(App::DocumentObject *obj); - virtual void onAddDep(App::DocumentObject *) {} - virtual void onRemoveDep(App::DocumentObject *) {} - void updateDeps(std::map &&newDeps); + void aboutToSetChildValue(App::Property& prop) override; + virtual PropertyXLink* createXLink(); + virtual void onBreakLink(App::DocumentObject* obj); + virtual void onAddDep(App::DocumentObject*) + {} + virtual void onRemoveDep(App::DocumentObject*) + {} + void updateDeps(std::map&& newDeps); void clearDeps(); - void _onBreakLink(App::DocumentObject *obj); + void _onBreakLink(App::DocumentObject* obj); protected: - std::map _Deps; - std::map > _XLinks; + std::map _Deps; + std::map> _XLinks; std::map _DocMap; bool _LinkRestored; private: - struct RestoreInfo { + struct RestoreInfo + { std::unique_ptr xlink; std::string docName; std::string docLabel; - bool hidden=false; + bool hidden = false; }; - std::unique_ptr > _XLinkRestores; + std::unique_ptr> _XLinkRestores; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYLINKS_H +#endif // APP_PROPERTYLINKS_H diff --git a/src/App/PropertyPythonObject.cpp b/src/App/PropertyPythonObject.cpp index 63ac957b10da..4141c022d6f7 100644 --- a/src/App/PropertyPythonObject.cpp +++ b/src/App/PropertyPythonObject.cpp @@ -39,7 +39,7 @@ using namespace App; -TYPESYSTEM_SOURCE(App::PropertyPythonObject , App::Property) +TYPESYSTEM_SOURCE(App::PropertyPythonObject, App::Property) PropertyPythonObject::PropertyPythonObject() = default; @@ -51,11 +51,11 @@ PropertyPythonObject::~PropertyPythonObject() this->object = Py::Object(); } -void PropertyPythonObject::setValue(Py::Object o) +void PropertyPythonObject::setValue(const Py::Object& py) { Base::PyGILStateLocker lock; aboutToSetValue(); - this->object = o; + this->object = py; hasSetValue(); } @@ -64,12 +64,12 @@ Py::Object PropertyPythonObject::getValue() const return object; } -PyObject *PropertyPythonObject::getPyObject() +PyObject* PropertyPythonObject::getPyObject() { return Py::new_reference_to(this->object); } -void PropertyPythonObject::setPyObject(PyObject * obj) +void PropertyPythonObject::setPyObject(PyObject* obj) { Base::PyGILStateLocker lock; aboutToSetValue(); @@ -82,9 +82,10 @@ std::string PropertyPythonObject::toString() const std::string repr; Base::PyGILStateLocker lock; try { - Py::Module pickle(PyImport_ImportModule("json"),true); - if (pickle.isNull()) + Py::Module pickle(PyImport_ImportModule("json"), true); + if (pickle.isNull()) { throw Py::Exception(); + } Py::Callable method(pickle.getAttr(std::string("dumps"))); Py::Object dump; if (this->object.hasAttr("dumps")) { @@ -95,10 +96,9 @@ std::string PropertyPythonObject::toString() const // support add-ons that use the old method names else if (this->object.hasAttr("__getstate__") #if PY_VERSION_HEX >= 0x030b0000 - && this->object.getAttr("__getstate__").hasAttr("__func__") + && this->object.getAttr("__getstate__").hasAttr("__func__") #endif - ) - { + ) { Py::Tuple args; Py::Callable state(this->object.getAttr("__getstate__")); dump = state.apply(args); @@ -118,8 +118,9 @@ std::string PropertyPythonObject::toString() const } catch (Py::Exception&) { Py::String typestr(this->object.type().str()); - Base::Console().Error("PropertyPythonObject::toString(): failed for %s\n", typestr.as_string().c_str()); - Base::PyException e; // extract the Python error text + Base::Console().Error("PropertyPythonObject::toString(): failed for %s\n", + typestr.as_string().c_str()); + Base::PyException e; // extract the Python error text e.ReportException(); } @@ -130,11 +131,13 @@ void PropertyPythonObject::fromString(const std::string& repr) { Base::PyGILStateLocker lock; try { - if (repr.empty()) + if (repr.empty()) { return; - Py::Module pickle(PyImport_ImportModule("json"),true); - if (pickle.isNull()) + } + Py::Module pickle(PyImport_ImportModule("json"), true); + if (pickle.isNull()) { throw Py::Exception(); + } Py::Callable method(pickle.getAttr(std::string("loads"))); Py::Tuple args(1); args.setItem(0, Py::String(repr)); @@ -149,10 +152,9 @@ void PropertyPythonObject::fromString(const std::string& repr) // support add-ons that use the old method names else if (this->object.hasAttr("__setstate__") #if PY_VERSION_HEX >= 0x030b0000 - && this->object.getAttr("__setstate__").hasAttr("__func__") + && this->object.getAttr("__setstate__").hasAttr("__func__") #endif - ) - { + ) { Py::Tuple args(1); args.setItem(0, res); Py::Callable state(this->object.getAttr("__setstate__")); @@ -168,7 +170,7 @@ void PropertyPythonObject::fromString(const std::string& repr) } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -194,7 +196,7 @@ void PropertyPythonObject::loadPickle(const std::string& str) } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); } } @@ -203,18 +205,24 @@ std::string PropertyPythonObject::encodeValue(const std::string& str) const { std::string tmp; for (char it : str) { - if (it == '<') + if (it == '<') { tmp += "<"; - else if (it == '"') + } + else if (it == '"') { tmp += """; - else if (it == '&') + } + else if (it == '&') { tmp += "&"; - else if (it == '>') + } + else if (it == '>') { tmp += ">"; - else if (it == '\n') + } + else if (it == '\n') { tmp += "\\n"; - else + } + else { tmp += it; + } } return tmp; @@ -230,14 +238,15 @@ std::string PropertyPythonObject::decodeValue(const std::string& str) const tmp += '\n'; } } - else + else { tmp += *it; + } } return tmp; } -void PropertyPythonObject::saveObject(Base::Writer &writer) const +void PropertyPythonObject::saveObject(Base::Writer& writer) const { Base::PyGILStateLocker lock; try { @@ -258,19 +267,19 @@ void PropertyPythonObject::saveObject(Base::Writer &writer) const } } -void PropertyPythonObject::restoreObject(Base::XMLReader &reader) +void PropertyPythonObject::restoreObject(Base::XMLReader& reader) { Base::PyGILStateLocker lock; try { PropertyContainer* parent = this->getContainer(); if (reader.hasAttribute("object")) { - if (strcmp(reader.getAttribute("object"),"yes") == 0) { + if (strcmp(reader.getAttribute("object"), "yes") == 0) { Py::Object obj = Py::asObject(parent->getPyObject()); this->object.setAttr("__object__", obj); } } if (reader.hasAttribute("vobject")) { - if (strcmp(reader.getAttribute("vobject"),"yes") == 0) { + if (strcmp(reader.getAttribute("vobject"), "yes") == 0) { Py::Object obj = Py::asObject(parent->getPyObject()); this->object.setAttr("__vobject__", obj); } @@ -280,65 +289,57 @@ void PropertyPythonObject::restoreObject(Base::XMLReader &reader) e.clear(); } catch (const Base::Exception& e) { - Base::Console().Error("%s\n",e.what()); + Base::Console().Error("%s\n", e.what()); } catch (...) { Base::Console().Error("Critical error in PropertyPythonObject::restoreObject\n"); } } -void PropertyPythonObject::Save (Base::Writer &writer) const +void PropertyPythonObject::Save(Base::Writer& writer) const { - //if (writer.isForceXML()) { - std::string repr = this->toString(); - repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size()); - std::string val = /*encodeValue*/(repr); - writer.Stream() << writer.ind() << "toString(); + repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size()); + std::string val = /*encodeValue*/ (repr); + writer.Stream() << writer.ind() << "object.hasAttr("__module__") && this->object.hasAttr("__class__")) { - Py::String mod(this->object.getAttr("__module__")); - Py::Object cls(this->object.getAttr("__class__")); - if (cls.hasAttr("__name__")) { - Py::String name(cls.getAttr("__name__")); - writer.Stream() << " module=\"" << (std::string)mod << "\"" - << " class=\"" << (std::string)name << "\""; - } - } - else { - writer.Stream() << " json=\"yes\""; + Base::PyGILStateLocker lock; + try { + if (this->object.hasAttr("__module__") && this->object.hasAttr("__class__")) { + Py::String mod(this->object.getAttr("__module__")); + Py::Object cls(this->object.getAttr("__class__")); + if (cls.hasAttr("__name__")) { + Py::String name(cls.getAttr("__name__")); + writer.Stream() << " module=\"" << (std::string)mod << "\"" + << " class=\"" << (std::string)name << "\""; } } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); + else { + writer.Stream() << " json=\"yes\""; } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } - saveObject(writer); - writer.Stream() << "/>" << std::endl; - //} - //else { - // writer.Stream() << writer.ind() << "" << std::endl; - //} + saveObject(writer); + writer.Stream() << "/>" << std::endl; } -void PropertyPythonObject::Restore(Base::XMLReader &reader) +void PropertyPythonObject::Restore(Base::XMLReader& reader) { reader.readElement("Python"); if (reader.hasAttribute("file")) { std::string file(reader.getAttribute("file")); - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } else { - bool load_json=false; - bool load_pickle=false; - bool load_failed=false; + bool load_json = false; + bool load_pickle = false; + bool load_failed = false; std::string buffer = reader.getAttribute("value"); - if (reader.hasAttribute("encoded") && - strcmp(reader.getAttribute("encoded"),"yes") == 0) { + if (reader.hasAttribute("encoded") && strcmp(reader.getAttribute("encoded"), "yes") == 0) { buffer = Base::base64_decode(buffer); } else { @@ -353,14 +354,15 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) start = buffer.begin(); end = buffer.end(); if (reader.hasAttribute("module") && reader.hasAttribute("class")) { - Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")),true); - if (mod.isNull()) + Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")), true); + if (mod.isNull()) { throw Py::Exception(); + } PyObject* cls = mod.getAttr(reader.getAttribute("class")).ptr(); if (!cls) { std::stringstream s; - s << "Module " << reader.getAttribute("module") - << " has no class " << reader.getAttribute("class"); + s << "Module " << reader.getAttribute("module") << " has no class " + << reader.getAttribute("class"); throw Py::AttributeError(s.str()); } if (PyType_Check(cls)) { @@ -374,9 +376,10 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) else if (boost::regex_search(start, end, what, pickle)) { std::string name = std::string(what[1].first, what[1].second); std::string type = std::string(what[2].first, what[2].second); - Py::Module mod(PyImport_ImportModule(name.c_str()),true); - if (mod.isNull()) + Py::Module mod(PyImport_ImportModule(name.c_str()), true); + if (mod.isNull()) { throw Py::Exception(); + } this->object = PyObject_CallObject(mod.getAttr(type).ptr(), nullptr); load_pickle = true; buffer = std::string(what[2].second, end); @@ -386,57 +389,63 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) } } catch (Py::Exception&) { - Base::PyException e; // extract the Python error text + Base::PyException e; // extract the Python error text e.ReportException(); this->object = Py::None(); load_failed = true; } aboutToSetValue(); - if (load_json) + if (load_json) { this->fromString(buffer); - else if (load_pickle) + } + else if (load_pickle) { this->loadPickle(buffer); - else if (!load_failed) - Base::Console().Warning("PropertyPythonObject::Restore: unsupported serialisation: %s\n", buffer.c_str()); + } + else if (!load_failed) { + Base::Console().Warning( + "PropertyPythonObject::Restore: unsupported serialisation: %s\n", + buffer.c_str()); + } restoreObject(reader); hasSetValue(); } } -void PropertyPythonObject::SaveDocFile (Base::Writer &writer) const +void PropertyPythonObject::SaveDocFile(Base::Writer& writer) const { std::string buffer = this->toString(); - for (char it : buffer) + for (char it : buffer) { writer.Stream().put(it); + } } -void PropertyPythonObject::RestoreDocFile(Base::Reader &reader) +void PropertyPythonObject::RestoreDocFile(Base::Reader& reader) { aboutToSetValue(); std::string buffer; - char c; - while (reader.get(c)) { - buffer.push_back(c); + char ch {}; + while (reader.get(ch)) { + buffer.push_back(ch); } this->fromString(buffer); hasSetValue(); } -unsigned int PropertyPythonObject::getMemSize () const +unsigned int PropertyPythonObject::getMemSize() const { return sizeof(Py::Object); } -Property *PropertyPythonObject::Copy() const +Property* PropertyPythonObject::Copy() const { - PropertyPythonObject *p = new PropertyPythonObject(); + PropertyPythonObject* p = new PropertyPythonObject(); Base::PyGILStateLocker lock; p->object = this->object; return p; } -void PropertyPythonObject::Paste(const Property &from) +void PropertyPythonObject::Paste(const Property& from) { if (from.is()) { Base::PyGILStateLocker lock; diff --git a/src/App/PropertyPythonObject.h b/src/App/PropertyPythonObject.h index cf1357a2344e..fb2a7a6dad98 100644 --- a/src/App/PropertyPythonObject.h +++ b/src/App/PropertyPythonObject.h @@ -30,10 +30,11 @@ #include "Property.h" -namespace Base { +namespace Base +{ class Writer; class XMLReader; -} +} // namespace Base namespace App { @@ -42,7 +43,7 @@ namespace App * PropertyPythonObject is used to manage Py::Object instances as properties. * @author Werner Mayer */ -class AppExport PropertyPythonObject : public Property +class AppExport PropertyPythonObject: public Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -50,29 +51,29 @@ class AppExport PropertyPythonObject : public Property PropertyPythonObject(); ~PropertyPythonObject() override; - void setValue(Py::Object); + void setValue(const Py::Object& py); Py::Object getValue() const; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject* obj) override; /** Use Python's pickle module to save the object */ - void Save (Base::Writer &writer) const override; + void Save(Base::Writer& writer) const override; /** Use Python's pickle module to restore the object */ - void Restore(Base::XMLReader &reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void Restore(Base::XMLReader& reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - unsigned int getMemSize () const override; - Property *Copy() const override; - void Paste(const Property &from) override; + unsigned int getMemSize() const override; + Property* Copy() const override; + void Paste(const Property& from) override; std::string toString() const; void fromString(const std::string&); private: - void saveObject(Base::Writer &writer) const; - void restoreObject(Base::XMLReader &reader); + void saveObject(Base::Writer& writer) const; + void restoreObject(Base::XMLReader& reader); std::string encodeValue(const std::string& str) const; std::string decodeValue(const std::string& str) const; void loadPickle(const std::string& str); @@ -80,6 +81,6 @@ class AppExport PropertyPythonObject : public Property }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYPYTHONOBJECT_H +#endif // APP_PROPERTYPYTHONOBJECT_H diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 2618506f2d9a..696afa0ec496 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -48,14 +48,12 @@ using namespace Base; using namespace std; - - //************************************************************************** //************************************************************************** // PropertyInteger //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyInteger , App::Property) +TYPESYSTEM_SOURCE(App::PropertyInteger, App::Property) //************************************************************************** // Construction/Destruction @@ -76,7 +74,7 @@ PropertyInteger::~PropertyInteger() = default; void PropertyInteger::setValue(long lValue) { aboutToSetValue(); - _lValue=lValue; + _lValue = lValue; hasSetValue(); } @@ -85,12 +83,12 @@ long PropertyInteger::getValue() const return _lValue; } -PyObject *PropertyInteger::getPyObject() +PyObject* PropertyInteger::getPyObject() { return Py_BuildValue("l", _lValue); } -void PropertyInteger::setPyObject(PyObject *value) +void PropertyInteger::setPyObject(PyObject* value) { if (PyLong_Check(value)) { aboutToSetValue(); @@ -104,12 +102,12 @@ void PropertyInteger::setPyObject(PyObject *value) } } -void PropertyInteger::Save (Base::Writer &writer) const +void PropertyInteger::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyInteger::Restore(Base::XMLReader &reader) +void PropertyInteger::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Integer"); @@ -117,36 +115,42 @@ void PropertyInteger::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsInteger("value")); } -Property *PropertyInteger::Copy() const +Property* PropertyInteger::Copy() const { - PropertyInteger *p= new PropertyInteger(); + PropertyInteger* p = new PropertyInteger(); p->_lValue = _lValue; return p; } -void PropertyInteger::Paste(const Property &from) +void PropertyInteger::Paste(const Property& from) { aboutToSetValue(); _lValue = dynamic_cast(from)._lValue; hasSetValue(); } -void PropertyInteger::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyInteger::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(long)) + if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::math::round(boost::any_cast(value).getValue())); - else + } + else { throw bad_cast(); + } } @@ -155,7 +159,7 @@ void PropertyInteger::setPathValue(const ObjectIdentifier &path, const boost::an // PropertyPath //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPath , App::Property) +TYPESYSTEM_SOURCE(App::PropertyPath, App::Property) //************************************************************************** // Construction/Destruction @@ -172,32 +176,30 @@ PropertyPath::~PropertyPath() = default; //************************************************************************** // Setter/getter for the property -void PropertyPath::setValue(const boost::filesystem::path &Path) +void PropertyPath::setValue(const boost::filesystem::path& Path) { aboutToSetValue(); _cValue = Path; hasSetValue(); } -void PropertyPath::setValue(const char * Path) +void PropertyPath::setValue(const char* Path) { aboutToSetValue(); #if (BOOST_FILESYSTEM_VERSION == 2) - _cValue = boost::filesystem::path(Path,boost::filesystem::no_check ); - //_cValue = boost::filesystem::path(Path,boost::filesystem::native ); - //_cValue = boost::filesystem::path(Path,boost::filesystem::windows_name ); + _cValue = boost::filesystem::path(Path, boost::filesystem::no_check); #else _cValue = boost::filesystem::path(Path); #endif hasSetValue(); } -const boost::filesystem::path &PropertyPath::getValue() const +const boost::filesystem::path& PropertyPath::getValue() const { return _cValue; } -PyObject *PropertyPath::getPyObject() +PyObject* PropertyPath::getPyObject() { #if (BOOST_FILESYSTEM_VERSION == 2) std::string str = _cValue.native_file_string(); @@ -206,12 +208,14 @@ PyObject *PropertyPath::getPyObject() #endif // Returns a new reference, don't increment it! - PyObject *p = PyUnicode_DecodeUTF8(str.c_str(),str.size(),nullptr); - if (!p) throw Base::UnicodeError("UTF8 conversion failure at PropertyPath::getPyObject()"); + PyObject* p = PyUnicode_DecodeUTF8(str.c_str(), str.size(), nullptr); + if (!p) { + throw Base::UnicodeError("UTF8 conversion failure at PropertyPath::getPyObject()"); + } return p; } -void PropertyPath::setPyObject(PyObject *value) +void PropertyPath::setPyObject(PyObject* value) { std::string path; if (PyUnicode_Check(value)) { @@ -228,13 +232,13 @@ void PropertyPath::setPyObject(PyObject *value) } -void PropertyPath::Save (Base::Writer &writer) const +void PropertyPath::Save(Base::Writer& writer) const { std::string val = encodeAttribute(_cValue.string()); - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyPath::Restore(Base::XMLReader &reader) +void PropertyPath::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Path"); @@ -242,21 +246,21 @@ void PropertyPath::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } -Property *PropertyPath::Copy() const +Property* PropertyPath::Copy() const { - PropertyPath *p= new PropertyPath(); + PropertyPath* p = new PropertyPath(); p->_cValue = _cValue; return p; } -void PropertyPath::Paste(const Property &from) +void PropertyPath::Paste(const Property& from) { aboutToSetValue(); _cValue = dynamic_cast(from)._cValue; hasSetValue(); } -unsigned int PropertyPath::getMemSize () const +unsigned int PropertyPath::getMemSize() const { return static_cast(_cValue.string().size()); } @@ -277,32 +281,34 @@ PropertyEnumeration::PropertyEnumeration() _editorTypeName = "Gui::PropertyEditor::PropertyEnumItem"; } -PropertyEnumeration::PropertyEnumeration(const App::Enumeration &e) +PropertyEnumeration::PropertyEnumeration(const App::Enumeration& e) { _enum = e; } PropertyEnumeration::~PropertyEnumeration() = default; -void PropertyEnumeration::setEnums(const char **plEnums) +void PropertyEnumeration::setEnums(const char** plEnums) { // For backward compatibility, if the property container is not attached to // any document (i.e. its full name starts with '?'), do not notify, or // else existing code may crash. bool notify = !boost::starts_with(getFullName(), "?"); - if (notify) + if (notify) { aboutToSetValue(); + } _enum.setEnums(plEnums); - if (notify) + if (notify) { hasSetValue(); + } } -void PropertyEnumeration::setEnums(const std::vector &Enums) +void PropertyEnumeration::setEnums(const std::vector& Enums) { setEnumVector(Enums); } -void PropertyEnumeration::setValue(const char *value) +void PropertyEnumeration::setValue(const char* value) { aboutToSetValue(); _enum.setValue(value); @@ -316,7 +322,7 @@ void PropertyEnumeration::setValue(long value) hasSetValue(); } -void PropertyEnumeration::setValue(const Enumeration &source) +void PropertyEnumeration::setValue(const Enumeration& source) { aboutToSetValue(); _enum = source; @@ -328,24 +334,25 @@ long PropertyEnumeration::getValue() const return _enum.getInt(); } -bool PropertyEnumeration::isValue(const char *value) const +bool PropertyEnumeration::isValue(const char* value) const { return _enum.isValue(value); } -bool PropertyEnumeration::isPartOf(const char *value) const +bool PropertyEnumeration::isPartOf(const char* value) const { return _enum.contains(value); } -const char * PropertyEnumeration::getValueAsString() const +const char* PropertyEnumeration::getValueAsString() const { - if (!_enum.isValid()) + if (!_enum.isValid()) { throw Base::RuntimeError("Cannot get value from invalid enumeration"); + } return _enum.getCStr(); } -const Enumeration & PropertyEnumeration::getEnum() const +const Enumeration& PropertyEnumeration::getEnum() const { return _enum; } @@ -355,17 +362,19 @@ std::vector PropertyEnumeration::getEnumVector() const return _enum.getEnumVector(); } -void PropertyEnumeration::setEnumVector(const std::vector &values) +void PropertyEnumeration::setEnumVector(const std::vector& values) { // For backward compatibility, if the property container is not attached to // any document (i.e. its full name starts with '?'), do not notify, or // else existing code may crash. bool notify = !boost::starts_with(getFullName(), "?"); - if (notify) + if (notify) { aboutToSetValue(); + } _enum.setEnums(values); - if (notify) + if (notify) { hasSetValue(); + } } bool PropertyEnumeration::hasEnums() const @@ -378,26 +387,28 @@ bool PropertyEnumeration::isValid() const return _enum.isValid(); } -void PropertyEnumeration::Save(Base::Writer &writer) const +void PropertyEnumeration::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; if (_enum.isCustom()) { std::vector items = getEnumVector(); - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" + << endl; writer.incInd(); - for(auto & item : items) { + for (auto& item : items) { std::string val = encodeAttribute(item); - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); writer.Stream() << writer.ind() << "" << endl; } } -void PropertyEnumeration::Restore(Base::XMLReader &reader) +void PropertyEnumeration::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Integer"); @@ -411,7 +422,7 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("Enum"); values[i] = reader.getAttribute("value"); } @@ -424,7 +435,9 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) if (val < 0) { // If the enum is empty at this stage do not print a warning if (_enum.hasEnums()) { - Base::Console().DeveloperWarning(std::string("PropertyEnumeration"), "Enumeration index %d is out of range, ignore it\n", val); + Base::Console().DeveloperWarning(std::string("PropertyEnumeration"), + "Enumeration index %d is out of range, ignore it\n", + val); } val = getValue(); } @@ -433,7 +446,7 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) hasSetValue(); } -PyObject * PropertyEnumeration::getPyObject() +PyObject* PropertyEnumeration::getPyObject() { if (!_enum.isValid()) { Py_Return; @@ -442,7 +455,7 @@ PyObject * PropertyEnumeration::getPyObject() return Py_BuildValue("s", getValueAsString()); } -void PropertyEnumeration::setPyObject(PyObject *value) +void PropertyEnumeration::setPyObject(PyObject* value) { if (PyLong_Check(value)) { long val = PyLong_AsLong(value); @@ -461,9 +474,8 @@ void PropertyEnumeration::setPyObject(PyObject *value) hasSetValue(); } else { - FC_THROWM(Base::ValueError, "'" << str - << "' is not part of the enumeration in " - << getFullName()); + FC_THROWM(Base::ValueError, + "'" << str << "' is not part of the enumeration in " << getFullName()); } return; } @@ -475,9 +487,9 @@ void PropertyEnumeration::setPyObject(PyObject *value) int idx = -1; Py::Sequence seq(value); - if(seq.size() == 2) { + if (seq.size() == 2) { Py::Object v(seq[0].ptr()); - if(!v.isString() && v.isSequence()) { + if (!v.isString() && v.isSequence()) { idx = Py::Int(seq[1].ptr()); seq = v; } @@ -485,54 +497,67 @@ void PropertyEnumeration::setPyObject(PyObject *value) values.resize(seq.size()); - for (int i = 0; i < seq.size(); ++i) + for (int i = 0; i < seq.size(); ++i) { values[i] = Py::Object(seq[i].ptr()).as_string(); + } aboutToSetValue(); _enum.setEnums(values); - if (idx>=0) - _enum.setValue(idx,true); + if (idx >= 0) { + _enum.setValue(idx, true); + } hasSetValue(); return; - } catch (Py::Exception &) { + } + catch (Py::Exception&) { Base::PyException e; e.ReportException(); } } - FC_THROWM(Base::TypeError, "PropertyEnumeration " << getFullName() - << " expects type to be int, string, or list(string), or list(list, int)"); + FC_THROWM(Base::TypeError, + "PropertyEnumeration " + << getFullName() + << " expects type to be int, string, or list(string), or list(list, int)"); } -Property * PropertyEnumeration::Copy() const +Property* PropertyEnumeration::Copy() const { return new PropertyEnumeration(_enum); } -void PropertyEnumeration::Paste(const Property &from) +void PropertyEnumeration::Paste(const Property& from) { const PropertyEnumeration& prop = dynamic_cast(from); setValue(prop._enum); } -void PropertyEnumeration::setPathValue(const ObjectIdentifier &, const boost::any &value) +void PropertyEnumeration::setPathValue(const ObjectIdentifier&, const boost::any& value) { - if (value.type() == typeid(int)) + if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(short)) + } + else if (value.type() == typeid(short)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(std::string)) + } + else if (value.type() == typeid(std::string)) { setValue(boost::any_cast(value).c_str()); - else if (value.type() == typeid(char*)) + } + else if (value.type() == typeid(char*)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(const char*)) + } + else if (value.type() == typeid(const char*)) { setValue(boost::any_cast(value)); + } else { Base::PyGILStateLocker lock; Py::Object pyValue = pyObjectFromAny(value); @@ -540,53 +565,59 @@ void PropertyEnumeration::setPathValue(const ObjectIdentifier &, const boost::an } } -bool PropertyEnumeration::setPyPathValue(const ObjectIdentifier &, const Py::Object &value) +bool PropertyEnumeration::setPyPathValue(const ObjectIdentifier&, const Py::Object& value) { setPyObject(value.ptr()); return true; } -const boost::any PropertyEnumeration::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyEnumeration::getPathValue(const ObjectIdentifier& path) const { std::string p = path.getSubPathStr(); if (p == ".Enum" || p == ".All") { Base::PyGILStateLocker lock; Py::Object res; getPyPathValue(path, res); - return pyObjectToAny(res,false); + return pyObjectToAny(res, false); } else if (p == ".String") { auto v = getValueAsString(); - return std::string(v?v:""); - } else + return std::string(v ? v : ""); + } + else { return getValue(); + } } -bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier &path, Py::Object &r) const +bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier& path, Py::Object& r) const { std::string p = path.getSubPathStr(); if (p == ".Enum" || p == ".All") { Base::PyGILStateLocker lock; - Py::Tuple res(_enum.maxValue()+1); + Py::Tuple res(_enum.maxValue() + 1); std::vector enums = _enum.getEnumVector(); PropertyString tmp; - for(int i=0;i< int(enums.size());++i) { + for (int i = 0; i < int(enums.size()); ++i) { tmp.setValue(enums[i]); - res.setItem(i,Py::asObject(tmp.getPyObject())); + res.setItem(i, Py::asObject(tmp.getPyObject())); } - if (p == ".Enum") + if (p == ".Enum") { r = res; + } else { Py::Tuple tuple(2); tuple.setItem(0, res); tuple.setItem(1, Py::Int(getValue())); r = tuple; } - } else if (p == ".String") { + } + else if (p == ".String") { auto v = getValueAsString(); - r = Py::String(v?v:""); - } else + r = Py::String(v ? v : ""); + } + else { r = Py::Int(getValue()); + } return true; } @@ -605,57 +636,64 @@ PropertyIntegerConstraint::PropertyIntegerConstraint() = default; PropertyIntegerConstraint::~PropertyIntegerConstraint() { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } void PropertyIntegerConstraint::setConstraints(const Constraints* sConstrain) { if (_ConstStruct != sConstrain) { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } _ConstStruct = sConstrain; } -const PropertyIntegerConstraint::Constraints* PropertyIntegerConstraint::getConstraints() const +const PropertyIntegerConstraint::Constraints* PropertyIntegerConstraint::getConstraints() const { return _ConstStruct; } long PropertyIntegerConstraint::getMinimum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->LowerBound; + } // return the min of int, not long return std::numeric_limits::min(); } long PropertyIntegerConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } // return the max of int, not long return std::numeric_limits::max(); } long PropertyIntegerConstraint::getStepSize() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->StepSize; + } return 1; } -void PropertyIntegerConstraint::setPyObject(PyObject *value) +void PropertyIntegerConstraint::setPyObject(PyObject* value) { if (PyLong_Check(value)) { long temp = PyLong_AsLong(value); if (_ConstStruct) { - if (temp > _ConstStruct->UpperBound) + if (temp > _ConstStruct->UpperBound) { temp = _ConstStruct->UpperBound; - else if(temp < _ConstStruct->LowerBound) + } + else if (temp < _ConstStruct->LowerBound) { temp = _ConstStruct->LowerBound; + } } aboutToSetValue(); @@ -664,13 +702,15 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) } else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) { long values[4]; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { PyObject* item; - item = PyTuple_GetItem(value,i); - if (PyLong_Check(item)) + item = PyTuple_GetItem(value, i); + if (PyLong_Check(item)) { values[i] = PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Type in tuple must be int"); + } } Constraints* c = new Constraints(); @@ -678,10 +718,12 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) c->LowerBound = values[1]; c->UpperBound = values[2]; c->StepSize = std::max(1, values[3]); - if (values[0] > c->UpperBound) + if (values[0] > c->UpperBound) { values[0] = c->UpperBound; - else if (values[0] < c->LowerBound) + } + else if (values[0] < c->LowerBound) { values[0] = c->LowerBound; + } setConstraints(c); aboutToSetValue(); @@ -700,9 +742,9 @@ void PropertyIntegerConstraint::setPyObject(PyObject *value) // PropertyPercent //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPercent , App::PropertyIntegerConstraint) +TYPESYSTEM_SOURCE(App::PropertyPercent, App::PropertyIntegerConstraint) -const PropertyIntegerConstraint::Constraints percent = {0,100,1}; +const PropertyIntegerConstraint::Constraints percent = {0, 100, 1}; //************************************************************************** // Construction/Destruction @@ -720,7 +762,7 @@ PropertyPercent::~PropertyPercent() = default; // PropertyIntegerList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyIntegerList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyIntegerList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -733,33 +775,37 @@ PropertyIntegerList::~PropertyIntegerList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyIntegerList::getPyObject() +PyObject* PropertyIntegerList::getPyObject() { PyObject* list = PyList_New(getSize()); - for(int i = 0;iob_type->tp_name; throw Base::TypeError(error); } -void PropertyIntegerList::Save (Base::Writer &writer) const +void PropertyIntegerList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; ; + for (int i = 0; i < getSize(); i++) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyIntegerList::Restore(Base::XMLReader &reader) +void PropertyIntegerList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("IntegerList"); @@ -767,43 +813,41 @@ void PropertyIntegerList::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("I"); values[i] = reader.getAttributeAsInteger("v"); } reader.readEndElement("IntegerList"); - //assignment + // assignment setValues(values); } -Property *PropertyIntegerList::Copy() const +Property* PropertyIntegerList::Copy() const { - PropertyIntegerList *p= new PropertyIntegerList(); + PropertyIntegerList* p = new PropertyIntegerList(); p->_lValueList = _lValueList; return p; } -void PropertyIntegerList::Paste(const Property &from) +void PropertyIntegerList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyIntegerList::getMemSize () const +unsigned int PropertyIntegerList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(long)); } - - //************************************************************************** //************************************************************************** // PropertyIntegerSet //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyIntegerSet , App::Property) +TYPESYSTEM_SOURCE(App::PropertyIntegerSet, App::Property) //************************************************************************** // Construction/Destruction @@ -832,15 +876,16 @@ void PropertyIntegerSet::setValues(const std::set& values) hasSetValue(); } -PyObject *PropertyIntegerSet::getPyObject() +PyObject* PropertyIntegerSet::getPyObject() { PyObject* set = PySet_New(nullptr); - for(long it : _lValueSet) - PySet_Add(set,PyLong_FromLong(it)); + for (long it : _lValueSet) { + PySet_Add(set, PyLong_FromLong(it)); + } return set; } -void PropertyIntegerSet::setPyObject(PyObject *value) +void PropertyIntegerSet::setPyObject(PyObject* value) { if (PySequence_Check(value)) { @@ -848,7 +893,7 @@ void PropertyIntegerSet::setPyObject(PyObject *value) Py_ssize_t nSize = sequence.size(); std::set values; - for (Py_ssize_t i=0; i" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(long it : _lValueSet) - writer.Stream() << writer.ind() << "" << endl; ; + for (long it : _lValueSet) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyIntegerSet::Restore(Base::XMLReader &reader) +void PropertyIntegerSet::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("IntegerSet"); @@ -888,44 +934,43 @@ void PropertyIntegerSet::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::set values; - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("I"); values.insert(reader.getAttributeAsInteger("v")); } reader.readEndElement("IntegerSet"); - //assignment + // assignment setValues(values); } -Property *PropertyIntegerSet::Copy() const +Property* PropertyIntegerSet::Copy() const { - PropertyIntegerSet *p= new PropertyIntegerSet(); + PropertyIntegerSet* p = new PropertyIntegerSet(); p->_lValueSet = _lValueSet; return p; } -void PropertyIntegerSet::Paste(const Property &from) +void PropertyIntegerSet::Paste(const Property& from) { aboutToSetValue(); _lValueSet = dynamic_cast(from)._lValueSet; hasSetValue(); } -unsigned int PropertyIntegerSet::getMemSize () const +unsigned int PropertyIntegerSet::getMemSize() const { return static_cast(_lValueSet.size() * sizeof(long)); } - //************************************************************************** //************************************************************************** // PropertyFloat //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFloat , App::Property) +TYPESYSTEM_SOURCE(App::PropertyFloat, App::Property) //************************************************************************** // Construction/Destruction @@ -944,7 +989,7 @@ PropertyFloat::~PropertyFloat() = default; void PropertyFloat::setValue(double lValue) { aboutToSetValue(); - _dValue=lValue; + _dValue = lValue; hasSetValue(); } @@ -953,19 +998,19 @@ double PropertyFloat::getValue() const return _dValue; } -PyObject *PropertyFloat::getPyObject() +PyObject* PropertyFloat::getPyObject() { return Py_BuildValue("d", _dValue); } -void PropertyFloat::setPyObject(PyObject *value) +void PropertyFloat::setPyObject(PyObject* value) { if (PyFloat_Check(value)) { aboutToSetValue(); _dValue = PyFloat_AsDouble(value); hasSetValue(); } - else if(PyLong_Check(value)) { + else if (PyLong_Check(value)) { aboutToSetValue(); _dValue = PyLong_AsLong(value); hasSetValue(); @@ -977,12 +1022,12 @@ void PropertyFloat::setPyObject(PyObject *value) } } -void PropertyFloat::Save (Base::Writer &writer) const +void PropertyFloat::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyFloat::Restore(Base::XMLReader &reader) +void PropertyFloat::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Float"); @@ -990,41 +1035,48 @@ void PropertyFloat::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsFloat("value")); } -Property *PropertyFloat::Copy() const +Property* PropertyFloat::Copy() const { - PropertyFloat *p= new PropertyFloat(); + PropertyFloat* p = new PropertyFloat(); p->_dValue = _dValue; return p; } -void PropertyFloat::Paste(const Property &from) +void PropertyFloat::Paste(const Property& from) { aboutToSetValue(); _dValue = dynamic_cast(from)._dValue; hasSetValue(); } -void PropertyFloat::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyFloat::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(long)) + if (value.type() == typeid(long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(unsigned long)) + } + else if (value.type() == typeid(unsigned long)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue((boost::any_cast(value)).getValue()); - else + } + else { throw bad_cast(); + } } -const boost::any PropertyFloat::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyFloat::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); return _dValue; @@ -1045,54 +1097,61 @@ PropertyFloatConstraint::PropertyFloatConstraint() = default; PropertyFloatConstraint::~PropertyFloatConstraint() { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } void PropertyFloatConstraint::setConstraints(const Constraints* sConstrain) { if (_ConstStruct != sConstrain) { - if (_ConstStruct && _ConstStruct->isDeletable()) + if (_ConstStruct && _ConstStruct->isDeletable()) { delete _ConstStruct; + } } _ConstStruct = sConstrain; } -const PropertyFloatConstraint::Constraints* PropertyFloatConstraint::getConstraints() const +const PropertyFloatConstraint::Constraints* PropertyFloatConstraint::getConstraints() const { return _ConstStruct; } double PropertyFloatConstraint::getMinimum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->LowerBound; + } return std::numeric_limits::min(); } double PropertyFloatConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } return std::numeric_limits::max(); } double PropertyFloatConstraint::getStepSize() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->StepSize; + } return 1.0; } -void PropertyFloatConstraint::setPyObject(PyObject *value) +void PropertyFloatConstraint::setPyObject(PyObject* value) { if (PyFloat_Check(value)) { double temp = PyFloat_AsDouble(value); if (_ConstStruct) { - if (temp > _ConstStruct->UpperBound) + if (temp > _ConstStruct->UpperBound) { temp = _ConstStruct->UpperBound; - else if (temp < _ConstStruct->LowerBound) + } + else if (temp < _ConstStruct->LowerBound) { temp = _ConstStruct->LowerBound; + } } aboutToSetValue(); @@ -1102,10 +1161,12 @@ void PropertyFloatConstraint::setPyObject(PyObject *value) else if (PyLong_Check(value)) { double temp = (double)PyLong_AsLong(value); if (_ConstStruct) { - if (temp > _ConstStruct->UpperBound) + if (temp > _ConstStruct->UpperBound) { temp = _ConstStruct->UpperBound; - else if (temp < _ConstStruct->LowerBound) + } + else if (temp < _ConstStruct->LowerBound) { temp = _ConstStruct->LowerBound; + } } aboutToSetValue(); @@ -1114,31 +1175,37 @@ void PropertyFloatConstraint::setPyObject(PyObject *value) } else if (PyTuple_Check(value) && PyTuple_Size(value) == 4) { double values[4]; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { PyObject* item; - item = PyTuple_GetItem(value,i); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, i); + if (PyFloat_Check(item)) { values[i] = PyFloat_AsDouble(item); - else if (PyLong_Check(item)) + } + else if (PyLong_Check(item)) { values[i] = PyLong_AsLong(item); - else + } + else { throw Base::TypeError("Type in tuple must be float or int"); + } } double stepSize = values[3]; // need a value > 0 - if (stepSize < DBL_EPSILON) + if (stepSize < DBL_EPSILON) { throw Base::ValueError("Step size must be greater than zero"); + } Constraints* c = new Constraints(); c->setDeletable(true); c->LowerBound = values[1]; c->UpperBound = values[2]; c->StepSize = stepSize; - if (values[0] > c->UpperBound) + if (values[0] > c->UpperBound) { values[0] = c->UpperBound; - else if (values[0] < c->LowerBound) + } + else if (values[0] < c->LowerBound) { values[0] = c->LowerBound; + } setConstraints(c); aboutToSetValue(); @@ -1161,7 +1228,7 @@ TYPESYSTEM_SOURCE(App::PropertyPrecision, App::PropertyFloatConstraint) //************************************************************************** // Construction/Destruction // -const PropertyFloatConstraint::Constraints PrecisionStandard = {0.0,DBL_MAX,0.001}; +const PropertyFloatConstraint::Constraints PrecisionStandard = {0.0, DBL_MAX, 0.001}; PropertyPrecision::PropertyPrecision() { @@ -1175,7 +1242,7 @@ PropertyPrecision::~PropertyPrecision() = default; // PropertyFloatList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFloatList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyFloatList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -1188,54 +1255,60 @@ PropertyFloatList::~PropertyFloatList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyFloatList::getPyObject() +PyObject* PropertyFloatList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;i(PyLong_AsLong(item)); - } else { + } + else { std::string error = std::string("type in list must be float, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } } -void PropertyFloatList::Save (Base::Writer &writer) const +void PropertyFloatList::Save(Base::Writer& writer) const { if (writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; ; + for (int i = 0; i < getSize(); i++) { + writer.Stream() << writer.ind() << "" << endl; + }; writer.decInd(); - writer.Stream() << writer.ind() <<"" << endl ; + writer.Stream() << writer.ind() << "" << endl; } else { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } } -void PropertyFloatList::Restore(Base::XMLReader &reader) +void PropertyFloatList::Restore(Base::XMLReader& reader) { reader.readElement("FloatList"); - string file (reader.getAttribute("file") ); + string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void PropertyFloatList::SaveDocFile (Base::Writer &writer) const +void PropertyFloatList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); @@ -1253,19 +1326,19 @@ void PropertyFloatList::SaveDocFile (Base::Writer &writer) const } } -void PropertyFloatList::RestoreDocFile(Base::Reader &reader) +void PropertyFloatList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); if (!isSinglePrecision()) { - for (double & it : values) { + for (double& it : values) { str >> it; } } else { - for (double & it : values) { + for (double& it : values) { float val; str >> val; it = val; @@ -1274,19 +1347,19 @@ void PropertyFloatList::RestoreDocFile(Base::Reader &reader) setValues(values); } -Property *PropertyFloatList::Copy() const +Property* PropertyFloatList::Copy() const { - PropertyFloatList *p= new PropertyFloatList(); + PropertyFloatList* p = new PropertyFloatList(); p->_lValueList = _lValueList; return p; } -void PropertyFloatList::Paste(const Property &from) +void PropertyFloatList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyFloatList::getMemSize () const +unsigned int PropertyFloatList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(double)); } @@ -1296,7 +1369,7 @@ unsigned int PropertyFloatList::getMemSize () const // PropertyString //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyString , App::Property) +TYPESYSTEM_SOURCE(App::PropertyString, App::Property) PropertyString::PropertyString() = default; @@ -1304,43 +1377,46 @@ PropertyString::~PropertyString() = default; void PropertyString::setValue(const char* newLabel) { - if(!newLabel) + if (!newLabel) { return; + } - if(_cValue == newLabel) + if (_cValue == newLabel) { return; + } std::string _newLabel; - std::vector > > propChanges; + std::vector>> propChanges; std::string label; auto obj = dynamic_cast(getContainer()); bool commit = false; - if(obj && obj->isAttachedToDocument() && this==&obj->Label && - (!obj->getDocument()->testStatus(App::Document::Restoring)|| - obj->getDocument()->testStatus(App::Document::Importing)) && - !obj->getDocument()->isPerformingTransaction()) - { + if (obj && obj->isAttachedToDocument() && this == &obj->Label + && (!obj->getDocument()->testStatus(App::Document::Restoring) + || obj->getDocument()->testStatus(App::Document::Importing)) + && !obj->getDocument()->isPerformingTransaction()) { // allow object to control label change static ParameterGrp::handle _hPGrp; - if(!_hPGrp) { + if (!_hPGrp) { _hPGrp = GetApplication().GetUserParameter().GetGroup("BaseApp"); _hPGrp = _hPGrp->GetGroup("Preferences")->GetGroup("Document"); } App::Document* doc = obj->getDocument(); - if(doc && !_hPGrp->GetBool("DuplicateLabels") && !obj->allowDuplicateLabel()) { + if (doc && !_hPGrp->GetBool("DuplicateLabels") && !obj->allowDuplicateLabel()) { std::vector objectLabels; std::vector::const_iterator it; std::vector objs = doc->getObjects(); bool match = false; - for (it = objs.begin();it != objs.end();++it) { - if (*it == obj) - continue; // don't compare object with itself + for (it = objs.begin(); it != objs.end(); ++it) { + if (*it == obj) { + continue; // don't compare object with itself + } std::string objLabel = (*it)->Label.getValue(); - if (!match && objLabel == newLabel) + if (!match && objLabel == newLabel) { match = true; + } objectLabels.push_back(objLabel); } @@ -1348,48 +1424,52 @@ void PropertyString::setValue(const char* newLabel) if (match && *newLabel) { label = newLabel; // remove number from end to avoid lengthy names - size_t lastpos = label.length()-1; + size_t lastpos = label.length() - 1; while (label[lastpos] >= 48 && label[lastpos] <= 57) { // if 'lastpos' becomes 0 then all characters are digits. In this case we use // the complete label again if (lastpos == 0) { - lastpos = label.length()-1; + lastpos = label.length() - 1; break; } lastpos--; } bool changed = false; - label = label.substr(0,lastpos+1); - if(label != obj->getNameInDocument() - && boost::starts_with(obj->getNameInDocument(),label)) - { + label = label.substr(0, lastpos + 1); + if (label != obj->getNameInDocument() + && boost::starts_with(obj->getNameInDocument(), label)) { // In case the label has the same base name as object's // internal name, use it as the label instead. - const char *objName = obj->getNameInDocument(); - const char *c = &objName[lastpos+1]; - for(;*c;++c) { - if(*c<48 || *c>57) + const char* objName = obj->getNameInDocument(); + const char* c = &objName[lastpos + 1]; + for (; *c; ++c) { + if (*c < 48 || *c > 57) { break; + } } - if(*c == 0 && std::find(objectLabels.begin(), objectLabels.end(), - obj->getNameInDocument())==objectLabels.end()) - { + if (*c == 0 + && std::find(objectLabels.begin(), + objectLabels.end(), + obj->getNameInDocument()) + == objectLabels.end()) { label = obj->getNameInDocument(); changed = true; } } - if(!changed) + if (!changed) { label = Base::Tools::getUniqueName(label, objectLabels, 3); + } } } - if(label.empty()) + if (label.empty()) { label = newLabel; + } obj->onBeforeChangeLabel(label); newLabel = label.c_str(); - if(!obj->getDocument()->testStatus(App::Document::Restoring)) { + if (!obj->getDocument()->testStatus(App::Document::Restoring)) { // Only update label reference if we are not restoring. When // importing (which also counts as restoring), it is possible the // new object changes its label. However, we cannot update label @@ -1397,10 +1477,10 @@ void PropertyString::setValue(const char* newLabel) // dependency order. It can only be done in afterRestore(). // // See PropertyLinkBase::restoreLabelReference() for more details. - propChanges = PropertyLinkBase::updateLabelReferences(obj,newLabel); + propChanges = PropertyLinkBase::updateLabelReferences(obj, newLabel); } - if(!propChanges.empty() && !GetApplication().getActiveTransaction()) { + if (!propChanges.empty() && !GetApplication().getActiveTransaction()) { commit = true; std::ostringstream str; str << "Change " << obj->getNameInDocument() << ".Label"; @@ -1412,14 +1492,16 @@ void PropertyString::setValue(const char* newLabel) _cValue = newLabel; hasSetValue(); - for(auto &change : propChanges) + for (auto& change : propChanges) { change.first->Paste(*change.second.get()); + } - if(commit) + if (commit) { GetApplication().closeActiveTransaction(); + } } -void PropertyString::setValue(const std::string &sString) +void PropertyString::setValue(const std::string& sString) { setValue(sString.c_str()); } @@ -1429,14 +1511,16 @@ const char* PropertyString::getValue() const return _cValue.c_str(); } -PyObject *PropertyString::getPyObject() +PyObject* PropertyString::getPyObject() { - PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),nullptr); - if (!p) throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()"); + PyObject* p = PyUnicode_DecodeUTF8(_cValue.c_str(), _cValue.size(), nullptr); + if (!p) { + throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()"); + } return p; } -void PropertyString::setPyObject(PyObject *value) +void PropertyString::setPyObject(PyObject* value) { std::string string; if (PyUnicode_Check(value)) { @@ -1452,90 +1536,103 @@ void PropertyString::setPyObject(PyObject *value) setValue(string); } -void PropertyString::Save (Base::Writer &writer) const +void PropertyString::Save(Base::Writer& writer) const { std::string val; auto obj = dynamic_cast(getContainer()); writer.Stream() << writer.ind() << "isAttachedToDocument() && - obj->isExporting() && &obj->Label==this) - { - if(obj->allowDuplicateLabel()) - writer.Stream() <<"restore=\"1\" "; - else if(_cValue==obj->getNameInDocument()) { - writer.Stream() <<"restore=\"0\" "; + if (obj && obj->isAttachedToDocument() && obj->isExporting() && &obj->Label == this) { + if (obj->allowDuplicateLabel()) { + writer.Stream() << "restore=\"1\" "; + } + else if (_cValue == obj->getNameInDocument()) { + writer.Stream() << "restore=\"0\" "; val = encodeAttribute(obj->getExportName()); exported = true; } } - if(!exported) + if (!exported) { val = encodeAttribute(_cValue); - writer.Stream() <<"value=\"" << val <<"\"/>" << std::endl; + } + writer.Stream() << "value=\"" << val << "\"/>" << std::endl; } -void PropertyString::Restore(Base::XMLReader &reader) +void PropertyString::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("String"); // get the value of my Attribute auto obj = dynamic_cast(getContainer()); - if(obj && &obj->Label==this) { - if(reader.hasAttribute("restore")) { + if (obj && &obj->Label == this) { + if (reader.hasAttribute("restore")) { int restore = reader.getAttributeAsInteger("restore"); - if(restore == 1) { + if (restore == 1) { aboutToSetValue(); _cValue = reader.getAttribute("value"); hasSetValue(); - }else + } + else { setValue(reader.getName(reader.getAttribute("value"))); - } else + } + } + else { setValue(reader.getAttribute("value")); - }else + } + } + else { setValue(reader.getAttribute("value")); + } } -Property *PropertyString::Copy() const +Property* PropertyString::Copy() const { - PropertyString *p= new PropertyString(); + PropertyString* p = new PropertyString(); p->_cValue = _cValue; return p; } -void PropertyString::Paste(const Property &from) +void PropertyString::Paste(const Property& from) { setValue(dynamic_cast(from)._cValue); } -unsigned int PropertyString::getMemSize () const +unsigned int PropertyString::getMemSize() const { return static_cast(_cValue.size()); } -void PropertyString::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyString::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(bool)) - setValue(boost::any_cast(value)?"True":"False"); - else if (value.type() == typeid(int)) + if (value.type() == typeid(bool)) { + setValue(boost::any_cast(value) ? "True" : "False"); + } + else if (value.type() == typeid(int)) { setValue(std::to_string(boost::any_cast(value))); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(std::to_string(boost::any_cast(value))); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(std::to_string(App::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(std::to_string(App::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::any_cast(value).getUserString().toUtf8().constData()); - else if (value.type() == typeid(std::string)) - setValue(boost::any_cast(value)); + } + else if (value.type() == typeid(std::string)) { + setValue(boost::any_cast(value)); + } else { Base::PyGILStateLocker lock; setValue(pyObjectFromAny(value).as_string()); } } -const boost::any PropertyString::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyString::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); return _cValue; @@ -1546,13 +1643,13 @@ const boost::any PropertyString::getPathValue(const ObjectIdentifier &path) cons // PropertyUUID //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyUUID , App::Property) +TYPESYSTEM_SOURCE(App::PropertyUUID, App::Property) PropertyUUID::PropertyUUID() = default; PropertyUUID::~PropertyUUID() = default; -void PropertyUUID::setValue(const Base::Uuid &id) +void PropertyUUID::setValue(const Base::Uuid& id) { aboutToSetValue(); _uuid = id; @@ -1568,7 +1665,7 @@ void PropertyUUID::setValue(const char* sString) } } -void PropertyUUID::setValue(const std::string &sString) +void PropertyUUID::setValue(const std::string& sString) { aboutToSetValue(); _uuid.setValue(sString); @@ -1585,13 +1682,13 @@ const Base::Uuid& PropertyUUID::getValue() const return _uuid; } -PyObject *PropertyUUID::getPyObject() +PyObject* PropertyUUID::getPyObject() { - PyObject *p = PyUnicode_FromString(_uuid.getValue().c_str()); + PyObject* p = PyUnicode_FromString(_uuid.getValue().c_str()); return p; } -void PropertyUUID::setPyObject(PyObject *value) +void PropertyUUID::setPyObject(PyObject* value) { std::string string; if (PyUnicode_Check(value)) { @@ -1614,12 +1711,12 @@ void PropertyUUID::setPyObject(PyObject *value) } } -void PropertyUUID::Save (Base::Writer &writer) const +void PropertyUUID::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyUUID::Restore(Base::XMLReader &reader) +void PropertyUUID::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Uuid"); @@ -1627,21 +1724,21 @@ void PropertyUUID::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } -Property *PropertyUUID::Copy() const +Property* PropertyUUID::Copy() const { - PropertyUUID *p= new PropertyUUID(); + PropertyUUID* p = new PropertyUUID(); p->_uuid = _uuid; return p; } -void PropertyUUID::Paste(const Property &from) +void PropertyUUID::Paste(const Property& from) { aboutToSetValue(); _uuid = dynamic_cast(from)._uuid; hasSetValue(); } -unsigned int PropertyUUID::getMemSize () const +unsigned int PropertyUUID::getMemSize() const { return static_cast(sizeof(_uuid)); } @@ -1650,7 +1747,7 @@ unsigned int PropertyUUID::getMemSize () const // PropertyFont //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyFont , App::PropertyString) +TYPESYSTEM_SOURCE(App::PropertyFont, App::PropertyString) PropertyFont::PropertyFont() = default; @@ -1660,7 +1757,7 @@ PropertyFont::~PropertyFont() = default; // PropertyStringList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyStringList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyStringList, App::PropertyLists) PropertyStringList::PropertyStringList() = default; @@ -1673,20 +1770,23 @@ void PropertyStringList::setValues(const std::list& lValue) { std::vector vals; vals.reserve(lValue.size()); - for(const auto &v : lValue) + for (const auto& v : lValue) { vals.push_back(v); + } setValues(vals); } -PyObject *PropertyStringList::getPyObject() +PyObject* PropertyStringList::getPyObject() { PyObject* list = PyList_New(getSize()); - for (int i = 0;iob_type->tp_name; throw Base::TypeError(error); @@ -1709,27 +1811,28 @@ std::string PropertyStringList::getPyValue(PyObject *item) const return ret; } -unsigned int PropertyStringList::getMemSize () const +unsigned int PropertyStringList::getMemSize() const { - size_t size=0; - for(int i = 0;i(size); } -void PropertyStringList::Save (Base::Writer &writer) const +void PropertyStringList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for(int i = 0;i" << endl; + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyStringList::Restore(Base::XMLReader &reader) +void PropertyStringList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("StringList"); @@ -1737,7 +1840,7 @@ void PropertyStringList::Restore(Base::XMLReader &reader) int count = reader.getAttributeAsInteger("count"); std::vector values(count); - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { reader.readElement("String"); values[i] = reader.getAttribute("value"); } @@ -1748,14 +1851,14 @@ void PropertyStringList::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyStringList::Copy() const +Property* PropertyStringList::Copy() const { - PropertyStringList *p= new PropertyStringList(); + PropertyStringList* p = new PropertyStringList(); p->_lValueList = _lValueList; return p; } -void PropertyStringList::Paste(const Property &from) +void PropertyStringList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } @@ -1765,7 +1868,7 @@ void PropertyStringList::Paste(const Property &from) // PropertyMap //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyMap , App::Property) +TYPESYSTEM_SOURCE(App::PropertyMap, App::Property) PropertyMap::PropertyMap() = default; @@ -1780,62 +1883,59 @@ int PropertyMap::getSize() const return static_cast(_lValueList.size()); } -void PropertyMap::setValue(const std::string& key,const std::string& value) +void PropertyMap::setValue(const std::string& key, const std::string& value) { aboutToSetValue(); _lValueList[key] = value; hasSetValue(); } -void PropertyMap::setValues(const std::map& map) +void PropertyMap::setValues(const std::map& map) { aboutToSetValue(); - _lValueList=map; + _lValueList = map; hasSetValue(); } - - -const std::string& PropertyMap::operator[] (const std::string& key) const +const std::string& PropertyMap::operator[](const std::string& key) const { static std::string empty; - std::map::const_iterator it = _lValueList.find(key); - if(it!=_lValueList.end()) + auto it = _lValueList.find(key); + if (it != _lValueList.end()) { return it->second; - else - return empty; + } + return empty; } - -PyObject *PropertyMap::getPyObject() +PyObject* PropertyMap::getPyObject() { PyObject* dict = PyDict_New(); - for (std::map::const_iterator it = _lValueList.begin();it!= _lValueList.end(); ++it) { + for (auto it = _lValueList.begin(); it != _lValueList.end(); ++it) { PyObject* item = PyUnicode_DecodeUTF8(it->second.c_str(), it->second.size(), nullptr); if (!item) { Py_DECREF(dict); throw Base::UnicodeError("UTF8 conversion failure at PropertyMap::getPyObject()"); } - PyDict_SetItemString(dict,it->first.c_str(),item); + PyDict_SetItemString(dict, it->first.c_str(), item); Py_DECREF(item); } return dict; } -void PropertyMap::setPyObject(PyObject *value) +void PropertyMap::setPyObject(PyObject* value) { if (PyDict_Check(value)) { - std::map values; + std::map values; // get key and item list PyObject* keyList = PyDict_Keys(value); PyObject* itemList = PyDict_Values(value); Py_ssize_t nSize = PyList_Size(keyList); - for (Py_ssize_t i=0; iob_type->tp_name; throw Base::TypeError(error); } @@ -1855,7 +1955,7 @@ void PropertyMap::setPyObject(PyObject *value) values[keyStr] = PyUnicode_AsUTF8(item); } else { - std::string error = std::string("type in list must be string or unicode, not "); + std::string error("type in list must be string or unicode, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } @@ -1864,44 +1964,44 @@ void PropertyMap::setPyObject(PyObject *value) setValues(values); } else { - std::string error = std::string("type must be a dict object"); + std::string error("type must be a dict object"); error += value->ob_type->tp_name; throw Base::TypeError(error); } } -unsigned int PropertyMap::getMemSize () const +unsigned int PropertyMap::getMemSize() const { - size_t size=0; - for (const auto & it : _lValueList) { + size_t size = 0; + for (const auto& it : _lValueList) { size += it.second.size(); size += it.first.size(); } return size; } -void PropertyMap::Save (Base::Writer &writer) const +void PropertyMap::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" << endl; writer.incInd(); - for (const auto & it : _lValueList) { - writer.Stream() << writer.ind() << "" << endl; + for (const auto& it : _lValueList) { + writer.Stream() << writer.ind() << "" << endl; } writer.decInd(); - writer.Stream() << writer.ind() << "" << endl ; + writer.Stream() << writer.ind() << "" << endl; } -void PropertyMap::Restore(Base::XMLReader &reader) +void PropertyMap::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Map"); // get the value of my Attribute int count = reader.getAttributeAsInteger("count"); - std::map values; - for(int i = 0; i < count; i++) { + std::map values; + for (int i = 0; i < count; i++) { reader.readElement("Item"); values[reader.getAttribute("key")] = reader.getAttribute("value"); } @@ -1912,14 +2012,14 @@ void PropertyMap::Restore(Base::XMLReader &reader) setValues(values); } -Property *PropertyMap::Copy() const +Property* PropertyMap::Copy() const { - PropertyMap *p= new PropertyMap(); + PropertyMap* p = new PropertyMap(); p->_lValueList = _lValueList; return p; } -void PropertyMap::Paste(const Property &from) +void PropertyMap::Paste(const Property& from) { aboutToSetValue(); _lValueList = dynamic_cast(from)._lValueList; @@ -1927,14 +2027,12 @@ void PropertyMap::Paste(const Property &from) } - - //************************************************************************** //************************************************************************** // PropertyBool //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyBool , App::Property) +TYPESYSTEM_SOURCE(App::PropertyBool, App::Property) //************************************************************************** // Construction/Destruction @@ -1952,7 +2050,7 @@ PropertyBool::~PropertyBool() = default; void PropertyBool::setValue(bool lValue) { aboutToSetValue(); - _lValue=lValue; + _lValue = lValue; hasSetValue(); } @@ -1961,12 +2059,12 @@ bool PropertyBool::getValue() const return _lValue; } -PyObject *PropertyBool::getPyObject() +PyObject* PropertyBool::getPyObject() { return PyBool_FromLong(_lValue ? 1 : 0); } -void PropertyBool::setPyObject(PyObject *value) +void PropertyBool::setPyObject(PyObject* value) { if (PyBool_Check(value) || PyLong_Check(value)) { setValue(Base::asBoolean(value)); @@ -1978,17 +2076,19 @@ void PropertyBool::setPyObject(PyObject *value) } } -void PropertyBool::Save (Base::Writer &writer) const +void PropertyBool::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" ; - else - writer.Stream() << "false" <<"\"/>" ; + writer.Stream() << writer.ind() << ""; + } + else { + writer.Stream() << "false" << "\"/>"; + } writer.Stream() << std::endl; } -void PropertyBool::Restore(Base::XMLReader &reader) +void PropertyBool::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("Bool"); @@ -1998,41 +2098,48 @@ void PropertyBool::Restore(Base::XMLReader &reader) } -Property *PropertyBool::Copy() const +Property* PropertyBool::Copy() const { - PropertyBool *p= new PropertyBool(); + PropertyBool* p = new PropertyBool(); p->_lValue = _lValue; return p; } -void PropertyBool::Paste(const Property &from) +void PropertyBool::Paste(const Property& from) { aboutToSetValue(); _lValue = dynamic_cast(from)._lValue; hasSetValue(); } -void PropertyBool::setPathValue(const ObjectIdentifier &path, const boost::any &value) +void PropertyBool::setPathValue(const ObjectIdentifier& path, const boost::any& value) { verifyPath(path); - if (value.type() == typeid(bool)) + if (value.type() == typeid(bool)) { setValue(boost::any_cast(value)); - else if (value.type() == typeid(int)) + } + else if (value.type() == typeid(int)) { setValue(boost::any_cast(value) != 0); - else if (value.type() == typeid(long)) + } + else if (value.type() == typeid(long)) { setValue(boost::any_cast(value) != 0); - else if (value.type() == typeid(double)) + } + else if (value.type() == typeid(double)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(float)) + } + else if (value.type() == typeid(float)) { setValue(boost::math::round(boost::any_cast(value))); - else if (value.type() == typeid(Quantity)) + } + else if (value.type() == typeid(Quantity)) { setValue(boost::any_cast(value).getValue() != 0); - else + } + else { throw bad_cast(); + } } -const boost::any PropertyBool::getPathValue(const ObjectIdentifier &path) const +const boost::any PropertyBool::getPathValue(const ObjectIdentifier& path) const { verifyPath(path); @@ -2044,7 +2151,7 @@ const boost::any PropertyBool::getPathValue(const ObjectIdentifier &path) const // PropertyBoolList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyBoolList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyBoolList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -2057,10 +2164,10 @@ PropertyBoolList::~PropertyBoolList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyBoolList::getPyObject() +PyObject* PropertyBoolList::getPyObject() { PyObject* tuple = PyTuple_New(getSize()); - for(int i = 0;i values(str); setValues(values); - }else + } + else { inherited::setPyObject(value); + } } -bool PropertyBoolList::getPyValue(PyObject *item) const { +bool PropertyBoolList::getPyValue(PyObject* item) const +{ if (PyBool_Check(item)) { return Base::asBoolean(item); - } else if (PyLong_Check(item)) { + } + else if (PyLong_Check(item)) { return (PyLong_AsLong(item) ? true : false); - } else { + } + else { std::string error = std::string("type in list must be bool or int, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } } -void PropertyBoolList::Save (Base::Writer &writer) const +void PropertyBoolList::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" ; + writer.Stream() << bitset << "\"/>"; writer.Stream() << std::endl; } -void PropertyBoolList::Restore(Base::XMLReader &reader) +void PropertyBoolList::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("BoolList"); @@ -2115,19 +2227,19 @@ void PropertyBoolList::Restore(Base::XMLReader &reader) setValues(bitset); } -Property *PropertyBoolList::Copy() const +Property* PropertyBoolList::Copy() const { - PropertyBoolList *p= new PropertyBoolList(); + PropertyBoolList* p = new PropertyBoolList(); p->_lValueList = _lValueList; return p; } -void PropertyBoolList::Paste(const Property &from) +void PropertyBoolList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyBoolList::getMemSize () const +unsigned int PropertyBoolList::getMemSize() const { return static_cast(_lValueList.size()); } @@ -2137,7 +2249,7 @@ unsigned int PropertyBoolList::getMemSize () const // PropertyColor //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyColor , App::Property) +TYPESYSTEM_SOURCE(App::PropertyColor, App::Property) //************************************************************************** // Construction/Destruction @@ -2149,10 +2261,10 @@ PropertyColor::~PropertyColor() = default; //************************************************************************** // Base class implementer -void PropertyColor::setValue(const Color &col) +void PropertyColor::setValue(const Color& col) { aboutToSetValue(); - _cCol=col; + _cCol = col; hasSetValue(); } @@ -2166,7 +2278,7 @@ void PropertyColor::setValue(uint32_t rgba) void PropertyColor::setValue(float r, float g, float b, float a) { aboutToSetValue(); - _cCol.set(r,g,b,a); + _cCol.set(r, g, b, a); hasSetValue(); } @@ -2175,7 +2287,7 @@ const Color& PropertyColor::getValue() const return _cCol; } -PyObject *PropertyColor::getPyObject() +PyObject* PropertyColor::getPyObject() { PyObject* rgba = PyTuple_New(4); PyObject* r = PyFloat_FromDouble(_cCol.r); @@ -2191,50 +2303,62 @@ PyObject *PropertyColor::getPyObject() return rgba; } -void PropertyColor::setPyObject(PyObject *value) +void PropertyColor::setPyObject(PyObject* value) { App::Color cCol; - if (PyTuple_Check(value) && (PyTuple_Size(value) == 3 || PyTuple_Size(value) == 4) ) { + if (PyTuple_Check(value) && (PyTuple_Size(value) == 3 || PyTuple_Size(value) == 4)) { PyObject* item; - item = PyTuple_GetItem(value,0); + item = PyTuple_GetItem(value, 0); if (PyFloat_Check(item)) { cCol.r = (float)PyFloat_AsDouble(item); - item = PyTuple_GetItem(value,1); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 1); + if (PyFloat_Check(item)) { cCol.g = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); - item = PyTuple_GetItem(value,2); - if (PyFloat_Check(item)) + } + item = PyTuple_GetItem(value, 2); + if (PyFloat_Check(item)) { cCol.b = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); + } if (PyTuple_Size(value) == 4) { - item = PyTuple_GetItem(value,3); - if (PyFloat_Check(item)) + item = PyTuple_GetItem(value, 3); + if (PyFloat_Check(item)) { cCol.a = (float)PyFloat_AsDouble(item); - else + } + else { throw Base::TypeError("Type in tuple must be consistent (float)"); + } } } else if (PyLong_Check(item)) { - cCol.r = PyLong_AsLong(item)/255.0; - item = PyTuple_GetItem(value,1); - if (PyLong_Check(item)) - cCol.g = PyLong_AsLong(item)/255.0; - else + cCol.r = PyLong_AsLong(item) / 255.0; + item = PyTuple_GetItem(value, 1); + if (PyLong_Check(item)) { + cCol.g = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); - item = PyTuple_GetItem(value,2); - if (PyLong_Check(item)) - cCol.b = PyLong_AsLong(item)/255.0; - else + } + item = PyTuple_GetItem(value, 2); + if (PyLong_Check(item)) { + cCol.b = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); + } if (PyTuple_Size(value) == 4) { - item = PyTuple_GetItem(value,3); - if (PyLong_Check(item)) - cCol.a = PyLong_AsLong(item)/255.0; - else + item = PyTuple_GetItem(value, 3); + if (PyLong_Check(item)) { + cCol.a = PyLong_AsLong(item) / 255.0; + } + else { throw Base::TypeError("Type in tuple must be consistent (integer)"); + } } } else { @@ -2245,21 +2369,22 @@ void PropertyColor::setPyObject(PyObject *value) cCol.setPackedValue(PyLong_AsUnsignedLong(value)); } else { - std::string error = std::string("type must be integer or tuple of float or tuple integer, not "); + std::string error = + std::string("type must be integer or tuple of float or tuple integer, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } - setValue( cCol ); + setValue(cCol); } -void PropertyColor::Save (Base::Writer &writer) const +void PropertyColor::Save(Base::Writer& writer) const { - writer.Stream() << writer.ind() << "" << endl; + writer.Stream() << writer.ind() << "" + << endl; } -void PropertyColor::Restore(Base::XMLReader &reader) +void PropertyColor::Restore(Base::XMLReader& reader) { // read my Element reader.readElement("PropertyColor"); @@ -2268,14 +2393,14 @@ void PropertyColor::Restore(Base::XMLReader &reader) setValue(rgba); } -Property *PropertyColor::Copy() const +Property* PropertyColor::Copy() const { - PropertyColor *p= new PropertyColor(); + PropertyColor* p = new PropertyColor(); p->_cCol = _cCol; return p; } -void PropertyColor::Paste(const Property &from) +void PropertyColor::Paste(const Property& from) { aboutToSetValue(); _cCol = dynamic_cast(from)._cCol; @@ -2286,7 +2411,7 @@ void PropertyColor::Paste(const Property &from) // PropertyColorList //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyColorList , App::PropertyLists) +TYPESYSTEM_SOURCE(App::PropertyColorList, App::PropertyLists) //************************************************************************** // Construction/Destruction @@ -2298,11 +2423,11 @@ PropertyColorList::~PropertyColorList() = default; //************************************************************************** // Base class implementer -PyObject *PropertyColorList::getPyObject() +PyObject* PropertyColorList::getPyObject() { PyObject* list = PyList_New(getSize()); - for(int i = 0;i" << std::endl; + writer.Stream() << writer.ind() << "" + << std::endl; } } -void PropertyColorList::Restore(Base::XMLReader &reader) +void PropertyColorList::Restore(Base::XMLReader& reader) { reader.readElement("ColorList"); if (reader.hasAttribute("file")) { - std::string file (reader.getAttribute("file")); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } } -void PropertyColorList::SaveDocFile (Base::Writer &writer) const +void PropertyColorList::SaveDocFile(Base::Writer& writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)getSize(); @@ -2357,33 +2484,33 @@ void PropertyColorList::SaveDocFile (Base::Writer &writer) const } } -void PropertyColorList::RestoreDocFile(Base::Reader &reader) +void PropertyColorList::RestoreDocFile(Base::Reader& reader) { Base::InputStream str(reader); - uint32_t uCt=0; + uint32_t uCt = 0; str >> uCt; std::vector values(uCt); - uint32_t value; // must be 32 bit long - for (auto & it : values) { + uint32_t value; // must be 32 bit long + for (auto& it : values) { str >> value; it.setPackedValue(value); } setValues(values); } -Property *PropertyColorList::Copy() const +Property* PropertyColorList::Copy() const { - PropertyColorList *p= new PropertyColorList(); + PropertyColorList* p = new PropertyColorList(); p->_lValueList = _lValueList; return p; } -void PropertyColorList::Paste(const Property &from) +void PropertyColorList::Paste(const Property& from) { setValues(dynamic_cast(from)._lValueList); } -unsigned int PropertyColorList::getMemSize () const +unsigned int PropertyColorList::getMemSize() const { return static_cast(_lValueList.size() * sizeof(Color)); } @@ -3126,8 +3253,7 @@ void PropertyMaterialList::Save(Base::Writer& writer) const if (!writer.isForceXML()) { writer.Stream() << writer.ind() << "" - << std::endl; + << " version=\"3\"/>" << std::endl; } } @@ -3169,7 +3295,7 @@ void PropertyMaterialList::SaveDocFile(Base::Writer& writer) const } } -void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string &value) const +void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string& value) const { uint32_t uCt = (uint32_t)value.size(); str << uCt; @@ -3299,44 +3425,50 @@ unsigned int PropertyMaterialList::getMemSize() const // PropertyPersistentObject //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TYPESYSTEM_SOURCE(App::PropertyPersistentObject , App::PropertyString) +TYPESYSTEM_SOURCE(App::PropertyPersistentObject, App::PropertyString) -PyObject *PropertyPersistentObject::getPyObject(){ - if(_pObject) +PyObject* PropertyPersistentObject::getPyObject() +{ + if (_pObject) { return _pObject->getPyObject(); + } return inherited::getPyObject(); } -void PropertyPersistentObject::Save(Base::Writer &writer) const{ +void PropertyPersistentObject::Save(Base::Writer& writer) const +{ inherited::Save(writer); -#define ELEMENT_PERSISTENT_OBJ "PersistentObject" - writer.Stream() << writer.ind() << "<" ELEMENT_PERSISTENT_OBJ ">" << std::endl; - if(_pObject) { + writer.Stream() << writer.ind() << "" << std::endl; + if (_pObject) { writer.incInd(); _pObject->Save(writer); writer.decInd(); } - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; } -void PropertyPersistentObject::Restore(Base::XMLReader &reader){ +void PropertyPersistentObject::Restore(Base::XMLReader& reader) +{ inherited::Restore(reader); - reader.readElement(ELEMENT_PERSISTENT_OBJ); - if(_pObject) + reader.readElement("PersistentObject"); + if (_pObject) { _pObject->Restore(reader); - reader.readEndElement(ELEMENT_PERSISTENT_OBJ); + } + reader.readEndElement("PersistentObject"); } -Property *PropertyPersistentObject::Copy() const{ - auto *p= new PropertyPersistentObject(); +Property* PropertyPersistentObject::Copy() const +{ + auto* p = new PropertyPersistentObject(); p->_cValue = _cValue; p->_pObject = _pObject; return p; } -void PropertyPersistentObject::Paste(const Property &from){ - const auto &prop = dynamic_cast(from); - if(_cValue!=prop._cValue || _pObject!=prop._pObject) { +void PropertyPersistentObject::Paste(const Property& from) +{ + const auto& prop = dynamic_cast(from); + if (_cValue != prop._cValue || _pObject != prop._pObject) { aboutToSetValue(); _cValue = prop._cValue; _pObject = prop._pObject; @@ -3344,29 +3476,38 @@ void PropertyPersistentObject::Paste(const Property &from){ } } -unsigned int PropertyPersistentObject::getMemSize () const{ +unsigned int PropertyPersistentObject::getMemSize() const +{ auto size = inherited::getMemSize(); - if(_pObject) + if (_pObject) { size += _pObject->getMemSize(); + } return size; } -void PropertyPersistentObject::setValue(const char *type) { - if(!type) type = ""; - if(type[0]) { +void PropertyPersistentObject::setValue(const char* type) +{ + if (!type) { + type = ""; + } + if (type[0]) { Base::Type::importModule(type); Base::Type t = Base::Type::fromName(type); - if(t.isBad()) + if (t.isBad()) { throw Base::TypeError("Invalid type"); - if(!t.isDerivedFrom(Persistence::getClassTypeId())) + } + if (!t.isDerivedFrom(Persistence::getClassTypeId())) { throw Base::TypeError("Type must be derived from Base::Persistence"); - if(_pObject && _pObject->getTypeId()==t) + } + if (_pObject && _pObject->getTypeId() == t) { return; + } } aboutToSetValue(); _pObject.reset(); _cValue = type; - if(type[0]) + if (type[0]) { _pObject.reset(static_cast(Base::Type::createInstanceByName(type))); + } hasSetValue(); } diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index 4bdf33b300ea..3fce6611bb91 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -37,11 +37,12 @@ #include "Material.h" -namespace Base { +namespace Base +{ class InputStream; class OutputStream; class Writer; -} +} // namespace Base namespace App @@ -65,23 +66,33 @@ class AppExport PropertyInteger: public Property /** This method returns a string representation of the property */ long getValue() const; - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyIntegerItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyIntegerItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override{return sizeof(long);} + unsigned int getMemSize() const override + { + return sizeof(long); + } - void setPathValue(const App::ObjectIdentifier & path, const boost::any & value) override; - const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const override { return _lValue; } + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + const boost::any getPathValue(const App::ObjectIdentifier& /*path*/) const override + { + return _lValue; + } - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -101,36 +112,39 @@ class AppExport PropertyPath: public Property TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - PropertyPath(); ~PropertyPath() override; /** Sets the property */ - void setValue(const boost::filesystem::path &); + void setValue(const boost::filesystem::path&); /** Sets the property */ - void setValue(const char *); + void setValue(const char*); /** This method returns a string representation of the property */ - const boost::filesystem::path &getValue() const; + const boost::filesystem::path& getValue() const; - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyPathItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyPathItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -152,7 +166,7 @@ class AppExport PropertyEnumeration: public Property PropertyEnumeration(); /// Obvious constructor - explicit PropertyEnumeration(const Enumeration &e); + explicit PropertyEnumeration(const Enumeration& e); /// destructor ~PropertyEnumeration() override; @@ -173,7 +187,7 @@ class AppExport PropertyEnumeration: public Property /** setting the enumeration string as vector of strings * This makes the enumeration custom. */ - void setEnums(const std::vector &Enums); + void setEnums(const std::vector& Enums); /** set the enum by a string * is slower than setValue(long). Use long if possible @@ -187,7 +201,7 @@ class AppExport PropertyEnumeration: public Property void setValue(long); /// Setter using Enumeration - void setValue(const Enumeration &source); + void setValue(const Enumeration& source); /// Returns current value of the enumeration as an integer long getValue() const; @@ -199,16 +213,16 @@ class AppExport PropertyEnumeration: public Property bool isPartOf(const char* value) const; /// get the value as string - const char * getValueAsString() const; + const char* getValueAsString() const; /// Returns Enumeration object - const Enumeration &getEnum() const; + const Enumeration& getEnum() const; /// get all possible enum values as vector of strings std::vector getEnumVector() const; /// set enum values as vector of strings - void setEnumVector(const std::vector &); + void setEnumVector(const std::vector&); /// get the pointer to the enum list bool hasEnums() const; @@ -216,24 +230,31 @@ class AppExport PropertyEnumeration: public Property bool isValid() const; //@} - const char* getEditorName() const override { return _editorTypeName.c_str(); } - void setEditorName(const char* name) { _editorTypeName = name; } + const char* getEditorName() const override + { + return _editorTypeName.c_str(); + } + void setEditorName(const char* name) + { + _editorTypeName = name; + } - PyObject * getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save(Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property * Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - void setPathValue(const App::ObjectIdentifier & path, const boost::any & value) override; - virtual bool setPyPathValue(const App::ObjectIdentifier & path, const Py::Object &value); - const boost::any getPathValue(const App::ObjectIdentifier & /*path*/) const override; - bool getPyPathValue(const ObjectIdentifier &path, Py::Object &r) const override; + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + virtual bool setPyPathValue(const App::ObjectIdentifier& path, const Py::Object& value); + const boost::any getPathValue(const App::ObjectIdentifier& /*path*/) const override; + bool getPyPathValue(const ObjectIdentifier& path, Py::Object& r) const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -266,22 +287,21 @@ class AppExport PropertyIntegerConstraint: public PropertyInteger /// Constraint methods //@{ /// the boundary struct - struct Constraints { + struct Constraints + { long LowerBound, UpperBound, StepSize; Constraints() : LowerBound(0) , UpperBound(0) , StepSize(0) , candelete(false) - { - } + {} Constraints(long l, long u, long s) : LowerBound(l) , UpperBound(u) , StepSize(s) , candelete(false) - { - } + {} ~Constraints() = default; void setDeletable(bool on) { @@ -291,6 +311,7 @@ class AppExport PropertyIntegerConstraint: public PropertyInteger { return candelete; } + private: bool candelete; }; @@ -304,18 +325,21 @@ class AppExport PropertyIntegerConstraint: public PropertyInteger */ void setConstraints(const Constraints* sConstraint); /// get the constraint struct - const Constraints* getConstraints() const; + const Constraints* getConstraints() const; //@} long getMinimum() const; long getMaximum() const; long getStepSize() const; - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyIntegerConstraintItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyIntegerConstraintItem"; + } void setPyObject(PyObject* py) override; protected: - const Constraints* _ConstStruct{nullptr}; + const Constraints* _ConstStruct {nullptr}; }; /** Percent property @@ -357,19 +381,21 @@ class AppExport PropertyIntegerList: public PropertyListsT ~PropertyIntegerList() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyIntegerListItem"; } + { + return "Gui::PropertyEditor::PropertyIntegerListItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; protected: - long getPyValue(PyObject *item) const override; + long getPyValue(PyObject* item) const override; }; /** Integer list properties @@ -396,30 +422,41 @@ class AppExport PropertyIntegerSet: public Property /** Sets the property */ void setValue(long); - void setValue(){;} + void setValue() + { + ; + } - void addValue (long value){_lValueSet.insert(value);} - void setValues (const std::set& values); + void addValue(long value) + { + _lValueSet.insert(value); + } + void setValues(const std::set& values); - const std::set &getValues() const{return _lValueSet;} + const std::set& getValues() const + { + return _lValueSet; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } return getTypeId() == other.getTypeId() && getValues() == static_cast(&other)->getValues(); } + private: std::set _lValueSet; }; @@ -433,7 +470,6 @@ class AppExport PropertyMap: public Property TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -450,31 +486,40 @@ class AppExport PropertyMap: public Property /** Sets the property */ - void setValue(){} - void setValue(const std::string& key,const std::string& value); - void setValues(const std::map&); + void setValue() + {} + void setValue(const std::string& key, const std::string& value); + void setValues(const std::map&); /// index operator - const std::string& operator[] (const std::string& key) const ; + const std::string& operator[](const std::string& key) const; - void set1Value (const std::string& key, const std::string& value){_lValueList.operator[] (key) = value;} + void set1Value(const std::string& key, const std::string& value) + { + _lValueList.operator[](key) = value; + } - const std::map &getValues() const{return _lValueList;} + const std::map& getValues() const + { + return _lValueList; + } - //virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringListItem"; } + // virtual const char* getEditorName(void) const { return + // "Gui::PropertyEditor::PropertyStringListItem"; } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -483,11 +528,10 @@ class AppExport PropertyMap: public Property } private: - std::map _lValueList; + std::map _lValueList; }; - /** Float properties * This is the father of all properties handling floats. * Use this type only in rare cases. Mostly you want to @@ -515,23 +559,30 @@ class AppExport PropertyFloat: public Property void setValue(double lValue); double getValue() const; - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyFloatItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyFloatItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override{return sizeof(double);} + unsigned int getMemSize() const override + { + return sizeof(double); + } - void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override; - const boost::any getPathValue(const App::ObjectIdentifier &path) const override; + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + const boost::any getPathValue(const App::ObjectIdentifier& path) const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -554,7 +605,6 @@ class AppExport PropertyFloatConstraint: public PropertyFloat TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** Value Constructor * Construct with explicit Values */ @@ -570,22 +620,21 @@ class AppExport PropertyFloatConstraint: public PropertyFloat /// Constraint methods //@{ /// the boundary struct - struct Constraints { + struct Constraints + { double LowerBound, UpperBound, StepSize; Constraints() : LowerBound(0) , UpperBound(0) , StepSize(0) , candelete(false) - { - } + {} Constraints(double l, double u, double s) : LowerBound(l) , UpperBound(u) , StepSize(s) , candelete(false) - { - } + {} ~Constraints() = default; void setDeletable(bool on) { @@ -595,6 +644,7 @@ class AppExport PropertyFloatConstraint: public PropertyFloat { return candelete; } + private: bool candelete; }; @@ -608,7 +658,7 @@ class AppExport PropertyFloatConstraint: public PropertyFloat */ void setConstraints(const Constraints* sConstrain); /// get the constraint struct - const Constraints* getConstraints() const; + const Constraints* getConstraints() const; //@} double getMinimum() const; @@ -616,12 +666,14 @@ class AppExport PropertyFloatConstraint: public PropertyFloat double getStepSize() const; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyFloatConstraintItem"; } + { + return "Gui::PropertyEditor::PropertyFloatConstraintItem"; + } void setPyObject(PyObject* py) override; protected: - const Constraints* _ConstStruct{nullptr}; + const Constraints* _ConstStruct {nullptr}; }; @@ -633,11 +685,14 @@ class AppExport PropertyFloatConstraint: public PropertyFloat class AppExport PropertyPrecision: public PropertyFloatConstraint { TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: PropertyPrecision(); ~PropertyPrecision() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyPrecisionItem"; } + { + return "Gui::PropertyEditor::PropertyPrecisionItem"; + } }; @@ -646,7 +701,6 @@ class AppExport PropertyFloatList: public PropertyListsT TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -660,22 +714,24 @@ class AppExport PropertyFloatList: public PropertyListsT ~PropertyFloatList() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyFloatListItem"; } + { + return "Gui::PropertyEditor::PropertyFloatListItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; protected: - double getPyValue(PyObject *item) const override; + double getPyValue(PyObject* item) const override; }; @@ -687,7 +743,6 @@ class AppExport PropertyString: public Property TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -701,27 +756,36 @@ class AppExport PropertyString: public Property ~PropertyString() override; virtual void setValue(const char* sString); - void setValue(const std::string &sString); + void setValue(const std::string& sString); const char* getValue() const; const std::string& getStrValue() const - { return _cValue; } - bool isEmpty(){return _cValue.empty();} + { + return _cValue; + } + bool isEmpty() + { + return _cValue.empty(); + } - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyStringItem"; } - PyObject *getPyObject() override; + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyStringItem"; + } + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; - void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override; - const boost::any getPathValue(const App::ObjectIdentifier &path) const override; + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + const boost::any getPathValue(const App::ObjectIdentifier& path) const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -741,7 +805,6 @@ class AppExport PropertyUUID: public Property TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -755,24 +818,26 @@ class AppExport PropertyUUID: public Property ~PropertyUUID() override; - void setValue(const Base::Uuid &); + void setValue(const Base::Uuid&); void setValue(const char* sString); - void setValue(const std::string &sString); + void setValue(const std::string& sString); const std::string& getValueStr() const; const Base::Uuid& getValue() const; - //virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringItem"; } - PyObject *getPyObject() override; + // virtual const char* getEditorName(void) const { return + // "Gui::PropertyEditor::PropertyStringItem"; } + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -787,7 +852,7 @@ class AppExport PropertyUUID: public Property /** Property handling with font names. */ -class AppExport PropertyFont : public PropertyString +class AppExport PropertyFont: public PropertyString { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -795,9 +860,12 @@ class AppExport PropertyFont : public PropertyString PropertyFont(); ~PropertyFont() override; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyFontItem"; } + { + return "Gui::PropertyEditor::PropertyFontItem"; + } - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -812,7 +880,6 @@ class AppExport PropertyStringList: public PropertyListsT using inherited = PropertyListsT; public: - /** * A constructor. * A more elaborate description of the constructor. @@ -829,31 +896,32 @@ class AppExport PropertyStringList: public PropertyListsT using inherited::setValues; const char* getEditorName() const override - { return "Gui::PropertyEditor::PropertyStringListItem"; } + { + return "Gui::PropertyEditor::PropertyStringListItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override; + unsigned int getMemSize() const override; protected: - std::string getPyValue(PyObject *item) const override; + std::string getPyValue(PyObject* item) const override; }; /** Bool properties * This is the father of all properties handling booleans. */ -class AppExport PropertyBool : public Property +class AppExport PropertyBool: public Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -869,23 +937,30 @@ class AppExport PropertyBool : public Property void setValue(bool lValue); bool getValue() const; - const char* getEditorName() const override { return "Gui::PropertyEditor::PropertyBoolItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyBoolItem"; + } - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; + Property* Copy() const override; + void Paste(const Property& from) override; - unsigned int getMemSize () const override{return sizeof(bool);} + unsigned int getMemSize() const override + { + return sizeof(bool); + } - void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override; - const boost::any getPathValue(const App::ObjectIdentifier &path) const override; + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + const boost::any getPathValue(const App::ObjectIdentifier& path) const override; - bool isSame(const Property &other) const override { + bool isSame(const Property& other) const override + { if (&other == this) { return true; } @@ -900,24 +975,24 @@ class AppExport PropertyBool : public Property /** Bool list properties * */ -class AppExport PropertyBoolList : public PropertyListsT > +class AppExport PropertyBoolList: public PropertyListsT> { TYPESYSTEM_HEADER_WITH_OVERRIDE(); - using inherited = PropertyListsT >; + using inherited = PropertyListsT>; public: PropertyBoolList(); ~PropertyBoolList() override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setPyObject(PyObject* py) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; protected: bool getPyValue(PyObject* py) const override; @@ -927,7 +1002,7 @@ class AppExport PropertyBoolList : public PropertyListsT TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - /** * A constructor. * A more elaborate description of the constructor. @@ -997,17 +1078,17 @@ class AppExport PropertyColorList: public PropertyListsT */ ~PropertyColorList() override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; protected: Color getPyValue(PyObject* py) const override; @@ -1118,7 +1199,8 @@ class AppExport PropertyMaterialList: public PropertyListsT { PropertyListsT::setValue(materials); } - void setValues(const std::vector& newValues = std::vector()) override; + void + setValues(const std::vector& newValues = std::vector()) override; void setValue(const Material& mat); void setValue(int index, const Material& mat); @@ -1196,7 +1278,8 @@ class AppExport PropertyMaterialList: public PropertyListsT Material getPyValue(PyObject* py) const override; private: - enum Format { + enum Format + { Version_0, Version_1, Version_2, @@ -1206,7 +1289,7 @@ class AppExport PropertyMaterialList: public PropertyListsT void RestoreDocFileV0(uint32_t count, Base::Reader& reader); void RestoreDocFileV3(Base::Reader& reader); - void writeString(Base::OutputStream& str, const std::string &value) const; + void writeString(Base::OutputStream& str, const std::string& value) const; void readString(Base::InputStream& str, std::string& value); void verifyIndex(int index) const; @@ -1222,21 +1305,24 @@ class AppExport PropertyMaterialList: public PropertyListsT * In Python, this property can be assigned a type string to create a dynamic FreeCAD * object, and then read back as the Python binding of the newly created object. */ -class AppExport PropertyPersistentObject: public PropertyString { +class AppExport PropertyPersistentObject: public PropertyString +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); using inherited = PropertyString; + public: - PyObject *getPyObject() override; + PyObject* getPyObject() override; void setValue(const char* type) override; - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; - Property *Copy() const override; - void Paste(const Property &from) override; - unsigned int getMemSize () const override; + Property* Copy() const override; + void Paste(const Property& from) override; + unsigned int getMemSize() const override; - std::shared_ptr getObject() const { + std::shared_ptr getObject() const + { return _pObject; } @@ -1244,6 +1330,6 @@ class AppExport PropertyPersistentObject: public PropertyString { std::shared_ptr _pObject; }; -} // namespace App +} // namespace App -#endif // APP_PROPERTYSTANDARD_H +#endif // APP_PROPERTYSTANDARD_H diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index 867555456c15..bd8a0610bcf6 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -37,8 +37,8 @@ using namespace Base; using namespace std; -const PropertyQuantityConstraint::Constraints LengthStandard = {0.0,DBL_MAX,1.0}; -const PropertyQuantityConstraint::Constraints AngleStandard = {-360,360,1.0}; +const PropertyQuantityConstraint::Constraints LengthStandard = {0.0, DBL_MAX, 1.0}; +const PropertyQuantityConstraint::Constraints AngleStandard = {-360, 360, 1.0}; //************************************************************************** // PropertyQuantity @@ -48,7 +48,7 @@ TYPESYSTEM_SOURCE(App::PropertyQuantity, App::PropertyFloat) Base::Quantity PropertyQuantity::getQuantityValue() const { - return Quantity(_dValue,_Unit); + return Quantity(_dValue, _Unit); } const char* PropertyQuantity::getEditorName() const @@ -56,24 +56,26 @@ const char* PropertyQuantity::getEditorName() const return "Gui::PropertyEditor::PropertyUnitItem"; } -PyObject *PropertyQuantity::getPyObject() +PyObject* PropertyQuantity::getPyObject() { - return new QuantityPy (new Quantity(_dValue,_Unit)); + return new QuantityPy(new Quantity(_dValue, _Unit)); } -Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject *value) +Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject* value) { Base::Quantity quant; - if (PyUnicode_Check(value)){ + if (PyUnicode_Check(value)) { quant = Quantity::parse(QString::fromUtf8(PyUnicode_AsUTF8(value))); } - else if (PyFloat_Check(value)) - quant = Quantity(PyFloat_AsDouble(value),_Unit); - else if (PyLong_Check(value)) - quant = Quantity(double(PyLong_AsLong(value)),_Unit); + else if (PyFloat_Check(value)) { + quant = Quantity(PyFloat_AsDouble(value), _Unit); + } + else if (PyLong_Check(value)) { + quant = Quantity(double(PyLong_AsLong(value)), _Unit); + } else if (PyObject_TypeCheck(value, &(QuantityPy::Type))) { - Base::QuantityPy *pcObject = static_cast(value); + Base::QuantityPy* pcObject = static_cast(value); quant = *(pcObject->getQuantityPtr()); } else { @@ -85,45 +87,47 @@ Base::Quantity PropertyQuantity::createQuantityFromPy(PyObject *value) return quant; } -void PropertyQuantity::setPyObject(PyObject *value) +void PropertyQuantity::setPyObject(PyObject* value) { // Set the unit if Unit object supplied, else check the unit // and set the value if (PyObject_TypeCheck(value, &(UnitPy::Type))) { - Base::UnitPy *pcObject = static_cast(value); + Base::UnitPy* pcObject = static_cast(value); Base::Unit unit = *(pcObject->getUnitPtr()); aboutToSetValue(); _Unit = unit; hasSetValue(); } else { - Base::Quantity quant= createQuantityFromPy(value); + Base::Quantity quant = createQuantityFromPy(value); Unit unit = quant.getUnit(); - if (unit.isEmpty()){ + if (unit.isEmpty()) { PropertyFloat::setValue(quant.getValue()); return; } - if (unit != _Unit) + if (unit != _Unit) { throw Base::UnitsMismatchError("Not matching Unit!"); + } PropertyFloat::setValue(quant.getValue()); } } -void PropertyQuantity::setPathValue(const ObjectIdentifier & /*path*/, const boost::any &value) +void PropertyQuantity::setPathValue(const ObjectIdentifier& /*path*/, const boost::any& value) { auto q = App::anyToQuantity(value); aboutToSetValue(); - if(!q.getUnit().isEmpty()) + if (!q.getUnit().isEmpty()) { _Unit = q.getUnit(); - _dValue=q.getValue(); + } + _dValue = q.getValue(); setValue(q.getValue()); } -const boost::any PropertyQuantity::getPathValue(const ObjectIdentifier & /*path*/) const +const boost::any PropertyQuantity::getPathValue(const ObjectIdentifier& /*path*/) const { return Quantity(_dValue, _Unit); } @@ -145,55 +149,61 @@ const char* PropertyQuantityConstraint::getEditorName() const return "Gui::PropertyEditor::PropertyUnitConstraintItem"; } -const PropertyQuantityConstraint::Constraints* PropertyQuantityConstraint::getConstraints() const +const PropertyQuantityConstraint::Constraints* PropertyQuantityConstraint::getConstraints() const { return _ConstStruct; } double PropertyQuantityConstraint::getMinimum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->LowerBound; + } return std::numeric_limits::min(); } double PropertyQuantityConstraint::getMaximum() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->UpperBound; + } return std::numeric_limits::max(); } double PropertyQuantityConstraint::getStepSize() const { - if (_ConstStruct) + if (_ConstStruct) { return _ConstStruct->StepSize; + } return 1.0; } -void PropertyQuantityConstraint::setPyObject(PyObject *value) +void PropertyQuantityConstraint::setPyObject(PyObject* value) { - Base::Quantity quant= createQuantityFromPy(value); + Base::Quantity quant = createQuantityFromPy(value); Unit unit = quant.getUnit(); double temp = quant.getValue(); if (_ConstStruct) { - if (temp > _ConstStruct->UpperBound) + if (temp > _ConstStruct->UpperBound) { temp = _ConstStruct->UpperBound; - else if (temp < _ConstStruct->LowerBound) + } + else if (temp < _ConstStruct->LowerBound) { temp = _ConstStruct->LowerBound; + } } quant.setValue(temp); - if (unit.isEmpty()){ - PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method + if (unit.isEmpty()) { + PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method return; } - if (unit != _Unit) + if (unit != _Unit) { throw Base::UnitsMismatchError("Not matching Unit!"); + } - PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method + PropertyFloat::setValue(quant.getValue()); // clazy:exclude=skipped-base-method } // ------------------------------------------------------ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index c0854e47c1b6..0d4780eac5ff 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -29,7 +29,8 @@ #include "PropertyStandard.h" -namespace Base { +namespace Base +{ class Writer; } @@ -39,7 +40,7 @@ namespace App /** Float with Unit property * This is a property for float with a predefined Unit associated. */ -class AppExport PropertyQuantity : public PropertyFloat +class AppExport PropertyQuantity: public PropertyFloat { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -51,35 +52,49 @@ class AppExport PropertyQuantity : public PropertyFloat const char* getEditorName() const override; - PyObject *getPyObject() override; - void setPyObject(PyObject *) override; + PyObject* getPyObject() override; + void setPyObject(PyObject*) override; - void setUnit(const Base::Unit &u) {_Unit = u;} - const Base::Unit &getUnit() const {return _Unit;} + void setUnit(const Base::Unit& u) + { + _Unit = u; + } + const Base::Unit& getUnit() const + { + return _Unit; + } - void setValue(double lValue) { PropertyFloat::setValue(lValue); } - double getValue() const { return PropertyFloat::getValue(); } + void setValue(double lValue) + { + PropertyFloat::setValue(lValue); + } + double getValue() const + { + return PropertyFloat::getValue(); + } - void setPathValue(const App::ObjectIdentifier &path, const boost::any &value) override; - const boost::any getPathValue(const App::ObjectIdentifier &path) const override; + void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override; + const boost::any getPathValue(const App::ObjectIdentifier& path) const override; - bool isSame(const Property &other) const override { - if (&other == this) + bool isSame(const Property& other) const override + { + if (&other == this) { return true; + } return getTypeId() == other.getTypeId() && getValue() == static_cast(&other)->getValue() && _Unit == static_cast(&other)->_Unit; } protected: - Base::Quantity createQuantityFromPy(PyObject *value); + Base::Quantity createQuantityFromPy(PyObject* value); Base::Unit _Unit; }; /** Float with Unit property * This is a property for float with a predefined Unit associated. */ -class AppExport PropertyQuantityConstraint : public PropertyQuantity +class AppExport PropertyQuantityConstraint: public PropertyQuantity { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -90,7 +105,8 @@ class AppExport PropertyQuantityConstraint : public PropertyQuantity /// Constraint methods //@{ /// the boundary struct - struct Constraints { + struct Constraints + { double LowerBound, UpperBound, StepSize; }; /** setting the boundaries @@ -103,7 +119,7 @@ class AppExport PropertyQuantityConstraint : public PropertyQuantity */ void setConstraints(const Constraints* sConstrain); /// get the constraint struct - const Constraints* getConstraints() const; + const Constraints* getConstraints() const; //@} double getMinimum() const; @@ -111,10 +127,10 @@ class AppExport PropertyQuantityConstraint : public PropertyQuantity double getStepSize() const; const char* getEditorName() const override; - void setPyObject(PyObject *) override; + void setPyObject(PyObject*) override; private: - const Constraints* _ConstStruct{nullptr}; + const Constraints* _ConstStruct {nullptr}; }; // ------------------------------------------------------ @@ -158,7 +174,10 @@ class AppExport PropertyAngle: public PropertyQuantityConstraint public: PropertyAngle(); ~PropertyAngle() override = default; - const char *getEditorName() const override { return "Gui::PropertyEditor::PropertyAngleItem"; } + const char* getEditorName() const override + { + return "Gui::PropertyEditor::PropertyAngleItem"; + } }; /** Area property @@ -425,7 +444,7 @@ class AppExport PropertyInverseLength: public PropertyQuantity /** InverseVolume property * This is a property for representing the reciprocal of volume. It is basically a float -* property. which must not be negative. On the Gui it has a quantity like 1/m^3. + * property. which must not be negative. On the Gui it has a quantity like 1/m^3. */ class AppExport PropertyInverseVolume: public PropertyQuantity { @@ -514,11 +533,11 @@ class AppExport PropertyMagneticFluxDensity: public PropertyQuantity ~PropertyMagneticFluxDensity() override = default; }; - /** Magnetization property +/** Magnetization property * This is a property for representing magnetizations. It is basically a float * property. On the Gui it has a quantity like A/m. */ - class AppExport PropertyMagnetization: public PropertyQuantity +class AppExport PropertyMagnetization: public PropertyQuantity { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -852,6 +871,6 @@ class AppExport PropertyYoungsModulus: public PropertyQuantity ~PropertyYoungsModulus() override = default; }; -}// namespace App +} // namespace App -#endif// APP_PROPERTYUNITS_H +#endif // APP_PROPERTYUNITS_H diff --git a/src/App/private/DocumentP.h b/src/App/private/DocumentP.h index b0098f1715cc..64d3b6697d3f 100644 --- a/src/App/private/DocumentP.h +++ b/src/App/private/DocumentP.h @@ -154,8 +154,8 @@ struct DocumentP Path tmp); std::vector topologicalSort(const std::vector& objects) const; - static std::vector partialTopologicalSort( - const std::vector& objects); + static std::vector + partialTopologicalSort(const std::vector& objects); static void checkStringHasher(const Base::XMLReader& reader); }; From 2197d626b41b527fea688a2cffae89f71b82089a Mon Sep 17 00:00:00 2001 From: Max Wilfinger <6246609+maxwxyz@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:48:38 +0100 Subject: [PATCH 037/161] Update PROBLEM_REPORT.yml Add "needs confirmation" as default tag for new issues. --- .github/ISSUE_TEMPLATE/PROBLEM_REPORT.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/PROBLEM_REPORT.yml b/.github/ISSUE_TEMPLATE/PROBLEM_REPORT.yml index d54be10c50a3..c58333058f26 100644 --- a/.github/ISSUE_TEMPLATE/PROBLEM_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/PROBLEM_REPORT.yml @@ -1,6 +1,6 @@ name: Report a Problem description: Have you found something that does not work well, is too hard to do or is missing altogether? Please create a Problem Report. -labels: ["Status: Needs triage"] +labels: ["Status: Needs triage","Status: Needs confirmation"] body: - type: checkboxes id: existing_issue @@ -40,6 +40,8 @@ body: - Expressions - FEM - File formats + - Material + - Measurement - Mesh - OpenSCAD - Part From a4bc06219b6046d72c57294da2c0d46f6a575192 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Nov 2024 21:39:57 +0100 Subject: [PATCH 038/161] Tests: Add unit test to explore a null shape --- tests/src/Mod/Part/App/TopoDS_Shape.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/src/Mod/Part/App/TopoDS_Shape.cpp b/tests/src/Mod/Part/App/TopoDS_Shape.cpp index 7b37566bf088..26d2f0dcdd91 100644 --- a/tests/src/Mod/Part/App/TopoDS_Shape.cpp +++ b/tests/src/Mod/Part/App/TopoDS_Shape.cpp @@ -3,8 +3,10 @@ #include #include #include +#include #include #include +#include #include // NOLINTBEGIN @@ -34,5 +36,12 @@ TEST(TopoDS_Shape, TestCastNullEdge) EXPECT_TRUE(vertex.IsNull()); } +TEST(TopoDS_Shape, TestExploreNullShape) +{ + TopoDS_Face face; + TopExp_Explorer xp(face, TopAbs_FACE); + EXPECT_FALSE(xp.More()); +} + // clang-format on // NOLINTEND From f3d84b601fdfa6cae36843f8aad51b3cccfc2428 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 1 Jul 2024 13:44:21 +0200 Subject: [PATCH 039/161] PD: Fix convoluted event handling of dress-up task boxes --- .../PartDesign/Gui/TaskChamferParameters.cpp | 5 --- .../PartDesign/Gui/TaskChamferParameters.h | 1 - .../PartDesign/Gui/TaskDraftParameters.cpp | 5 --- src/Mod/PartDesign/Gui/TaskDraftParameters.h | 1 - .../PartDesign/Gui/TaskDressUpParameters.cpp | 37 ++++++++++--------- .../PartDesign/Gui/TaskDressUpParameters.h | 4 +- .../PartDesign/Gui/TaskFilletParameters.cpp | 5 --- src/Mod/PartDesign/Gui/TaskFilletParameters.h | 3 +- .../Gui/TaskThicknessParameters.cpp | 5 --- .../PartDesign/Gui/TaskThicknessParameters.h | 1 - 10 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp b/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp index 4914511509ed..75f30d13ca0b 100644 --- a/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp @@ -293,11 +293,6 @@ TaskChamferParameters::~TaskChamferParameters() } } -bool TaskChamferParameters::event(QEvent* e) -{ - return TaskDressUpParameters::KeyEvent(e); -} - void TaskChamferParameters::changeEvent(QEvent* e) { TaskBox::changeEvent(e); diff --git a/src/Mod/PartDesign/Gui/TaskChamferParameters.h b/src/Mod/PartDesign/Gui/TaskChamferParameters.h index 0d93bf3c2184..0131424bcfe3 100644 --- a/src/Mod/PartDesign/Gui/TaskChamferParameters.h +++ b/src/Mod/PartDesign/Gui/TaskChamferParameters.h @@ -56,7 +56,6 @@ private Q_SLOTS: protected: void setButtons(const selectionModes mode) override; - bool event(QEvent *e) override; void changeEvent(QEvent *e) override; void onSelectionChanged(const Gui::SelectionChanges& msg) override; diff --git a/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp b/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp index 9e6b27b2bdea..fd99eab73779 100644 --- a/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp @@ -272,11 +272,6 @@ TaskDraftParameters::~TaskDraftParameters() } } -bool TaskDraftParameters::event(QEvent* e) -{ - return TaskDressUpParameters::KeyEvent(e); -} - void TaskDraftParameters::changeEvent(QEvent* e) { TaskBox::changeEvent(e); diff --git a/src/Mod/PartDesign/Gui/TaskDraftParameters.h b/src/Mod/PartDesign/Gui/TaskDraftParameters.h index bb170a1b79f6..b827493c443e 100644 --- a/src/Mod/PartDesign/Gui/TaskDraftParameters.h +++ b/src/Mod/PartDesign/Gui/TaskDraftParameters.h @@ -57,7 +57,6 @@ private Q_SLOTS: protected: void setButtons(const selectionModes mode) override; - bool event(QEvent *e) override; void changeEvent(QEvent *e) override; void onSelectionChanged(const Gui::SelectionChanges& msg) override; diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp index 3feec5643af9..6bb7b87e0e56 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp @@ -319,11 +319,10 @@ void TaskDressUpParameters::createDeleteAction(QListWidget* parentList) parentList->setContextMenuPolicy(Qt::ActionsContextMenu); } -bool TaskDressUpParameters::KeyEvent(QEvent *e) +bool TaskDressUpParameters::event(QEvent* event) { - // in case another instance takes key events, accept the overridden key event - if (e && e->type() == QEvent::ShortcutOverride) { - QKeyEvent * kevent = static_cast(e); + if (event->type() == QEvent::ShortcutOverride) { + QKeyEvent * kevent = static_cast(event); // NOLINT if (deleteAction && Gui::QtTools::matches(kevent, deleteAction->shortcut())) { kevent->accept(); return true; @@ -333,22 +332,24 @@ bool TaskDressUpParameters::KeyEvent(QEvent *e) return true; } } - // if we have a Del key, trigger the deleteAction - else if (e && e->type() == QEvent::KeyPress) { - QKeyEvent * kevent = static_cast(e); - if (deleteAction && deleteAction->isEnabled() && - Gui::QtTools::matches(kevent, deleteAction->shortcut())) { - deleteAction->trigger(); - return true; - } - if (addAllEdgesAction && addAllEdgesAction->isEnabled() && - Gui::QtTools::matches(kevent, addAllEdgesAction->shortcut())) { - addAllEdgesAction->trigger(); - return true; - } + + return TaskBox::event(event); +} + +void TaskDressUpParameters::keyPressEvent(QKeyEvent* ke) +{ + if (deleteAction && deleteAction->isEnabled() && + Gui::QtTools::matches(ke, deleteAction->shortcut())) { + deleteAction->trigger(); + return; + } + if (addAllEdgesAction && addAllEdgesAction->isEnabled() && + Gui::QtTools::matches(ke, addAllEdgesAction->shortcut())) { + addAllEdgesAction->trigger(); + return; } - return TaskDressUpParameters::event(e); + TaskBox::keyPressEvent(ke); } const std::vector TaskDressUpParameters::getReferences() const diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h index 905dbca9f379..9220f2395c6f 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h @@ -64,6 +64,8 @@ class TaskDressUpParameters : public Gui::TaskView::TaskBox, public Gui::Selecti return transactionID; } + bool event(QEvent* event) override; + protected Q_SLOTS: void onButtonRefSel(const bool checked); void doubleClicked(QListWidgetItem* item); @@ -76,7 +78,7 @@ protected Q_SLOTS: protected: void referenceSelected(const Gui::SelectionChanges& msg, QListWidget* widget); bool wasDoubleClicked = false; - bool KeyEvent(QEvent *e); + void keyPressEvent(QKeyEvent* ke) override; void hideOnError(); void addAllEdges(QListWidget* listWidget); void deleteRef(QListWidget* listWidget); diff --git a/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp b/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp index 8fa4d7ee6f45..3d34226178a4 100644 --- a/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp @@ -176,11 +176,6 @@ TaskFilletParameters::~TaskFilletParameters() } } -bool TaskFilletParameters::event(QEvent* e) -{ - return TaskDressUpParameters::KeyEvent(e); -} - void TaskFilletParameters::changeEvent(QEvent* e) { TaskBox::changeEvent(e); diff --git a/src/Mod/PartDesign/Gui/TaskFilletParameters.h b/src/Mod/PartDesign/Gui/TaskFilletParameters.h index d5142d3f8abc..5fdfe8767f26 100644 --- a/src/Mod/PartDesign/Gui/TaskFilletParameters.h +++ b/src/Mod/PartDesign/Gui/TaskFilletParameters.h @@ -50,8 +50,7 @@ private Q_SLOTS: protected: double getLength() const; void setButtons(const selectionModes mode) override; - bool event(QEvent *e) override; - void changeEvent(QEvent *e) override; + void changeEvent(QEvent* e) override; void onSelectionChanged(const Gui::SelectionChanges& msg) override; private: diff --git a/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp b/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp index 31ccf74721a3..b6cffe420008 100644 --- a/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp @@ -245,11 +245,6 @@ TaskThicknessParameters::~TaskThicknessParameters() } } -bool TaskThicknessParameters::event(QEvent* e) -{ - return TaskDressUpParameters::KeyEvent(e); -} - void TaskThicknessParameters::changeEvent(QEvent* e) { TaskBox::changeEvent(e); diff --git a/src/Mod/PartDesign/Gui/TaskThicknessParameters.h b/src/Mod/PartDesign/Gui/TaskThicknessParameters.h index 35c21940440e..408dd33c6952 100644 --- a/src/Mod/PartDesign/Gui/TaskThicknessParameters.h +++ b/src/Mod/PartDesign/Gui/TaskThicknessParameters.h @@ -63,7 +63,6 @@ private Q_SLOTS: protected: void setButtons(const selectionModes mode) override; - bool event(QEvent* e) override; void changeEvent(QEvent* e) override; void onSelectionChanged(const Gui::SelectionChanges& msg) override; From e299c46a947998282d61515047b936c9e9932c22 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Jul 2024 08:40:30 +0200 Subject: [PATCH 040/161] Part: move model check to separate function This is to avoid code duplication. --- src/Mod/Part/App/FeaturePartBoolean.cpp | 39 +++++++++++++++++-------- src/Mod/Part/App/FeaturePartCommon.cpp | 17 ++++------- src/Mod/Part/App/FeaturePartFuse.cpp | 18 +++++------- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 96a22f111550..22587b7ace45 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -30,6 +30,7 @@ #endif #include +#include #include #include "FeaturePartBoolean.h" @@ -39,6 +40,26 @@ using namespace Part; +namespace Part +{ +void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape) +{ + Base::Reference hGrp = App::GetApplication() + .GetUserParameter() + .GetGroup("BaseApp") + ->GetGroup("Preferences") + ->GetGroup("Mod/Part/Boolean"); + + if (hGrp->GetBool("CheckModel", true)) { + BRepCheck_Analyzer aChecker(shape); + if (!aChecker.IsValid()) { + throw Base::RuntimeError("Resulting shape is invalid"); + } + } +} + +} + PROPERTY_SOURCE_ABSTRACT(Part::Boolean, Part::Feature) @@ -118,18 +139,9 @@ App::DocumentObjectExecReturn* Boolean::execute() if (resShape.IsNull()) { return new App::DocumentObjectExecReturn("Resulting shape is null"); } - Base::Reference hGrp = App::GetApplication() - .GetUserParameter() - .GetGroup("BaseApp") - ->GetGroup("Preferences") - ->GetGroup("Mod/Part/Boolean"); - - if (hGrp->GetBool("CheckModel", true)) { - BRepCheck_Analyzer aChecker(resShape); - if (!aChecker.IsValid()) { - return new App::DocumentObjectExecReturn("Resulting shape is invalid"); - } - } + + throwIfInvalidIfCheckModel(resShape); + TopoShape res(0); res.makeElementShape(*mkBool, shapes, opCode()); if (this->Refine.getValue()) { @@ -139,6 +151,9 @@ App::DocumentObjectExecReturn* Boolean::execute() copyMaterial(base); return Part::Feature::execute(); } + catch (const Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } catch (...) { return new App::DocumentObjectExecReturn( "A fatal error occurred when running boolean operation"); diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index cd72d54b6858..008a946f0ae3 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -40,6 +40,11 @@ using namespace Part; +namespace Part +{ + extern void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape); +} + PROPERTY_SOURCE(Part::Common, Part::Boolean) @@ -101,17 +106,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute() throw Base::RuntimeError("Resulting shape is null"); } - Base::Reference hGrp = App::GetApplication() - .GetUserParameter() - .GetGroup("BaseApp") - ->GetGroup("Preferences") - ->GetGroup("Mod/Part/Boolean"); - if (hGrp->GetBool("CheckModel", false)) { - BRepCheck_Analyzer aChecker(res.getShape()); - if (!aChecker.IsValid()) { - return new App::DocumentObjectExecReturn("Resulting shape is invalid"); - } - } + throwIfInvalidIfCheckModel(res.getShape()); if (this->Refine.getValue()) { res = res.makeElementRefine(); diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index 19f3091c4e6c..3a41e7af129b 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -43,6 +43,11 @@ FC_LOG_LEVEL_INIT("Part",true,true); using namespace Part; +namespace Part +{ + extern void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape); +} + PROPERTY_SOURCE(Part::Fuse, Part::Boolean) @@ -151,17 +156,8 @@ App::DocumentObjectExecReturn *MultiFuse::execute() throw Base::RuntimeError("Resulting shape is null"); } - Base::Reference hGrp = App::GetApplication() - .GetUserParameter() - .GetGroup("BaseApp") - ->GetGroup("Preferences") - ->GetGroup("Mod/Part/Boolean"); - if (hGrp->GetBool("CheckModel", true)) { - BRepCheck_Analyzer aChecker(res.getShape()); - if (!aChecker.IsValid()) { - return new App::DocumentObjectExecReturn("Resulting shape is invalid"); - } - } + throwIfInvalidIfCheckModel(res.getShape()); + if (this->Refine.getValue()) { try { TopoDS_Shape oldShape = res.getShape(); From 0e0df5b92e6d92a57290708be77c2a1d8e834256 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Jul 2024 08:46:15 +0200 Subject: [PATCH 041/161] Part: move refine model parameter to separate function --- src/Mod/Part/App/FeaturePartBoolean.cpp | 12 ++++++++---- src/Mod/Part/App/FeaturePartCommon.cpp | 9 ++------- src/Mod/Part/App/FeaturePartFuse.cpp | 11 ++--------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 22587b7ace45..0104dbf3ce97 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -58,6 +58,13 @@ void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape) } } +bool getRefineModelParameter() +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); + return hGrp->GetBool("RefineModel", false); +} + } PROPERTY_SOURCE_ABSTRACT(Part::Boolean, Part::Feature) @@ -73,10 +80,7 @@ Boolean::Boolean() ADD_PROPERTY_TYPE(Refine,(0),"Boolean",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after this boolean operation"); - //init Refine property - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); - this->Refine.setValue(hGrp->GetBool("RefineModel", false)); + this->Refine.setValue(getRefineModelParameter()); } short Boolean::mustExecute() const diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 008a946f0ae3..1d2e052bb595 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -30,9 +30,6 @@ # include #endif -#include -#include - #include "FeaturePartCommon.h" #include "TopoShapeOpCode.h" #include "modelRefine.h" @@ -43,6 +40,7 @@ using namespace Part; namespace Part { extern void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape); + extern bool getRefineModelParameter(); } PROPERTY_SOURCE(Part::Common, Part::Boolean) @@ -76,10 +74,7 @@ MultiCommon::MultiCommon() ADD_PROPERTY_TYPE(Refine,(0),"Boolean",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after this boolean operation"); - //init Refine property - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); - this->Refine.setValue(hGrp->GetBool("RefineModel", false)); + this->Refine.setValue(getRefineModelParameter()); } short MultiCommon::mustExecute() const diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index 3a41e7af129b..183351696271 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -30,10 +30,6 @@ # include #endif -#include -#include -#include - #include "FeaturePartFuse.h" #include "TopoShape.h" #include "modelRefine.h" @@ -46,6 +42,7 @@ using namespace Part; namespace Part { extern void throwIfInvalidIfCheckModel(const TopoDS_Shape& shape); + extern bool getRefineModelParameter(); } PROPERTY_SOURCE(Part::Fuse, Part::Boolean) @@ -79,11 +76,7 @@ MultiFuse::MultiFuse() ADD_PROPERTY_TYPE(Refine,(0),"Boolean",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after this boolean operation"); - //init Refine property - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); - this->Refine.setValue(hGrp->GetBool("RefineModel", false)); - + this->Refine.setValue(getRefineModelParameter()); } short MultiFuse::mustExecute() const From 98fec525b098121755af4c69a3b170af3c71b3d5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 2 Jul 2024 10:08:50 +0200 Subject: [PATCH 042/161] PD: move refine model parameter to separate function --- src/Mod/PartDesign/App/Feature.cpp | 8 ++++++++ src/Mod/PartDesign/App/FeatureAddSub.cpp | 8 ++------ src/Mod/PartDesign/App/FeatureBoolean.cpp | 9 ++++----- src/Mod/PartDesign/App/FeatureTransformed.cpp | 8 ++------ src/Mod/PartDesign/App/ShapeBinder.cpp | 9 ++++++--- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Mod/PartDesign/App/Feature.cpp b/src/Mod/PartDesign/App/Feature.cpp index 060dad41bc36..a1992db815cd 100644 --- a/src/Mod/PartDesign/App/Feature.cpp +++ b/src/Mod/PartDesign/App/Feature.cpp @@ -49,6 +49,14 @@ FC_LOG_LEVEL_INIT("PartDesign", true, true) namespace PartDesign { +bool getPDRefineModelParameter() +{ + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); + return hGrp->GetBool("RefineModel", true); +} + +// ------------------------------------------------------------------------------------------------ PROPERTY_SOURCE(PartDesign::Feature,Part::Feature) diff --git a/src/Mod/PartDesign/App/FeatureAddSub.cpp b/src/Mod/PartDesign/App/FeatureAddSub.cpp index c0c8c9f8fd65..9cb955657f57 100644 --- a/src/Mod/PartDesign/App/FeatureAddSub.cpp +++ b/src/Mod/PartDesign/App/FeatureAddSub.cpp @@ -26,9 +26,7 @@ # include #endif -#include #include -#include #include #include "FeatureAddSub.h" @@ -39,6 +37,7 @@ using namespace PartDesign; namespace PartDesign { +extern bool getPDRefineModelParameter(); PROPERTY_SOURCE(PartDesign::FeatureAddSub, PartDesign::Feature) @@ -46,10 +45,7 @@ FeatureAddSub::FeatureAddSub() { ADD_PROPERTY(AddSubShape,(TopoDS_Shape())); ADD_PROPERTY_TYPE(Refine,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting"); - //init Refine property - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); - this->Refine.setValue(hGrp->GetBool("RefineModel", true)); + this->Refine.setValue(getPDRefineModelParameter()); } FeatureAddSub::Type FeatureAddSub::getAddSubType() diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index 59d0f617bfb6..af9a4f35d303 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -29,9 +29,7 @@ # include #endif -#include #include -#include #include #include @@ -44,6 +42,8 @@ using namespace PartDesign; namespace PartDesign { +extern bool getPDRefineModelParameter(); + PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::Boolean, PartDesign::Feature) const char* Boolean::TypeEnums[]= {"Fuse","Cut","Common",nullptr}; @@ -54,9 +54,8 @@ Boolean::Boolean() Type.setEnums(TypeEnums); ADD_PROPERTY_TYPE(Refine,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting"); - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); - this->Refine.setValue(hGrp->GetBool("RefineModel", true)); + this->Refine.setValue(getPDRefineModelParameter()); + ADD_PROPERTY_TYPE(UsePlacement,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Apply the placement of the second ( tool ) object"); this->UsePlacement.setValue(false); diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index bdec0481358a..b7f18afaaeb9 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -35,10 +35,8 @@ #include -#include #include #include -#include #include #include @@ -57,6 +55,7 @@ using namespace PartDesign; namespace PartDesign { +extern bool getPDRefineModelParameter(); PROPERTY_SOURCE(PartDesign::Transformed, PartDesign::Feature) @@ -79,10 +78,7 @@ Transformed::Transformed() (App::PropertyType)(App::Prop_None), "Refine shape (clean up redundant edges) after adding/subtracting"); - //init Refine property - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); - this->Refine.setValue(hGrp->GetBool("RefineModel", true)); + this->Refine.setValue(getPDRefineModelParameter()); } void Transformed::positionBySupport() diff --git a/src/Mod/PartDesign/App/ShapeBinder.cpp b/src/Mod/PartDesign/App/ShapeBinder.cpp index ca4a67cad8f2..41d99df9dea2 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.cpp +++ b/src/Mod/PartDesign/App/ShapeBinder.cpp @@ -51,6 +51,11 @@ FC_LOG_LEVEL_INIT("PartDesign",true,true) using namespace PartDesign; namespace sp = std::placeholders; +namespace PartDesign +{ +extern bool getPDRefineModelParameter(); +} + // ============================================================================ PROPERTY_SOURCE(PartDesign::ShapeBinder, Part::Feature) @@ -381,9 +386,7 @@ void SubShapeBinder::setupObject() { _Version.setValue(2); checkPropertyStatus(); - Base::Reference hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign"); - this->Refine.setValue(hGrp->GetBool("RefineModel", true)); + this->Refine.setValue(getPDRefineModelParameter()); } App::DocumentObject* SubShapeBinder::getSubObject(const char* subname, PyObject** pyObj, From 2137dbc8d0883641ebbabbfc3525116beb6da680 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 25 Sep 2024 19:09:24 +0200 Subject: [PATCH 043/161] Tests: Add unit test for PR #16576 --- tests/src/Mod/Part/App/PropertyTopoShape.cpp | 87 ++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/tests/src/Mod/Part/App/PropertyTopoShape.cpp b/tests/src/Mod/Part/App/PropertyTopoShape.cpp index e08435b75ae0..a6464c3b2541 100644 --- a/tests/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/tests/src/Mod/Part/App/PropertyTopoShape.cpp @@ -32,6 +32,75 @@ class PropertyTopoShapeTest: public ::testing::Test, public PartTestHelperClass void TearDown() override {} + std::string getDocumentXml() const + { + return R"x( + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)x"; + } + Common* _common = nullptr; // NOLINT Can't be private in a test framework }; @@ -182,3 +251,21 @@ TEST_F(PropertyTopoShapeTest, testPropertyShapeCachePyObj) Py_XDECREF(pyObjOut); Py_XDECREF(pyObjOutErased); } + +TEST_F(PropertyTopoShapeTest, testRestore) +{ + // Test case for https://github.com/FreeCAD/FreeCAD/pull/16576 + std::stringstream str(getDocumentXml()); + Base::XMLReader reader("Document.xml", str); + App::StringHasher hasher; + hasher.Restore(reader); + + Part::PropertyPartShape prop; + prop.Restore(reader); + + EXPECT_STREQ(reader.localName(), "ElementMap2"); + EXPECT_EQ(reader.level(), 5); + EXPECT_EQ(reader.getAttributeCount(), 1); + EXPECT_TRUE(reader.isValid()); + EXPECT_TRUE(reader.isEndOfElement()); +} From 6f23f01e509348a6755ad3c465a3d7ffd758ee03 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 28 Sep 2024 00:29:40 +0200 Subject: [PATCH 044/161] Tests: Add unit test for PR #16763 --- tests/src/App/Property.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/src/App/Property.cpp b/tests/src/App/Property.cpp index 9ab8aeffa6c1..528ca56f2fa1 100644 --- a/tests/src/App/Property.cpp +++ b/tests/src/App/Property.cpp @@ -1,6 +1,9 @@ #include #include "App/PropertyLinks.h" +#include +#include +#include TEST(PropertyLink, TestSetValues) { @@ -13,3 +16,27 @@ TEST(PropertyLink, TestSetValues) EXPECT_EQ(sub[0], "Sub1"); EXPECT_EQ(sub[1], "Sub2"); } + +TEST(PropertyFloatTest, testWriteRead) +{ +#if defined(FC_OS_LINUX) || defined(FC_OS_BSD) + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); // avoid rounding of floating point numbers +#endif + double value = 1.2345; + App::PropertyFloat prop; + prop.setValue(value); + Base::StringWriter writer; + prop.Save(writer); + + std::string str = "\n"; + str.append("\n"); + str.append(writer.getString()); + str.append("\n"); + + std::stringstream data(str); + Base::XMLReader reader("Document.xml", data); + App::PropertyFloat prop2; + prop2.Restore(reader); + EXPECT_DOUBLE_EQ(prop2.getValue(), value); +} From aea09d4a4536fc5e6dcf5606c4a55b2f99bea5c9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 22 Nov 2024 14:29:35 +0100 Subject: [PATCH 045/161] MSVC: Fix compiler warnings --- src/Gui/NavigationStyle.cpp | 2 +- src/Mod/PartDesign/App/FeatureExtrude.cpp | 2 +- src/Mod/Sketcher/App/SketchObject.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 44bd5858a29d..633b1c64c695 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -62,7 +62,7 @@ class FCSphereSheetProjector : public SbSphereSheetProjector { FreeTurntable }; - static constexpr float defaultSphereRadius = 0.8; + static constexpr float defaultSphereRadius = 0.8F; FCSphereSheetProjector(const SbSphere & sph, const SbBool orienttoeye = true) : SbSphereSheetProjector(sph, orienttoeye) diff --git a/src/Mod/PartDesign/App/FeatureExtrude.cpp b/src/Mod/PartDesign/App/FeatureExtrude.cpp index 9b3f9c6acf71..97f3ae3fec02 100644 --- a/src/Mod/PartDesign/App/FeatureExtrude.cpp +++ b/src/Mod/PartDesign/App/FeatureExtrude.cpp @@ -691,7 +691,7 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt TopoShape::PrismMode::None, true /*CheckUpToFaceLimits.getValue()*/); } - catch (Base::Exception& e) { + catch (Base::Exception&) { if (method == "UpToShape" && faceCount > 1){ return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP( "Exception", diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 0eaf99b327e3..eb346a71874c 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -265,7 +265,7 @@ App::DocumentObjectExecReturn* SketchObject::execute() rebuildExternalGeometry(); Constraints.acceptGeometry(getCompleteGeometry()); } - catch (const Base::Exception& e) { + catch (const Base::Exception&) { // 9/16/24: We used to clear the constraints here, but we no longer want to do that // as missing reference geometry is not considered an error while we sort out sketcher UI. // Base::Console().Error("%s\nClear constraints to external geometry\n", e.what()); From be1622176c7376a92eae9b866d7ad4247bdf69ab Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 19 Nov 2024 12:14:03 +0100 Subject: [PATCH 046/161] Core: Fix dangling pointer in SoFCUnifiedSelection::setSelection This fixes #17965: Measurement: Crash when clicking on COM label --- src/Gui/SoFCUnifiedSelection.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Gui/SoFCUnifiedSelection.cpp b/src/Gui/SoFCUnifiedSelection.cpp index 79d97c20d79e..719e384139ae 100644 --- a/src/Gui/SoFCUnifiedSelection.cpp +++ b/src/Gui/SoFCUnifiedSelection.cpp @@ -79,6 +79,7 @@ #include "SoFCUnifiedSelection.h" #include "Application.h" #include "Document.h" +#include "DocumentObserver.h" #include "MainWindow.h" #include "SoFCInteractiveElement.h" #include "SoFCSelectionAction.h" @@ -607,9 +608,16 @@ bool SoFCUnifiedSelection::setSelection(const std::vector &infos, bo return true; } else { + // Changing the selection may result in destroying this view provider. + // So, make sure that the object still exists afterwards (#17965) + ViewProviderWeakPtrT guard(vpd); getFullSubElementName(subName); bool ok = Gui::Selection().addSelection(docname, objname, subName.c_str(), pt[0], pt[1], pt[2], &sels); + if (guard.expired()) { + return false; + } + if (ok && mymode == OFF) { snprintf(buf, 512, "Selected: %s.%s.%s (%g, %g, %g)", docname, objname, info.element.c_str(), fabs(pt[0]) > 1e-7 ? pt[0] : 0.0, From 5e21dd3b37fb71ce7cccd8faad282ca55d13026e Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Fri, 4 Oct 2024 20:19:41 +0200 Subject: [PATCH 047/161] Delete src/Tools/generateTemplates/templateModuleGui.py the file is never used --- src/Tools/generateTemplates/templateModuleGui.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/Tools/generateTemplates/templateModuleGui.py diff --git a/src/Tools/generateTemplates/templateModuleGui.py b/src/Tools/generateTemplates/templateModuleGui.py deleted file mode 100644 index e6a244d22196..000000000000 --- a/src/Tools/generateTemplates/templateModuleGui.py +++ /dev/null @@ -1,10 +0,0 @@ -#! python -# -*- coding: utf-8 -*- -# (c) 2006 Juergen Riegel - -from . import template - - -class TemplateModuleGui(template.ModelTemplate): - def Generate(self): - print("Generate() needs to be implemented in a Template class!") From 2c1348fdc271948182e18b712fe0b23e84d92c05 Mon Sep 17 00:00:00 2001 From: haruka tsubota Date: Tue, 8 Oct 2024 17:07:45 +0900 Subject: [PATCH 048/161] Add help message about customizing BOM export file format in Assembly workbench --- src/Mod/Assembly/CommandCreateBom.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Mod/Assembly/CommandCreateBom.py b/src/Mod/Assembly/CommandCreateBom.py index a61acc159141..6b5a55621cc4 100644 --- a/src/Mod/Assembly/CommandCreateBom.py +++ b/src/Mod/Assembly/CommandCreateBom.py @@ -412,14 +412,26 @@ def showHelpDialog(self): ) + "\n" ) + export_title = QtWidgets.QLabel("" + translate("Assembly", "Export:") + "") + export_text = QtWidgets.QLabel( + " - " + + translate( + "Assembly", + "The exported file format can be customized in the Spreadsheet workbench preferences.", + ) + + "\n" + ) options_text.setWordWrap(True) columns_text.setWordWrap(True) + export_text.setWordWrap(True) layout.addWidget(options_title) layout.addWidget(options_text) layout.addWidget(columns_title) layout.addWidget(columns_text) + layout.addWidget(export_title) + layout.addWidget(export_text) help_dialog.setLayout(layout) help_dialog.setFixedWidth(500) From d2e407d09619ef41dca858c4f96f19dd09aeb216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Winkler?= Date: Fri, 22 Nov 2024 17:37:33 +0100 Subject: [PATCH 049/161] Improve/fix debian docker build (#17003) * fix paths following past renames * add missing dependencies * switch to debian:12 (bookworm) * patch opencascade to silence warnings --- tools/build/Docker/Dockerfile.Debian | 12 +++++++++++- tools/build/Docker/README.rst | 10 +++++----- tools/build/Docker/debian.sh | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/build/Docker/Dockerfile.Debian b/tools/build/Docker/Dockerfile.Debian index 5e67b62b7ef2..951abab64d5c 100644 --- a/tools/build/Docker/Dockerfile.Debian +++ b/tools/build/Docker/Dockerfile.Debian @@ -1,4 +1,4 @@ -FROM debian:bullseye +FROM debian:12 ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Etc/UTC @@ -12,6 +12,16 @@ RUN apt-get update && \ sh /tmp/debian.sh && \ mkdir /builds +# Debian 12 (bookworm) contains opencascade 7.6.x which contains deprecated constructs +# (inheriting from std::iterator) which have been fixed in 7.7.x +# lets bring the changes here to have less warnings during the build +# https://github.com/Open-Cascade-SAS/OCCT/commit/8af9bbd59aecf24c765e7ea0eeeb8c9dd5c1f8db + +RUN apt-get install curl --yes +RUN curl --silent --location --output-dir /usr/include/opencascade/ \ + --remote-name https://github.com/Open-Cascade-SAS/OCCT/raw/8af9bbd59aecf24c765e7ea0eeeb8c9dd5c1f8db/src/NCollection/NCollection_StlIterator.hxx --next \ + --remote-name https://github.com/Open-Cascade-SAS/OCCT/raw/8af9bbd59aecf24c765e7ea0eeeb8c9dd5c1f8db/src/OSD/OSD_Parallel.hxx + WORKDIR /builds VOLUME [ "/builds" ] diff --git a/tools/build/Docker/README.rst b/tools/build/Docker/README.rst index a1d668c000a8..479f74b76d19 100644 --- a/tools/build/Docker/README.rst +++ b/tools/build/Docker/README.rst @@ -73,7 +73,7 @@ The following commands are used to create and run a Arch Linux build environment .. code-block:: console - docker build --file tools/build/Dockerfile.Arch --tag freecad-arch + docker build --file tools/build/Docker/Dockerfile.Arch --tag freecad-arch docker run --rm --interactive --tty --volume $(pwd):/builds:z freecad-arch @@ -84,7 +84,7 @@ The following commands are used to create and run a Debian build environment. .. code-block:: console - docker build --file tools/build/Dockerfile.Debian --tag freecad-debian + docker build --file tools/build/Docker/Dockerfile.Debian --tag freecad-debian docker run --rm --interactive --tty --volume $(pwd):/builds:z freecad-debian @@ -95,7 +95,7 @@ The following commands are used to create and run a Fedora build environment. .. code-block:: console - docker build --file tools/build/Dockerfile.Fedora --tag freecad-fedora + docker build --file tools/build/Docker/Dockerfile.Fedora --tag freecad-fedora docker run --rm --interactive --tty --volume $(pwd):/builds:z freecad-fedora @@ -106,7 +106,7 @@ The following commands are used to create and run a Manjaro build environment. .. code-block:: console - docker build --file tools/build/Dockerfile.Manjaro --tag freecad-manjaro + docker build --file tools/build/Docker/Dockerfile.Manjaro --tag freecad-manjaro docker run --rm --interactive --tty --volume $(pwd):/builds:z freecad-manjaro @@ -118,7 +118,7 @@ The following commands are used to create and run a Ubuntu build environment. .. code-block:: console - docker build --file tools/build/Dockerfile.Ubuntu --tag freecad-ubuntu + docker build --file tools/build/Docker/Dockerfile.Ubuntu --tag freecad-ubuntu docker run --rm --interactive --tty --volume $(pwd):/builds:z freecad-ubuntu diff --git a/tools/build/Docker/debian.sh b/tools/build/Docker/debian.sh index 4418def8756f..e10542527fc5 100755 --- a/tools/build/Docker/debian.sh +++ b/tools/build/Docker/debian.sh @@ -12,4 +12,5 @@ apt-get install --no-install-recommends --yes build-essential cmake doxygen \ libvtk-dicom-dev libx11-dev libxerces-c-dev libxmu-dev libxmuu-dev \ libzipios++-dev netgen netgen-headers pyside2-tools python3-dev \ python3-matplotlib python3-pivy python3-ply python3-pyside2.qtsvg \ - python3-pyside2.qtuitools qtchooser qttools5-dev shiboken2 swig + python3-pyside2.qtuitools qtchooser qttools5-dev shiboken2 swig \ + python3-pyside2.qtnetwork libyaml-cpp-dev From 4bdb104bedc439bfbf90d96b0dc82a6dce3606ba Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 1 Oct 2024 15:02:47 +0200 Subject: [PATCH 050/161] BIM: Support for additions/subtractions in NativeIFC - fixes #16631 --- src/Mod/BIM/nativeifc/ifc_tools.py | 77 ++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/src/Mod/BIM/nativeifc/ifc_tools.py b/src/Mod/BIM/nativeifc/ifc_tools.py index be29177bfd76..af0cabbe51d2 100644 --- a/src/Mod/BIM/nativeifc/ifc_tools.py +++ b/src/Mod/BIM/nativeifc/ifc_tools.py @@ -1044,7 +1044,7 @@ def create_product(obj, parent, ifcfile, ifcclass=None): description = getattr(obj, "Description", None) if not ifcclass: ifcclass = get_ifctype(obj) - representation, placement = create_representation(obj, ifcfile) + representation, placement, shapetype = create_representation(obj, ifcfile) product = api_run("root.create_entity", ifcfile, ifc_class=ifcclass, name=name) set_attribute(ifcfile, product, "Description", description) set_attribute(ifcfile, product, "ObjectPlacement", placement) @@ -1052,7 +1052,26 @@ def create_product(obj, parent, ifcfile, ifcclass=None): # IfcProductDefinitionShape already and not an IfcShapeRepresentation # api_run("geometry.assign_representation", ifcfile, product=product, representation=representation) set_attribute(ifcfile, product, "Representation", representation) - # TODO treat subtractions/additions + # additions + if hasattr(obj,"Additions") and shapetype in ["extrusion","no shape"]: + for addobj in obj.Additions: + r2,p2,c2 = create_representation(addobj, ifcfile) + cl2 = get_ifctype(addobj) + addprod = api_run("root.create_entity", ifcfile, ifc_class=cl2, name=addobj.Label) + set_attribute(ifcfile, addprod, "Description", getattr(addobj, "Description", "")) + set_attribute(ifcfile, addprod, "ObjectPlacement", p2) + set_attribute(ifcfile, addprod, "Representation", r2) + create_relationship(None, addobj, product, addprod, ifcfile) + # subtractions + if hasattr(obj,"Subtractions") and shapetype in ["extrusion","no shape"]: + for subobj in obj.Subtractions: + r3,p3,c3 = create_representation(subobj, ifcfile) + cl3 = "IfcOpeningElement" + subprod = api_run("root.create_entity", ifcfile, ifc_class=cl3, name=subobj.Label) + set_attribute(ifcfile, subprod, "Description", getattr(subobj, "Description", "")) + set_attribute(ifcfile, subprod, "ObjectPlacement", p3) + set_attribute(ifcfile, subprod, "Representation", r3) + create_relationship(None, subobj, product, subprod, ifcfile) return product @@ -1078,7 +1097,7 @@ def create_representation(obj, ifcfile): representation, placement, shapetype = exportIFC.getRepresentation( ifcfile, context, obj, preferences=prefs ) - return representation, placement + return representation, placement, shapetype def get_ifctype(obj): @@ -1145,18 +1164,22 @@ def get_subvolume(obj): def create_relationship(old_obj, obj, parent, element, ifcfile): """Creates a relationship between an IFC object and a parent IFC object""" - parent_element = get_ifc_element(parent) + if isinstance(parent, FreeCAD.DocumentObject): + parent_element = get_ifc_element(parent) + else: + parent_element = parent # case 1: element inside spatiual structure if parent_element.is_a("IfcSpatialStructureElement") and element.is_a("IfcElement"): # first remove the FreeCAD object from any parent - for old_par in old_obj.InList: - if hasattr(old_par, "Group") and old_obj in old_par.Group: - old_par.Group = [o for o in old_par.Group if o != old_obj] - try: - api_run("spatial.unassign_container", ifcfile, products=[element]) - except: - # older version of IfcOpenShell - api_run("spatial.unassign_container", ifcfile, product=element) + if old_obj: + for old_par in old_obj.InList: + if hasattr(old_par, "Group") and old_obj in old_par.Group: + old_par.Group = [o for o in old_par.Group if o != old_obj] + try: + api_run("spatial.unassign_container", ifcfile, products=[element]) + except: + # older version of IfcOpenShell + api_run("spatial.unassign_container", ifcfile, product=element) if element.is_a("IfcOpeningElement"): uprel = api_run( "void.add_opening", @@ -1180,22 +1203,23 @@ def create_relationship(old_obj, obj, parent, element, ifcfile): product=element, relating_structure=parent_element, ) - # case 2: dooe/window inside element + # case 2: door/window inside element # https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/annex/annex-e/wall-with-opening-and-window.htm elif parent_element.is_a("IfcElement") and element.is_a() in [ "IfcDoor", "IfcWindow", ]: - tempface, tempobj = get_subvolume(old_obj) - if tempobj: - opening = create_product(tempobj, parent, ifcfile, "IfcOpeningElement") - old_obj.Document.removeObject(tempobj.Name) - if tempface: - old_obj.Document.removeObject(tempface.Name) - api_run( - "void.add_opening", ifcfile, opening=opening, element=parent_element - ) - api_run("void.add_filling", ifcfile, opening=opening, element=element) + if old_obj: + tempface, tempobj = get_subvolume(old_obj) + if tempobj: + opening = create_product(tempobj, parent, ifcfile, "IfcOpeningElement") + old_obj.Document.removeObject(tempobj.Name) + if tempface: + old_obj.Document.removeObject(tempface.Name) + api_run( + "void.add_opening", ifcfile, opening=opening, element=parent_element + ) + api_run("void.add_filling", ifcfile, opening=opening, element=element) # windows must also be part of a spatial container try: api_run("spatial.unassign_container", ifcfile, products=[element]) @@ -1236,6 +1260,11 @@ def create_relationship(old_obj, obj, parent, element, ifcfile): product=element, relating_object=container, ) + # case 4: void element + elif parent_element.is_a("IfcElement") and element.is_a("IfcOpeningElement"): + uprel = api_run( + "void.add_opening", ifcfile, opening=element, element=parent_element + ) # case 3: element aggregated inside other element else: try: @@ -1258,7 +1287,7 @@ def create_relationship(old_obj, obj, parent, element, ifcfile): product=element, relating_object=parent_element, ) - if hasattr(parent.Proxy, "addObject"): + if hasattr(parent, "Proxy") and hasattr(parent.Proxy, "addObject"): parent.Proxy.addObject(parent, obj) return uprel From 19fa91253fbcaae7d8786a0fc85d83e31d615bb7 Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Tue, 29 Oct 2024 23:22:41 +0100 Subject: [PATCH 051/161] Remove octal in expressions when there's a leading zero --- src/App/ExpressionParser.l | 2 +- src/App/lex.ExpressionParser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 4dce7e319dd4..49e6e3672cf7 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -340,7 +340,7 @@ EXPO [eE][-+]?[0-9]+ {DIGIT}*","{DIGIT}+{EXPO}? COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}+{EXPO} COUNTCHARS; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}+ { COUNTCHARS; - yylval.ivalue = strtoll( yytext, NULL, 0 ); + yylval.ivalue = strtoll( yytext, NULL, 10 ); if (yylval.ivalue == LLONG_MIN) throw Base::UnderflowError("Integer underflow"); else if (yylval.ivalue == LLONG_MAX) diff --git a/src/App/lex.ExpressionParser.c b/src/App/lex.ExpressionParser.c index 02d975762d2e..2916336b02ba 100644 --- a/src/App/lex.ExpressionParser.c +++ b/src/App/lex.ExpressionParser.c @@ -9572,7 +9572,7 @@ case 137: YY_RULE_SETUP #line 342 "ExpressionParser.l" { COUNTCHARS; - yylval.ivalue = strtoll( yytext, NULL, 0 ); + yylval.ivalue = strtoll( yytext, NULL, 10 ); if (yylval.ivalue == LLONG_MIN) throw Base::UnderflowError("Integer underflow"); else if (yylval.ivalue == LLONG_MAX) From 73f3cd9f953e8836b3b97f7fdbdaf685192e673f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 15 Oct 2024 11:23:34 +0200 Subject: [PATCH 052/161] BIM: Only dusplay context menu items when in BIM WB - fixes #17043 --- src/Mod/BIM/ArchAxis.py | 2 ++ src/Mod/BIM/ArchAxisSystem.py | 2 ++ src/Mod/BIM/ArchBuilding.py | 2 ++ src/Mod/BIM/ArchBuildingPart.py | 3 ++- src/Mod/BIM/ArchComponent.py | 2 ++ src/Mod/BIM/ArchFloor.py | 2 ++ src/Mod/BIM/ArchGrid.py | 2 ++ src/Mod/BIM/ArchIFCView.py | 2 ++ src/Mod/BIM/ArchMaterial.py | 6 ++++++ src/Mod/BIM/ArchReference.py | 3 +++ src/Mod/BIM/ArchSchedule.py | 4 ++++ src/Mod/BIM/ArchSectionPlane.py | 3 +++ src/Mod/BIM/ArchSite.py | 4 ++++ src/Mod/BIM/ArchWall.py | 4 ++++ src/Mod/BIM/ArchWindow.py | 4 ++++ src/Mod/BIM/nativeifc/ifc_viewproviders.py | 9 +++++++++ 16 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Mod/BIM/ArchAxis.py b/src/Mod/BIM/ArchAxis.py index 289d915fb0de..e5918bfa8ae3 100644 --- a/src/Mod/BIM/ArchAxis.py +++ b/src/Mod/BIM/ArchAxis.py @@ -578,6 +578,8 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchAxisSystem.py b/src/Mod/BIM/ArchAxisSystem.py index 3ea935fa667f..df12fbb93dac 100644 --- a/src/Mod/BIM/ArchAxisSystem.py +++ b/src/Mod/BIM/ArchAxisSystem.py @@ -200,6 +200,8 @@ def doubleClicked(self, vobj): self.edit() def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchBuilding.py b/src/Mod/BIM/ArchBuilding.py index 8231f81a34d5..64bba1ebb269 100644 --- a/src/Mod/BIM/ArchBuilding.py +++ b/src/Mod/BIM/ArchBuilding.py @@ -305,6 +305,8 @@ def getIcon(self): def setupContextMenu(self,vobj,menu): from PySide import QtCore,QtGui import Arch_rc + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return action1 = QtGui.QAction(QtGui.QIcon(":/icons/Arch_BuildingPart.svg"),"Convert to BuildingPart",menu) QtCore.QObject.connect(action1,QtCore.SIGNAL("triggered()"),self.convertToBuildingPart) menu.addAction(action1) diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index 0b128b96856d..5b08217687b8 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -803,7 +803,8 @@ def unsetEdit(self, vobj, mode): def setupContextMenu(self, vobj, menu): from PySide import QtCore, QtGui import Draft_rc - + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return if (not hasattr(vobj,"DoubleClickActivates")) or vobj.DoubleClickActivates: if FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch") == self.Object: menuTxt = translate("Arch", "Deactivate") diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index 9354cd58f58e..f4dd0da94593 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -1498,6 +1498,8 @@ def setupContextMenu(self, vobj, menu): The context menu already assembled prior to this method being called. """ + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return self.contextMenuAddEdit(menu) self.contextMenuAddToggleSubcomponents(menu) diff --git a/src/Mod/BIM/ArchFloor.py b/src/Mod/BIM/ArchFloor.py index 57284f6d6cf9..70d2c9a673c2 100644 --- a/src/Mod/BIM/ArchFloor.py +++ b/src/Mod/BIM/ArchFloor.py @@ -399,6 +399,8 @@ def setupContextMenu(self,vobj,menu): from PySide import QtCore,QtGui import Arch_rc + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return action1 = QtGui.QAction(QtGui.QIcon(":/icons/Arch_BuildingPart.svg"),"Convert to BuildingPart",menu) QtCore.QObject.connect(action1,QtCore.SIGNAL("triggered()"),self.convertToBuildingPart) menu.addAction(action1) diff --git a/src/Mod/BIM/ArchGrid.py b/src/Mod/BIM/ArchGrid.py index c8e18ca0de6b..dd14d12c5fa9 100644 --- a/src/Mod/BIM/ArchGrid.py +++ b/src/Mod/BIM/ArchGrid.py @@ -282,6 +282,8 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchIFCView.py b/src/Mod/BIM/ArchIFCView.py index b873f4423bb1..47325a2cd5f1 100644 --- a/src/Mod/BIM/ArchIFCView.py +++ b/src/Mod/BIM/ArchIFCView.py @@ -53,6 +53,8 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchMaterial.py b/src/Mod/BIM/ArchMaterial.py index 0c1a1262344f..30b0be4c364f 100644 --- a/src/Mod/BIM/ArchMaterial.py +++ b/src/Mod/BIM/ArchMaterial.py @@ -84,6 +84,8 @@ def attach(self,vobj): self.Object = vobj.Object def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionMergeByName = QtGui.QAction(QtGui.QIcon(":/icons/Arch_Material_Group.svg"), translate("Arch", "Merge duplicates"), menu) @@ -360,6 +362,8 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) actionEdit.triggered.connect(self.edit) @@ -660,6 +664,8 @@ def doubleClicked(self,vobj): self.edit() def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) actionEdit.triggered.connect(self.edit) diff --git a/src/Mod/BIM/ArchReference.py b/src/Mod/BIM/ArchReference.py index ef51cc933a36..f09b8fd101e1 100644 --- a/src/Mod/BIM/ArchReference.py +++ b/src/Mod/BIM/ArchReference.py @@ -649,6 +649,9 @@ def unsetEdit(self, vobj, mode): def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index eed79ea454b6..720dcb04410c 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -429,6 +429,10 @@ def doubleClicked(self, vobj): self.edit() def setupContextMenu(self, vobj, menu): + + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index bdb149cb60fa..d30f0dab4a04 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -1135,6 +1135,9 @@ def doubleClicked(self, vobj): self.edit() def setupContextMenu(self, vobj, menu): + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchSite.py b/src/Mod/BIM/ArchSite.py index 64eb439db6a0..4c51e0945836 100644 --- a/src/Mod/BIM/ArchSite.py +++ b/src/Mod/BIM/ArchSite.py @@ -855,6 +855,10 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + actionEdit = QtGui.QAction(translate("Arch", "Edit"), menu) QtCore.QObject.connect(actionEdit, diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index c9b649941403..c0d617cc2940 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -1327,6 +1327,10 @@ def setDisplayMode(self,mode): return ArchComponent.ViewProviderComponent.setDisplayMode(self,mode) def setupContextMenu(self, vobj, menu): + + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + super().contextMenuAddEdit(menu) actionFlipDirection = QtGui.QAction(QtGui.QIcon(":/icons/Arch_Wall_Tree.svg"), diff --git a/src/Mod/BIM/ArchWindow.py b/src/Mod/BIM/ArchWindow.py index 75d1cc83ea8e..4485baea239c 100644 --- a/src/Mod/BIM/ArchWindow.py +++ b/src/Mod/BIM/ArchWindow.py @@ -817,6 +817,10 @@ def unsetEdit(self, vobj, mode): return True def setupContextMenu(self, vobj, menu): + + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + hingeIdxs = self.getHingeEdgeIndices() super().contextMenuAddEdit(menu) diff --git a/src/Mod/BIM/nativeifc/ifc_viewproviders.py b/src/Mod/BIM/nativeifc/ifc_viewproviders.py index 697323700fa7..2284c0bb1f98 100644 --- a/src/Mod/BIM/nativeifc/ifc_viewproviders.py +++ b/src/Mod/BIM/nativeifc/ifc_viewproviders.py @@ -97,6 +97,9 @@ def setupContextMenu(self, vobj, menu): from nativeifc import ifc_materials from PySide import QtCore, QtGui # lazy import + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + icon = QtGui.QIcon(":/icons/IFC.svg") element = ifc_tools.get_ifc_element(vobj.Object) ifc_menu = None @@ -404,6 +407,9 @@ def setupContextMenu(self, vobj, menu): from PySide import QtCore, QtGui # lazy import + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + ifc_menu = super().setupContextMenu(vobj, menu) if not ifc_menu: ifc_menu = menu @@ -584,6 +590,9 @@ def setupContextMenu(self, vobj, menu): from nativeifc import ifc_psets from PySide import QtCore, QtGui # lazy import + if FreeCADGui.activeWorkbench().name() != 'BIMWorkbench': + return + icon = QtGui.QIcon(":/icons/IFC.svg") if ifc_psets.has_psets(self.Object): action_props = QtGui.QAction(icon, "Expand property sets", menu) From d8286158b0cab2d02d37fb54c9b8135f15d43127 Mon Sep 17 00:00:00 2001 From: mwganson Date: Tue, 15 Oct 2024 00:51:39 +0000 Subject: [PATCH 053/161] [PartDesign] change claimChildren() function to include all profile objects except for other Part Design features --- src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp b/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp index aa5c0827fdd7..e1a2d9bef923 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderSketchBased.cpp @@ -43,7 +43,7 @@ ViewProviderSketchBased::~ViewProviderSketchBased() = default; std::vector ViewProviderSketchBased::claimChildren() const { std::vector temp; App::DocumentObject* sketch = static_cast(getObject())->Profile.getValue(); - if (sketch && sketch->isDerivedFrom(Part::Part2DObject::getClassTypeId())) + if (sketch && !sketch->isDerivedFrom(PartDesign::Feature::getClassTypeId())) temp.push_back(sketch); return temp; From 841a10f2e00843f06ec9052024438f6af3541fb4 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Tue, 22 Oct 2024 20:34:24 +0200 Subject: [PATCH 054/161] Clean FindKDL.cmake update orocos version used by oldest supported focal fossa clean cmake --- cMake/FindKDL.cmake | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cMake/FindKDL.cmake b/cMake/FindKDL.cmake index 65bd9ddf26e5..0bc567329c8c 100644 --- a/cMake/FindKDL.cmake +++ b/cMake/FindKDL.cmake @@ -12,7 +12,7 @@ IF ( CMAKE_PKGCONFIG_EXECUTABLE ) SET(ENV{PKG_CONFIG_PATH} "${KDL_INSTALL}/lib/pkgconfig/") MESSAGE( "Looking for KDL in: ${KDL_INSTALL}") - PKGCONFIG( "orocos-kdl >= 0.99" KDL_FOUND KDL_INCLUDE_DIRS KDL_DEFINES KDL_LINK_DIRS KDL_LIBS ) + PKGCONFIG( "orocos-kdl >= 1.4.0" KDL_FOUND KDL_INCLUDE_DIRS KDL_DEFINES KDL_LINK_DIRS KDL_LIBS ) IF( KDL_FOUND ) MESSAGE(" Includes in: ${KDL_INCLUDE_DIRS}") @@ -22,13 +22,10 @@ IF ( CMAKE_PKGCONFIG_EXECUTABLE ) INCLUDE_DIRECTORIES( ${KDL_INCLUDE_DIRS} ) LINK_DIRECTORIES( ${KDL_LINK_DIRS}) - #OROCOS_PKGCONFIG_INCPATH("${KDLTK_INCLUDE_DIRS}") - #OROCOS_PKGCONFIG_LIBS("${KDL_LIBS}") - #OROCOS_PKGCONFIG_LIBPATH("${KDL_LINK_DIRS}") SET(ENV{PKG_CONFIG_PATH} "${KDL_INSTALL}/lib/pkgconfig/:${OROCOS_INSTALL}/lib/pkgconfig") MESSAGE( "Looking for KDL Toolkit in: ${PKG_CONFIG_PATH}") - PKGCONFIG( "orocos-kdltk-${OROCOS_TARGET} >= 0.99" KDLTK_FOUND KDLTK_INCLUDE_DIRS KDLTK_DEFINES KDLTK_LINK_DIRS KDLTK_LIBS ) + PKGCONFIG( "orocos-kdltk-${OROCOS_TARGET} >= 1.4.0" KDLTK_FOUND KDLTK_INCLUDE_DIRS KDLTK_DEFINES KDLTK_LINK_DIRS KDLTK_LIBS ) IF(KDLTK_FOUND) INCLUDE_DIRECTORIES( ${KDLTK_INCLUDE_DIRS} ) LINK_DIRECTORIES( ${KDLTK_LINK_DIRS}) @@ -38,7 +35,7 @@ IF ( CMAKE_PKGCONFIG_EXECUTABLE ) IF(CORBA_ENABLED) SET(ENV{PKG_CONFIG_PATH} "${KDL_INSTALL}/lib/pkgconfig/:${OROCOS_INSTALL}/lib/pkgconfig") MESSAGE("Looking for KDL Toolkit CORBA extension in ${PKG_CONFIG_PATH}") - PKGCONFIG( "orocos-kdltk-corba-${OROCOS_TARGET} >= 0.99" KDLTKCORBA_FOUND KDLTKCORBA_INCLUDE_DIRS KDLTKCORBA_DEFINES KDLTKCORBA_LINK_DIRS KDLTKCORBA_LIBS ) + PKGCONFIG( "orocos-kdltk-corba-${OROCOS_TARGET} >= 1.4.0" KDLTKCORBA_FOUND KDLTKCORBA_INCLUDE_DIRS KDLTKCORBA_DEFINES KDLTKCORBA_LINK_DIRS KDLTKCORBA_LIBS ) IF(KDLTKCORBA_FOUND) INCLUDE_DIRECTORIES( ${KDLTKCORBA_INCLUDE_DIRS} ) LINK_DIRECTORIES( ${KDLTKCORBA_LINK_DIRS}) From 28282e680039be67af065c10e849fc45295fd06f Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 27 Oct 2024 14:08:26 +0100 Subject: [PATCH 055/161] PD: Cleanup code of TaskRevolutionParameters --- .../Gui/TaskRevolutionParameters.cpp | 158 ++++++++++-------- .../PartDesign/Gui/TaskRevolutionParameters.h | 26 +-- 2 files changed, 102 insertions(+), 82 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index 8e2a1bc58823..9fb29e7f2857 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -40,6 +40,7 @@ #include "ui_TaskRevolutionParameters.h" #include "TaskRevolutionParameters.h" #include "ViewProviderGroove.h" +#include "ViewProviderRevolution.h" #include "ReferenceSelection.h" using namespace PartDesignGui; @@ -47,12 +48,15 @@ using namespace Gui; /* TRANSLATOR PartDesignGui::TaskRevolutionParameters */ -TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* RevolutionView, const char* pixname, QString title, QWidget *parent) - : TaskSketchBasedParameters(RevolutionView, parent, pixname, title), - ui(new Ui_TaskRevolutionParameters), - proxy(new QWidget(this)), - selectionFace(false), - isGroove(false) +TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* RevolutionView, + const char* pixname, + const QString& title, + QWidget *parent) + : TaskSketchBasedParameters(RevolutionView, parent, pixname, title) + , ui(new Ui_TaskRevolutionParameters) + , proxy(new QWidget(this)) + , selectionFace(false) + , isGroove(false) { // we need a separate container widget to add all controls to ui->setupUi(proxy); @@ -94,18 +98,27 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* setFocus(); // show the parts coordinate system axis for selection - PartDesign::Body * body = PartDesign::Body::findBodyOf(getObject()); - if (body) { - try { - App::Origin *origin = body->getOrigin(); - auto *vpOrigin = static_cast( - Gui::Application::Instance->getViewProvider(origin)); + try { + if (auto vpOrigin = getOriginView()) { vpOrigin->setTemporaryVisibility(true, false); } - catch (const Base::Exception &ex) { - ex.ReportException(); - } + } + catch (const Base::Exception &ex) { + ex.ReportException(); + } +} + +Gui::ViewProviderOrigin* TaskRevolutionParameters::getOriginView() const +{ + // show the parts coordinate system axis for selection + PartDesign::Body * body = PartDesign::Body::findBodyOf(getObject()); + if (body) { + App::Origin *origin = body->getOrigin(); + return dynamic_cast( + Gui::Application::Instance->getViewProvider(origin)); } + + return nullptr; } void TaskRevolutionParameters::setupDialog() @@ -123,8 +136,9 @@ void TaskRevolutionParameters::setupDialog() int faceId = -1; if (obj && !subStrings.empty()) { upToFace = subStrings.front(); - if (upToFace.compare(0, 4, "Face") == 0) + if (upToFace.compare(0, 4, "Face") == 0) { faceId = std::atoi(&upToFace[4]); + } } // Set object labels @@ -154,7 +168,7 @@ void TaskRevolutionParameters::setupDialog() ui->revolveAngle2->setMaximum(propAngle2->getMaximum()); ui->revolveAngle2->setMinimum(propAngle2->getMinimum()); - index = rev->Type.getValue(); + index = int(rev->Type.getValue()); } else { auto rev = getObject(); @@ -162,7 +176,7 @@ void TaskRevolutionParameters::setupDialog() ui->revolveAngle2->setMaximum(propAngle2->getMaximum()); ui->revolveAngle2->setMinimum(propAngle2->getMinimum()); - index = rev->Type.getValue(); + index = int(rev->Type.getValue()); } translateModeList(index); @@ -188,8 +202,10 @@ void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) { Base::StateLocker lock(getUpdateBlockRef(), true); - if (axesInList.empty()) - forceRefill = true;//not filled yet, full refill + if (axesInList.empty()) { + // not filled yet, full refill + forceRefill = true; + } if (forceRefill) { ui->axis->clear(); @@ -234,31 +250,34 @@ void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) App::DocumentObject* ax = propReferenceAxis->getValue(); const std::vector &subList = propReferenceAxis->getSubValues(); for (size_t i = 0; i < axesInList.size(); i++) { - if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) - indexOfCurrent = i; + if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) { + indexOfCurrent = int(i); + } } if (indexOfCurrent == -1 && ax) { assert(subList.size() <= 1); std::string sub; - if (!subList.empty()) + if (!subList.empty()) { sub = subList[0]; + } addAxisToCombo(ax, sub, getRefStr(ax, subList)); - indexOfCurrent = axesInList.size()-1; + indexOfCurrent = int(axesInList.size()) - 1; } //highlight current. - if (indexOfCurrent != -1) + if (indexOfCurrent != -1) { ui->axis->setCurrentIndex(indexOfCurrent); + } } void TaskRevolutionParameters::addAxisToCombo(App::DocumentObject* linkObj, - std::string linkSubname, - QString itemText) + const std::string& linkSubname, + const QString& itemText) { this->ui->axis->addItem(itemText); this->axesInList.emplace_back(new App::PropertyLinkSub()); App::PropertyLinkSub &lnk = *(axesInList[axesInList.size()-1]); - lnk.setValue(linkObj,std::vector(1,linkSubname)); + lnk.setValue(linkObj, std::vector(1, linkSubname)); } void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod mode) @@ -286,9 +305,6 @@ void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod isMidplaneVisible = true; isReversedEnabled = !ui->checkBoxMidplane->isChecked(); } - else if (mode == PartDesign::Revolution::RevolMethod::ToLast && !isGroove) { - isReversedEnabled = true; - } else if (mode == PartDesign::Revolution::RevolMethod::ToFirst) { isReversedEnabled = true; } @@ -297,8 +313,9 @@ void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod isFaceEditEnabled = true; QMetaObject::invokeMethod(ui->lineFaceName, "setFocus", Qt::QueuedConnection); // Go into reference selection mode if no face has been selected yet - if (ui->lineFaceName->property("FeatureName").isNull()) + if (ui->lineFaceName->property("FeatureName").isNull()) { ui->buttonFace->setChecked(true); + } } else if (mode == PartDesign::Revolution::RevolMethod::TwoDimensions) { isRevolveAngleVisible = true; @@ -330,6 +347,7 @@ void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod void TaskRevolutionParameters::connectSignals() { + // clang-format off connect(ui->revolveAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskRevolutionParameters::onAngleChanged); connect(ui->revolveAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -348,12 +366,15 @@ void TaskRevolutionParameters::connectSignals() this, &TaskRevolutionParameters::onButtonFace); connect(ui->lineFaceName, &QLineEdit::textEdited, this, &TaskRevolutionParameters::onFaceName); + // clang-format on } void TaskRevolutionParameters::updateUI(int index) { - if (isUpdateBlocked()) + if (isUpdateBlocked()) { return; + } + Base::StateLocker lock(getUpdateBlockRef(), true); fillAxisCombo(); setCheckboxes(static_cast(index)); @@ -380,7 +401,7 @@ void TaskRevolutionParameters::onSelectionChanged(const Gui::SelectionChanges& m else { exitSelectionMode(); std::vector axis; - App::DocumentObject* selObj; + App::DocumentObject* selObj {}; if (getReferencedSelection(getObject(), msg, selObj, axis) && selObj) { propReferenceAxis->setValue(selObj, axis); @@ -394,7 +415,7 @@ void TaskRevolutionParameters::onSelectionChanged(const Gui::SelectionChanges& m } } -void TaskRevolutionParameters::onButtonFace(const bool pressed) +void TaskRevolutionParameters::onButtonFace(bool pressed) { // to distinguish that this is NOT the axis selection selectionFace = pressed; @@ -443,8 +464,7 @@ void TaskRevolutionParameters::translateFaceName() if (ok) { ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") - .arg(parts[0]) - .arg(tr("Face")) + .arg(parts[0], tr("Face")) .arg(faceId)); } else { @@ -453,7 +473,7 @@ void TaskRevolutionParameters::translateFaceName() } } -QString TaskRevolutionParameters::getFaceName(void) const +QString TaskRevolutionParameters::getFaceName() const { QVariant featureName = ui->lineFaceName->property("FeatureName"); if (featureName.isValid()) { @@ -494,18 +514,21 @@ void TaskRevolutionParameters::onAngle2Changed(double len) void TaskRevolutionParameters::onAxisChanged(int num) { - if (isUpdateBlocked()) + if (isUpdateBlocked()) { return; + } auto pcRevolution = getObject(); - if (axesInList.empty()) + if (axesInList.empty()) { return; + } App::DocumentObject *oldRefAxis = propReferenceAxis->getValue(); std::vector oldSubRefAxis = propReferenceAxis->getSubValues(); std::string oldRefName; - if (!oldSubRefAxis.empty()) + if (!oldSubRefAxis.empty()) { oldRefName = oldSubRefAxis.front(); + } App::PropertyLinkSub &lnk = *(axesInList[num]); if (!lnk.getValue()) { @@ -529,17 +552,20 @@ void TaskRevolutionParameters::onAxisChanged(int num) App::DocumentObject *newRefAxis = propReferenceAxis->getValue(); const std::vector &newSubRefAxis = propReferenceAxis->getSubValues(); std::string newRefName; - if (!newSubRefAxis.empty()) + if (!newSubRefAxis.empty()) { newRefName = newSubRefAxis.front(); + } if (oldRefAxis != newRefAxis || oldSubRefAxis.size() != newSubRefAxis.size() || oldRefName != newRefName) { bool reversed = propReversed->getValue(); - if (pcRevolution->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) + if (pcRevolution->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) { reversed = static_cast(pcRevolution)->suggestReversed(); - if (pcRevolution->isDerivedFrom(PartDesign::Groove::getClassTypeId())) + } + if (pcRevolution->isDerivedFrom(PartDesign::Groove::getClassTypeId())) { reversed = static_cast(pcRevolution)->suggestReversed(); + } if (reversed != propReversed->getValue()) { propReversed->setValue(reversed); @@ -574,30 +600,24 @@ void TaskRevolutionParameters::onReversed(bool on) void TaskRevolutionParameters::onModeChanged(int index) { - App::PropertyEnumeration* pcType {}; - if (!isGroove) - pcType = &(getObject()->Type); - else - pcType = &(getObject()->Type); + App::PropertyEnumeration* propEnum = isGroove ? &(getObject()->Type) + : &(getObject()->Type); switch (static_cast(index)) { case PartDesign::Revolution::RevolMethod::Dimension: - pcType->setValue("Angle"); + propEnum->setValue("Angle"); break; case PartDesign::Revolution::RevolMethod::ToLast: - if (!isGroove) - pcType->setValue("UpToLast"); - else - pcType->setValue("ThroughAll"); + propEnum->setValue(isGroove ? "ThroughAll" : "UpToLast"); break; case PartDesign::Revolution::RevolMethod::ToFirst: - pcType->setValue("UpToFirst"); + propEnum->setValue("UpToFirst"); break; case PartDesign::Revolution::RevolMethod::ToFace: - pcType->setValue("UpToFace"); + propEnum->setValue("UpToFace"); break; case PartDesign::Revolution::RevolMethod::TwoDimensions: - pcType->setValue("TwoAngles"); + propEnum->setValue("TwoAngles"); break; } @@ -616,15 +636,14 @@ void TaskRevolutionParameters::getReferenceAxis(App::DocumentObject*& obj, std:: if (!lnk.getValue()) { throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet"); } - else { - auto revolution = getObject(); - if (!revolution->getDocument()->isIn(lnk.getValue())){ - throw Base::RuntimeError("Object was deleted"); - } - obj = lnk.getValue(); - sub = lnk.getSubValues(); + auto revolution = getObject(); + if (!revolution->getDocument()->isIn(lnk.getValue())){ + throw Base::RuntimeError("Object was deleted"); } + + obj = lnk.getValue(); + sub = lnk.getSubValues(); } bool TaskRevolutionParameters::getMidplane() const @@ -639,14 +658,9 @@ bool TaskRevolutionParameters::getReversed() const TaskRevolutionParameters::~TaskRevolutionParameters() { + //hide the parts coordinate system axis for selection try { - //hide the parts coordinate system axis for selection - auto obj = getObject(); - PartDesign::Body * body = obj ? PartDesign::Body::findBodyOf(obj) : nullptr; - if (body) { - App::Origin *origin = body->getOrigin(); - ViewProviderOrigin* vpOrigin; - vpOrigin = static_cast(Gui::Application::Instance->getViewProvider(origin)); + if (auto vpOrigin = getOriginView()) { vpOrigin->resetTemporaryVisibility(); } } @@ -674,7 +688,7 @@ void TaskRevolutionParameters::apply() ui->revolveAngle->apply(); ui->revolveAngle2->apply(); std::vector sub; - App::DocumentObject* obj; + App::DocumentObject* obj {}; getReferenceAxis(obj, sub); std::string axis = buildLinkSingleSubPythonStr(obj, sub); auto tobj = getObject(); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h index 3bc9066796e0..87df41a7c5ef 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h @@ -26,8 +26,6 @@ #include #include #include "TaskSketchBasedParameters.h" -#include "ViewProviderRevolution.h" -#include "ViewProviderGroove.h" class Ui_TaskRevolutionParameters; @@ -38,19 +36,22 @@ class Property; namespace Gui { class ViewProvider; +class ViewProviderOrigin; } namespace PartDesignGui { +class ViewProviderRevolution; +class ViewProviderGroove; class TaskRevolutionParameters : public TaskSketchBasedParameters { Q_OBJECT public: - explicit TaskRevolutionParameters(ViewProvider* RevolutionView, - const char *pixname, - QString title = tr("Revolution parameters"), - QWidget* parent = nullptr); + TaskRevolutionParameters(ViewProvider* RevolutionView, + const char *pixname, + const QString& title, + QWidget* parent = nullptr); ~TaskRevolutionParameters() override; void apply() override; @@ -63,7 +64,9 @@ class TaskRevolutionParameters : public TaskSketchBasedParameters * list (if necessary), and selected. If the list is empty, it will be refilled anyway. */ void fillAxisCombo(bool forceRefill = false); - void addAxisToCombo(App::DocumentObject *linkObj, std::string linkSubname, QString itemText); + void addAxisToCombo(App::DocumentObject *linkObj, + const std::string& linkSubname, + const QString& itemText); private Q_SLOTS: void onAngleChanged(double); @@ -72,7 +75,7 @@ private Q_SLOTS: void onMidplane(bool); void onReversed(bool); void onModeChanged(int); - void onButtonFace(const bool pressed = true); + void onButtonFace(bool pressed = true); void onFaceName(const QString& text); protected: @@ -82,9 +85,10 @@ private Q_SLOTS: bool getMidplane() const; bool getReversed() const; QString getFaceName() const; - void setupDialog(void); + void setupDialog(); void setCheckboxes(PartDesign::Revolution::RevolMethod mode); +private: //mirrors of revolution's or groove's properties //should have been done by inheriting revolution and groove from common class... App::PropertyAngle* propAngle; @@ -101,6 +105,7 @@ private Q_SLOTS: // TODO: This is common with extrude. Maybe send to superclass. void translateFaceName(); void clearFaceName(); + Gui::ViewProviderOrigin* getOriginView() const; private: std::unique_ptr ui; @@ -119,7 +124,6 @@ private Q_SLOTS: std::vector> axesInList; }; -/// simulation dialog for the TaskView class TaskDlgRevolutionParameters : public TaskDlgSketchBasedParameters { Q_OBJECT @@ -127,6 +131,7 @@ class TaskDlgRevolutionParameters : public TaskDlgSketchBasedParameters public: explicit TaskDlgRevolutionParameters(PartDesignGui::ViewProviderRevolution *RevolutionView); }; + class TaskDlgGrooveParameters : public TaskDlgSketchBasedParameters { Q_OBJECT @@ -134,6 +139,7 @@ class TaskDlgGrooveParameters : public TaskDlgSketchBasedParameters public: explicit TaskDlgGrooveParameters(PartDesignGui::ViewProviderGroove *GrooveView); }; + } //namespace PartDesignGui #endif // GUI_TASKVIEW_TASKAPPERANCE_H From e63c335e057a0cc1c11aa1782bf31474e75bb4f4 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Fri, 22 Nov 2024 18:00:19 +0100 Subject: [PATCH 056/161] Gui: Improve localization support in VarSet dialog (#17480) * Gui: Improve localization support in VarSet dialog * Gui: Adopt QObject translate This is not the ideal implementation but for the 1.0 release this is currently the better option. A separate issue has been filed for post 1.0 in https://github.com/FreeCAD/FreeCAD/issues/17510 that also covers the `DlgAddProperty`. --- src/Gui/DlgAddPropertyVarSet.cpp | 18 +++++++++++++++--- src/Gui/DlgAddPropertyVarSet.h | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Gui/DlgAddPropertyVarSet.cpp b/src/Gui/DlgAddPropertyVarSet.cpp index 47564c21b69c..b1ca96d634b1 100644 --- a/src/Gui/DlgAddPropertyVarSet.cpp +++ b/src/Gui/DlgAddPropertyVarSet.cpp @@ -174,9 +174,7 @@ void DlgAddPropertyVarSet::initializeWidgets(ViewProviderVarSet* viewProvider) connLineEditNameTextChanged = connect(ui->lineEditName, &QLineEdit::textChanged, this, &DlgAddPropertyVarSet::onNamePropertyChanged); - std::string title = "Add a property to " + varSet->getFullName(); - setWindowTitle(QString::fromStdString(title)); - + setTitle(); setOkEnabled(false); ui->lineEditName->setFocus(); @@ -188,6 +186,11 @@ void DlgAddPropertyVarSet::initializeWidgets(ViewProviderVarSet* viewProvider) // printFocusChain(ui->lineEditName); } +void DlgAddPropertyVarSet::setTitle() +{ + setWindowTitle(QObject::tr("Add a property to %1").arg(QString::fromStdString(varSet->getFullName()))); +} + void DlgAddPropertyVarSet::setOkEnabled(bool enabled) { QPushButton *okButton = ui->buttonBox->button(QDialogButtonBox::Ok); @@ -219,6 +222,15 @@ void DlgAddPropertyVarSet::removeEditor() } } +void DlgAddPropertyVarSet::changeEvent(QEvent* e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + setTitle(); + } + QDialog::changeEvent(e); +} + static PropertyEditor::PropertyItem *createPropertyItem(App::Property *prop) { const char *editor = prop->getEditorName(); diff --git a/src/Gui/DlgAddPropertyVarSet.h b/src/Gui/DlgAddPropertyVarSet.h index f837e1297c3f..d59a684cf6a2 100644 --- a/src/Gui/DlgAddPropertyVarSet.h +++ b/src/Gui/DlgAddPropertyVarSet.h @@ -74,6 +74,7 @@ class GuiExport DlgAddPropertyVarSet : public QDialog DlgAddPropertyVarSet(QWidget *parent, ViewProviderVarSet* viewProvider); ~DlgAddPropertyVarSet() override; + void changeEvent(QEvent* e) override; void accept() override; void reject() override; @@ -85,6 +86,7 @@ public Q_SLOTS: void initializeTypes(); void initializeWidgets(ViewProviderVarSet* viewProvider); + void setTitle(); void setOkEnabled(bool enabled); void clearEditors(bool clearName = true); void clearCurrentProperty(); From 3db3f7546d0aec80fe51afed668e7ae4dbfe5f85 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 28 Oct 2024 11:02:51 +0100 Subject: [PATCH 057/161] Gui: Add overloaded function Document::openEditingView3D(const App::DocumentObject*) --- src/Gui/Document.cpp | 31 +++++++++++++++++++++++-------- src/Gui/Document.h | 5 +++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index b53139b801e1..3223e1a13a13 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -578,7 +578,7 @@ void Document::resetIfEditing() } } -View3DInventor* Document::openEditingView3D(ViewProviderDocumentObject* vp) +View3DInventor* Document::openEditingView3D(const ViewProviderDocumentObject* vp) { auto view3d = dynamic_cast(getActiveView()); // if the currently active view is not the 3d view search for it and activate it @@ -592,6 +592,16 @@ View3DInventor* Document::openEditingView3D(ViewProviderDocumentObject* vp) return view3d; } +View3DInventor* Document::openEditingView3D(const App::DocumentObject* obj) +{ + if (auto vp = dynamic_cast( + Application::Instance->getViewProvider(obj))) { + return openEditingView3D(vp); + } + + return nullptr; +} + bool Document::trySetEdit(Gui::ViewProvider* p, int ModNum, const char *subname) { auto vp = DocumentP::throwIfCastFails(p); @@ -2357,7 +2367,7 @@ MDIView* Document::getActiveView() const return nullptr; } -MDIView *Document::setActiveView(ViewProviderDocumentObject *vp, Base::Type typeId) +MDIView *Document::setActiveView(const ViewProviderDocumentObject* vp, Base::Type typeId) { MDIView *view = nullptr; if (!vp) { @@ -2372,19 +2382,22 @@ MDIView *Document::setActiveView(ViewProviderDocumentObject *vp, Base::Type type } else { auto linked = obj->getLinkedObject(true); - if (linked!=obj) { + if (linked != obj) { auto vpLinked = dynamic_cast( Application::Instance->getViewProvider(linked)); - if (vpLinked) + if (vpLinked) { view = vpLinked->getMDIView(); + } } if (!view && typeId.isBad()) { MDIView* active = getActiveView(); - if (active && active->containsViewProvider(vp)) + if (active && active->containsViewProvider(vp)) { view = active; - else + } + else { typeId = View3DInventor::getClassTypeId(); + } } } } @@ -2401,11 +2414,13 @@ MDIView *Document::setActiveView(ViewProviderDocumentObject *vp, Base::Type type } } - if (!view && !typeId.isBad()) + if (!view && !typeId.isBad()) { view = createView(typeId); + } - if (view) + if (view) { getMainWindow()->setActiveWindow(view); + } return view; } diff --git a/src/Gui/Document.h b/src/Gui/Document.h index 42a3aae04c3c..6b0a1786bc6d 100644 --- a/src/Gui/Document.h +++ b/src/Gui/Document.h @@ -218,8 +218,9 @@ class GuiExport Document : public Base::Persistence std::list getMDIViews() const; /// returns a list of all MDI views of a certain type std::list getMDIViewsOfType(const Base::Type& typeId) const; - MDIView *setActiveView(ViewProviderDocumentObject *vp=nullptr, Base::Type typeId = Base::Type()); - View3DInventor* openEditingView3D(ViewProviderDocumentObject* vp); + MDIView *setActiveView(const ViewProviderDocumentObject* vp = nullptr, Base::Type typeId = Base::Type()); + View3DInventor* openEditingView3D(const ViewProviderDocumentObject* vp); + View3DInventor* openEditingView3D(const App::DocumentObject* obj); //@} /** @name View provider handling */ From bc94cbb97e93100d1796b28914bb6fb46c4192e4 Mon Sep 17 00:00:00 2001 From: huguesdpdn-aerospace Date: Wed, 6 Nov 2024 02:11:16 +0100 Subject: [PATCH 058/161] Bump OndelSolver version - Include compilation fix for Ubuntu with old GCC versions --- src/3rdParty/OndselSolver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdParty/OndselSolver b/src/3rdParty/OndselSolver index 91f70382beeb..2e3659c4bce3 160000 --- a/src/3rdParty/OndselSolver +++ b/src/3rdParty/OndselSolver @@ -1 +1 @@ -Subproject commit 91f70382beeb58b32432b5a82da3802e4c19199c +Subproject commit 2e3659c4bce3e6885269e0cb3d640261b2a91108 From 6034f06383cc0864b35cd52c7c6c8bebe67b4350 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Tue, 24 Sep 2024 22:31:18 -0400 Subject: [PATCH 059/161] Gui: Remove newline from dialog string This commit removes superflous newline that disrupts the flow of the sentence displayed in the VarSet dialog. See #16776 --- src/Gui/DlgAddPropertyVarSet.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Gui/DlgAddPropertyVarSet.cpp b/src/Gui/DlgAddPropertyVarSet.cpp index b1ca96d634b1..702c996ada2d 100644 --- a/src/Gui/DlgAddPropertyVarSet.cpp +++ b/src/Gui/DlgAddPropertyVarSet.cpp @@ -398,9 +398,10 @@ class CreatePropertyException : public std::exception { void DlgAddPropertyVarSet::checkName() { std::string name = ui->lineEditName->text().toStdString(); if(name.empty() || name != Base::Tools::getIdentifier(name)) { - critical(QObject::tr("Invalid name"), - QObject::tr("The property name must only contain alpha numericals,\n" - "underscore, and must not start with a digit.")); + QMessageBox::critical(getMainWindow(), + QObject::tr("Invalid name"), + QObject::tr("The property name must only contain alpha numericals, " + "underscore, and must not start with a digit.")); clearEditors(!CLEAR_NAME); throw CreatePropertyException("Invalid name"); } From 979075ce0d3430b4966ce96858c112ccdbc77466 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Thu, 14 Nov 2024 17:36:35 +0100 Subject: [PATCH 060/161] Assembly: Pressing Esc while a task is active will not escape edit mode --- src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index 5e0764ca37a1..dabbcd7c819a 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -326,6 +327,9 @@ bool ViewProviderAssembly::keyPressed(bool pressed, int key) { if (key == SoKeyboardEvent::ESCAPE) { if (isInEditMode()) { + if (Gui::Control().activeDialog()) { + return true; + } ParameterGrp::handle hPgr = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Assembly"); From a0e0713fef2d236d088ddfc06348c89f381b2f83 Mon Sep 17 00:00:00 2001 From: Kim Kirwan Date: Tue, 9 Jul 2024 00:47:12 -0500 Subject: [PATCH 061/161] Repair XML Files - fixes #10730 In ../src/Mod/Part/App/Geom2d/ sixteen out of seventeen XML files needed repair as per the GitHub issue. Tabbing in those sixteen files set to 4-spaces no-tab-chars. Other minor changes as needed. --- src/Mod/Part/App/Geom2d/ArcOfCircle2dPy.xml | 56 ++++----- src/Mod/Part/App/Geom2d/ArcOfConic2dPy.xml | 88 ++++++------- src/Mod/Part/App/Geom2d/ArcOfEllipse2dPy.xml | 68 +++++----- .../Part/App/Geom2d/ArcOfHyperbola2dPy.xml | 68 +++++----- src/Mod/Part/App/Geom2d/ArcOfParabola2dPy.xml | 56 ++++----- src/Mod/Part/App/Geom2d/BSplineCurve2dPy.xml | 119 +++++++++--------- src/Mod/Part/App/Geom2d/BezierCurve2dPy.xml | 18 +-- src/Mod/Part/App/Geom2d/Circle2dPy.xml | 56 ++++----- src/Mod/Part/App/Geom2d/Conic2dPy.xml | 88 ++++++------- src/Mod/Part/App/Geom2d/Curve2dPy.xml | 77 +++++++----- src/Mod/Part/App/Geom2d/Ellipse2dPy.xml | 11 +- src/Mod/Part/App/Geom2d/Geometry2dPy.xml | 100 +++++++-------- src/Mod/Part/App/Geom2d/Hyperbola2dPy.xml | 4 +- src/Mod/Part/App/Geom2d/Line2dPy.xml | 70 +++++------ src/Mod/Part/App/Geom2d/Line2dSegmentPy.xml | 81 ++++++------ src/Mod/Part/App/Geom2d/Parabola2dPy.xml | 8 +- 16 files changed, 495 insertions(+), 473 deletions(-) diff --git a/src/Mod/Part/App/Geom2d/ArcOfCircle2dPy.xml b/src/Mod/Part/App/Geom2d/ArcOfCircle2dPy.xml index feb6257f8293..670eaf53465f 100644 --- a/src/Mod/Part/App/Geom2d/ArcOfCircle2dPy.xml +++ b/src/Mod/Part/App/Geom2d/ArcOfCircle2dPy.xml @@ -1,31 +1,31 @@ - - - - Describes a portion of a circle - - - - The radius of the circle. - - - - - - The internal circle representation - - - - + + + + Describes a portion of a circle + + + + The radius of the circle. + + + + + + The internal circle representation + + + + diff --git a/src/Mod/Part/App/Geom2d/ArcOfConic2dPy.xml b/src/Mod/Part/App/Geom2d/ArcOfConic2dPy.xml index 27c438d22cef..aeceac6e0adb 100644 --- a/src/Mod/Part/App/Geom2d/ArcOfConic2dPy.xml +++ b/src/Mod/Part/App/Geom2d/ArcOfConic2dPy.xml @@ -1,49 +1,49 @@ - - - - Describes an abstract arc of conic in 2d space - - - - Location of the conic. - - - - + - - returns the eccentricity value of the conic e. - e = 0 for a circle - 0 < e < 1 for an ellipse (e = 0 if MajorRadius = MinorRadius) - e > 1 for a hyperbola - e = 1 for a parabola - + + Describes an abstract arc of conic in 2d space. - - - - - The X axis direction of the circle - - - - - - The Y axis direction of the circle - - - - + + + Location of the conic. + + + + + + + returns the eccentricity value of the conic e. + e = 0 for a circle + 0 < e < 1 for an ellipse (e = 0 if MajorRadius = MinorRadius) + e > 1 for a hyperbola + e = 1 for a parabola + + + + + + + The X axis direction of the circle. + + + + + + The Y axis direction of the circle. + + + + diff --git a/src/Mod/Part/App/Geom2d/ArcOfEllipse2dPy.xml b/src/Mod/Part/App/Geom2d/ArcOfEllipse2dPy.xml index 96692418ebc4..6a9773a68392 100644 --- a/src/Mod/Part/App/Geom2d/ArcOfEllipse2dPy.xml +++ b/src/Mod/Part/App/Geom2d/ArcOfEllipse2dPy.xml @@ -1,37 +1,37 @@ - - - - Describes a portion of an ellipse - - - - The major radius of the ellipse. - - - - - - The minor radius of the ellipse. - - - - - - The internal ellipse representation - - - - + + + + Describes a portion of an ellipse + + + + The major radius of the ellipse. + + + + + + The minor radius of the ellipse. + + + + + + The internal ellipse representation + + + + diff --git a/src/Mod/Part/App/Geom2d/ArcOfHyperbola2dPy.xml b/src/Mod/Part/App/Geom2d/ArcOfHyperbola2dPy.xml index 0b16e03fcfa9..25755bae6efb 100644 --- a/src/Mod/Part/App/Geom2d/ArcOfHyperbola2dPy.xml +++ b/src/Mod/Part/App/Geom2d/ArcOfHyperbola2dPy.xml @@ -1,37 +1,37 @@ - - - - Describes a portion of an hyperbola - - - - The major radius of the hyperbola. - - - - - - The minor radius of the hyperbola. - - - - - - The internal hyperbola representation - - - - + + + + Describes a portion of an hyperbola + + + + The major radius of the hyperbola. + + + + + + The minor radius of the hyperbola. + + + + + + The internal hyperbola representation + + + + diff --git a/src/Mod/Part/App/Geom2d/ArcOfParabola2dPy.xml b/src/Mod/Part/App/Geom2d/ArcOfParabola2dPy.xml index d45a81f7ee57..9cb9d752a049 100644 --- a/src/Mod/Part/App/Geom2d/ArcOfParabola2dPy.xml +++ b/src/Mod/Part/App/Geom2d/ArcOfParabola2dPy.xml @@ -1,31 +1,31 @@ - - - - Describes a portion of a parabola - - - - The focal length of the parabola. - - - - - - The internal parabola representation - - - - + + + + Describes a portion of a parabola. + + + + The focal length of the parabola. + + + + + + The internal parabola representation. + + + + diff --git a/src/Mod/Part/App/Geom2d/BSplineCurve2dPy.xml b/src/Mod/Part/App/Geom2d/BSplineCurve2dPy.xml index 2a6a3e48f163..9901aacdbdf2 100644 --- a/src/Mod/Part/App/Geom2d/BSplineCurve2dPy.xml +++ b/src/Mod/Part/App/Geom2d/BSplineCurve2dPy.xml @@ -24,7 +24,7 @@ Returns the value of the maximum polynomial degree of any -B-Spline curve curve. This value is 25. + B-Spline curve curve. This value is 25. @@ -55,16 +55,16 @@ B-Spline curve curve. This value is 25. Returns the index in the knot array of the knot -corresponding to the first or last parameter -of this B-Spline curve. + corresponding to the first or last parameter + of this B-Spline curve. Returns the index in the knot array of the knot -corresponding to the first or last parameter -of this B-Spline curve. + corresponding to the first or last parameter + of this B-Spline curve. @@ -95,54 +95,56 @@ of this B-Spline curve. increase(Int=Degree) -Increases the degree of this B-Spline curve to Degree. -As a result, the poles, weights and multiplicities tables -are modified; the knots table is not changed. Nothing is -done if Degree is less than or equal to the current degree. + Increases the degree of this B-Spline curve to Degree. + As a result, the poles, weights and multiplicities tables + are modified; the knots table is not changed. Nothing is + done if Degree is less than or equal to the current degree. increaseMultiplicity(int index, int mult) - increaseMultiplicity(int start, int end, int mult) - Increases multiplicity of knots up to mult. + increaseMultiplicity(int start, int end, int mult) + Increases multiplicity of knots up to mult. - index: the index of a knot to modify (1-based) - start, end: index range of knots to modify. - If mult is lower or equal to the current multiplicity nothing is done. If mult is higher than the degree the degree is used. + index: the index of a knot to modify (1-based) + start, end: index range of knots to modify. + If mult is lower or equal to the current multiplicity nothing is done. + If mult is higher than the degree the degree is used. incrementMultiplicity(int start, int end, int mult) - Raises multiplicity of knots by mult. + Raises multiplicity of knots by mult. - start, end: index range of knots to modify. + start, end: index range of knots to modify. insertKnot(u, mult = 1, tol = 0.0) - Inserts a knot value in the sequence of knots. If u is an existing knot the - multiplicity is increased by mult. + Inserts a knot value in the sequence of knots. If u is an existing knot the + multiplicity is increased by mult. insertKnots(list_of_floats, list_of_ints, tol = 0.0, bool_add = True) - Inserts a set of knots values in the sequence of knots. - For each u = list_of_floats[i], mult = list_of_ints[i] + Inserts a set of knots values in the sequence of knots. - If u is an existing knot the multiplicity is increased by mult if bool_add is - True, otherwise increased to mult. + For each u = list_of_floats[i], mult = list_of_ints[i] - If u is not on the parameter range nothing is done. + If u is an existing knot the multiplicity is increased by mult if bool_add is + True, otherwise increased to mult. - If the multiplicity is negative or null nothing is done. The new multiplicity - is limited to the degree. + If u is not on the parameter range nothing is done. - The tolerance criterion for knots equality is the max of Epsilon(U) and ParametricTolerance. + If the multiplicity is negative or null nothing is done. The new multiplicity + is limited to the degree. + + The tolerance criterion for knots equality is the max of Epsilon(U) and ParametricTolerance. @@ -192,7 +194,7 @@ done if Degree is less than or equal to the current degree. Modifies this B-Spline curve by assigning P -to the pole of index Index in the poles table. + to the pole of index Index in the poles table. @@ -228,27 +230,27 @@ to the pole of index Index in the poles table. Computes for this B-Spline curve the parametric tolerance (UTolerance) -for a given 3D tolerance (Tolerance3D). -If f(t) is the equation of this B-Spline curve, the parametric tolerance -ensures that: -|t1-t0| < UTolerance =""==> |f(t1)-f(t0)| < Tolerance3D + for a given 3D tolerance (Tolerance3D). + If f(t) is the equation of this B-Spline curve, the parametric tolerance + ensures that: + |t1-t0| < UTolerance =""==> |f(t1)-f(t0)| < Tolerance3D movePoint(U, P, Index1, Index2) - Moves the point of parameter U of this B-Spline curve to P. -Index1 and Index2 are the indexes in the table of poles of this B-Spline curve -of the first and last poles designated to be moved. + Moves the point of parameter U of this B-Spline curve to P. + Index1 and Index2 are the indexes in the table of poles of this B-Spline curve + of the first and last poles designated to be moved. -Returns: (FirstModifiedPole, LastModifiedPole). They are the indexes of the -first and last poles which are effectively modified. + Returns: (FirstModifiedPole, LastModifiedPole). They are the indexes of the + first and last poles which are effectively modified. Changes this B-Spline curve into a non-periodic curve. -If this curve is already non-periodic, it is not modified. + If this curve is already non-periodic, it is not modified. @@ -259,14 +261,14 @@ If this curve is already non-periodic, it is not modified. Assigns the knot of index Index in the knots table -as the origin of this periodic B-Spline curve. As a consequence, -the knots and poles tables are modified. + as the origin of this periodic B-Spline curve. As a consequence, + the knots and poles tables are modified. Returns the multiplicity of the knot of index -from the knots table of this B-Spline curve. + from the knots table of this B-Spline curve. @@ -353,28 +355,29 @@ from the knots table of this B-Spline curve. Builds a B-Spline by a lists of Poles, Mults, Knots. - arguments: poles (sequence of Base.Vector), [mults , knots, periodic, degree, weights (sequence of float), CheckRational] + arguments: poles (sequence of Base.Vector), + [mults , knots, periodic, degree, weights (sequence of float), CheckRational] - Examples: - from FreeCAD import Base - import Part - V=Base.Vector - poles=[V(-10,-10),V(10,-10),V(10,10),V(-10,10)] + Examples: + from FreeCAD import Base + import Part + V=Base.Vector + poles=[V(-10,-10),V(10,-10),V(10,10),V(-10,10)] - # non-periodic spline - n=Part.BSplineCurve() - n.buildFromPolesMultsKnots(poles,(3,1,3),(0,0.5,1),False,2) - Part.show(n.toShape()) + # non-periodic spline + n=Part.BSplineCurve() + n.buildFromPolesMultsKnots(poles,(3,1,3),(0,0.5,1),False,2) + Part.show(n.toShape()) - # periodic spline - p=Part.BSplineCurve() - p.buildFromPolesMultsKnots(poles,(1,1,1,1,1),(0,0.25,0.5,0.75,1),True,2) - Part.show(p.toShape()) + # periodic spline + p=Part.BSplineCurve() + p.buildFromPolesMultsKnots(poles,(1,1,1,1,1),(0,0.25,0.5,0.75,1),True,2) + Part.show(p.toShape()) - # periodic and rational spline - r=Part.BSplineCurve() - r.buildFromPolesMultsKnots(poles,(1,1,1,1,1),(0,0.25,0.5,0.75,1),True,2,(1,0.8,0.7,0.2)) - Part.show(r.toShape()) + # periodic and rational spline + r=Part.BSplineCurve() + r.buildFromPolesMultsKnots(poles,(1,1,1,1,1),(0,0.25,0.5,0.75,1),True,2,(1,0.8,0.7,0.2)) + Part.show(r.toShape()) diff --git a/src/Mod/Part/App/Geom2d/BezierCurve2dPy.xml b/src/Mod/Part/App/Geom2d/BezierCurve2dPy.xml index d18bb4f84140..55869d5553f6 100644 --- a/src/Mod/Part/App/Geom2d/BezierCurve2dPy.xml +++ b/src/Mod/Part/App/Geom2d/BezierCurve2dPy.xml @@ -20,14 +20,14 @@ Returns the polynomial degree of this Bezier curve, -which is equal to the number of poles minus 1. + which is equal to the number of poles minus 1. Returns the value of the maximum polynomial degree of any -Bezier curve curve. This value is 25. + Bezier curve curve. This value is 25. @@ -68,8 +68,8 @@ Bezier curve curve. This value is 25. increase(Int=Degree) -Increases the degree of this Bezier curve to Degree. -As a result, the poles and weights tables are modified. + Increases the degree of this Bezier curve to Degree. + As a result, the poles and weights tables are modified. @@ -85,7 +85,7 @@ As a result, the poles and weights tables are modified. Removes the pole of index Index from the table of poles of this Bezier curve. -If this Bezier curve is rational, it can become non-rational. + If this Bezier curve is rational, it can become non-rational. @@ -131,10 +131,10 @@ If this Bezier curve is rational, it can become non-rational. Computes for this Bezier curve the parametric tolerance (UTolerance) -for a given 3D tolerance (Tolerance3D). -If f(t) is the equation of this Bezier curve, the parametric tolerance -ensures that: -|t1-t0| < UTolerance =""==> |f(t1)-f(t0)| < Tolerance3D + for a given 3D tolerance (Tolerance3D). + If f(t) is the equation of this Bezier curve, + the parametric tolerance ensures that: + |t1-t0| < UTolerance =""==> |f(t1)-f(t0)| < Tolerance3D diff --git a/src/Mod/Part/App/Geom2d/Circle2dPy.xml b/src/Mod/Part/App/Geom2d/Circle2dPy.xml index 66bb6176f5b9..11d6c8d5250c 100644 --- a/src/Mod/Part/App/Geom2d/Circle2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Circle2dPy.xml @@ -1,19 +1,19 @@ - - - - Describes a circle in 3D space + + + + Describes a circle in 3D space To create a circle there are several ways: Part.Geom2d.Circle2d() Creates a default circle with center (0,0) and radius 1 @@ -29,18 +29,18 @@ Part.Geom2d.Circle2d(Center,Radius) Part.Geom2d.Circle2d(Point1,Point2,Point3) Creates a circle defined by three non-linear points - - - - - Get the circle center defined by three points - - - - - The radius of the circle. - - - - + + + + + Get the circle center defined by three points + + + + + The radius of the circle. + + + + diff --git a/src/Mod/Part/App/Geom2d/Conic2dPy.xml b/src/Mod/Part/App/Geom2d/Conic2dPy.xml index a02c16844efe..f86e5f12ea4d 100644 --- a/src/Mod/Part/App/Geom2d/Conic2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Conic2dPy.xml @@ -1,49 +1,49 @@ - - - - Describes an abstract conic in 2d space - - - - Location of the conic. - - - - + - - returns the eccentricity value of the conic e. - e = 0 for a circle - 0 < e < 1 for an ellipse (e = 0 if MajorRadius = MinorRadius) - e > 1 for a hyperbola - e = 1 for a parabola - + + Describes an abstract conic in 2d space - - - - - The X axis direction of the circle - - - - - - The Y axis direction of the circle - - - - + + + Location of the conic. + + + + + + + returns the eccentricity value of the conic e. + e = 0 for a circle + 0 < e < 1 for an ellipse (e = 0 if MajorRadius = MinorRadius) + e > 1 for a hyperbola + e = 1 for a parabola + + + + + + + The X axis direction of the circle + + + + + + The Y axis direction of the circle + + + + diff --git a/src/Mod/Part/App/Geom2d/Curve2dPy.xml b/src/Mod/Part/App/Geom2d/Curve2dPy.xml index 2594d2264fea..33f5050ec1d7 100644 --- a/src/Mod/Part/App/Geom2d/Curve2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Curve2dPy.xml @@ -27,23 +27,24 @@ - Discretizes the curve and returns a list of points. + +Discretizes the curve and returns a list of points. The function accepts keywords as argument: -discretize(Number=n) => gives a list of 'n' equidistant points -discretize(QuasiNumber=n) => gives a list of 'n' quasi equidistant points (is faster than the method above) -discretize(Distance=d) => gives a list of equidistant points with distance 'd' -discretize(Deflection=d) => gives a list of points with a maximum deflection 'd' to the curve -discretize(QuasiDeflection=d) => gives a list of points with a maximum deflection 'd' to the curve (faster) +discretize(Number=n) => gives a list of 'n' equidistant points. +discretize(QuasiNumber=n) => gives a list of 'n' quasi-equidistant points (is faster than the method above). +discretize(Distance=d) => gives a list of equidistant points with distance 'd'. +discretize(Deflection=d) => gives a list of points with a maximum deflection 'd' to the curve. +discretize(QuasiDeflection=d) => gives a list of points with a maximum deflection 'd' to the curve (faster). discretize(Angular=a,Curvature=c,[Minimum=m]) => gives a list of points with an angular deflection of 'a' - and a curvature deflection of 'c'. Optionally a minimum number of points - can be set which by default is set to 2. + and a curvature deflection of 'c'. Optionally a minimum number of points + can be set, which by default is set to 2. -Optionally you can set the keywords 'First' and 'Last' to define a sub-range of the parameter range -of the curve. +Optionally you can set the keywords 'First' and 'Last' to define + a sub-range of the parameter range of the curve. -If no keyword is given then it depends on whether the argument is an int or float. -If it's an int then the behaviour is as if using the keyword 'Number', if it's float -then the behaviour is as if using the keyword 'Distance'. +If no keyword is given, then it depends on whether the argument is an int or float. +If it's an int then the behaviour is as if using the keyword 'Number', +if it's a float then the behaviour is as if using the keyword 'Distance'. Example: @@ -57,19 +58,25 @@ Part.show(s) p=c.discretize(Angular=0.09,Curvature=0.01,Last=3.14,Minimum=100) s=Part.Compound([Part.Vertex(i) for i in p]) -Part.show(s) +Part.show(s) + - Computes the length of a curve -length([uMin,uMax,Tol]) -> Float + + Computes the length of a curve + length([uMin,uMax,Tol]) -> Float + - Returns the parameter on the curve of a point at the given distance from a starting parameter. -parameterAtDistance([abscissa, startingParameter]) -> Float the + + Returns the parameter on the curve of a point at + the given distance from a starting parameter. + parameterAtDistance([abscissa, startingParameter]) -> Float + @@ -84,40 +91,54 @@ parameterAtDistance([abscissa, startingParameter]) -> Float the - Returns the parameter on the curve -of the nearest orthogonal projection of the point. + + Returns the parameter on the curve of the + nearest orthogonal projection of the point. + - Vector = normal(pos) - Get the normal vector at the given parameter [First|Last] if defined + + Vector = normal(pos) - Get the normal vector at the given parameter [First|Last] if defined. + - Float = curvature(pos) - Get the curvature at the given parameter [First|Last] if defined + + Float = curvature(pos) - Get the curvature at the given parameter [First|Last] if defined. + - Vector = centerOfCurvature(float pos) - Get the center of curvature at the given parameter [First|Last] if defined + + Vector = centerOfCurvature(float pos) - Get the center of curvature at the given parameter [First|Last] if defined. + - Returns all intersection points between this curve and the given curve. + + Returns all intersection points between this curve and the given curve. + - Converts a curve of any type (only part from First to Last) - toBSpline([Float=First, Float=Last]) -> B-Spline curve + + Converts a curve of any type (only part from First to Last) + toBSpline([Float=First, Float=Last]) -> B-Spline curve + - Approximates a curve of any type to a B-Spline curve - approximateBSpline(Tolerance, MaxSegments, MaxDegree, [Order='C2']) -> B-Spline curve + + Approximates a curve of any type to a B-Spline curve + approximateBSpline(Tolerance, MaxSegments, MaxDegree, [Order='C2']) -> B-Spline curve + diff --git a/src/Mod/Part/App/Geom2d/Ellipse2dPy.xml b/src/Mod/Part/App/Geom2d/Ellipse2dPy.xml index ee60019a0ecf..2412cdd68b19 100644 --- a/src/Mod/Part/App/Geom2d/Ellipse2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Ellipse2dPy.xml @@ -13,7 +13,8 @@ Constructor="true"> - Describes an ellipse in 2D space + + Describes an ellipse in 2D space To create an ellipse there are several ways: Part.Geom2d.Ellipse2d() Creates an ellipse with major radius 2 and minor radius 1 with the @@ -52,17 +53,13 @@ - The first focus is on the positive side of the major axis of the ellipse; -the second focus is on the negative side. + The first focus is on the positive side of the major axis of the ellipse. - - The first focus is on the positive side of the major axis of the ellipse; -the second focus is on the negative side. - + The second focus is on the negative side of the major axis of the ellipse. diff --git a/src/Mod/Part/App/Geom2d/Geometry2dPy.xml b/src/Mod/Part/App/Geom2d/Geometry2dPy.xml index 2526fca0986a..743b2f3c8033 100644 --- a/src/Mod/Part/App/Geom2d/Geometry2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Geometry2dPy.xml @@ -1,53 +1,53 @@ - - - - The abstract class Geometry for 2D space is the root class of all geometric objects. -It describes the common behavior of these objects when: -- applying geometric transformations to objects, and -- constructing objects by geometric transformation (including copying). - - - - Performs the symmetrical transformation of this geometric object - - - - - Rotates this geometric object at angle Ang (in radians) around a point - - - - - Applies a scaling transformation on this geometric object with a center and scaling factor - - - - - Applies a transformation to this geometric object - - - - - Translates this geometric object - - - - - Create a copy of this geometry - - - + + + + The abstract class Geometry for 2D space is the root class of all geometric objects. + It describes the common behavior of these objects when: + - applying geometric transformations to objects, and + - constructing objects by geometric transformation (including copying). + + + + Performs the symmetrical transformation of this geometric object. + + + + + Rotates this geometric object at angle Ang (in radians) around a point. + + + + + Applies a scaling transformation on this geometric object with a center and scaling factor. + + + + + Applies a transformation to this geometric object. + + + + + Translates this geometric object. + + + + + Create a copy of this geometry. + + + diff --git a/src/Mod/Part/App/Geom2d/Hyperbola2dPy.xml b/src/Mod/Part/App/Geom2d/Hyperbola2dPy.xml index a8c60e0b63c8..24c8bfcf1ee4 100644 --- a/src/Mod/Part/App/Geom2d/Hyperbola2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Hyperbola2dPy.xml @@ -53,7 +53,7 @@ The first focus is on the positive side of the major axis of the hyperbola; -the second focus is on the negative side. + the second focus is on the negative side. @@ -61,7 +61,7 @@ the second focus is on the negative side. The first focus is on the positive side of the major axis of the hyperbola; -the second focus is on the negative side. + the second focus is on the negative side. diff --git a/src/Mod/Part/App/Geom2d/Line2dPy.xml b/src/Mod/Part/App/Geom2d/Line2dPy.xml index d210d14b4679..90b5ac87f516 100644 --- a/src/Mod/Part/App/Geom2d/Line2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Line2dPy.xml @@ -1,40 +1,40 @@ - - - - Describes an infinite line in 2D space -To create a line there are several ways: -Part.Geom2d.Line2d() - Creates a default line + + + + Describes an infinite line in 2D space + To create a line there are several ways: + Part.Geom2d.Line2d() + Creates a default line. -Part.Geom2d.Line2d(Line) - Creates a copy of the given line + Part.Geom2d.Line2d(Line) + Creates a copy of the given line. -Part.Geom2d.Line2d(Point,Dir) - Creates a line that goes through two given points - - - - Returns the location of this line. - - - - - - Returns the direction of this line. - - - - + Part.Geom2d.Line2d(Point,Dir) + Creates a line that goes through two given points. + + + + Returns the location of this line. + + + + + + Returns the direction of this line. + + + + diff --git a/src/Mod/Part/App/Geom2d/Line2dSegmentPy.xml b/src/Mod/Part/App/Geom2d/Line2dSegmentPy.xml index 55fa3f495c58..b915ca80fc50 100644 --- a/src/Mod/Part/App/Geom2d/Line2dSegmentPy.xml +++ b/src/Mod/Part/App/Geom2d/Line2dSegmentPy.xml @@ -1,45 +1,46 @@ - - - - Describes a line segment in 2D space -To create a line there are several ways: -Part.Geom2d.Line2dSegment() - Creates a default line + + + + Describes a line segment in 2D space. -Part.Geom2d.Line2dSegment(Line) - Creates a copy of the given line + To create a line there are several ways: + Part.Geom2d.Line2dSegment() + Creates a default line -Part.Geom2d.Line2dSegment(Point1,Point2) - Creates a line that goes through two given points - - - - Set the parameter range of the underlying line segment geometry - - - - - Returns the start point of this line segment. - - - - - - Returns the end point of this line segment. - - - - + Part.Geom2d.Line2dSegment(Line) + Creates a copy of the given line + + Part.Geom2d.Line2dSegment(Point1,Point2) + Creates a line that goes through two given points. + + + + Set the parameter range of the underlying line segment geometry. + + + + + Returns the start point of this line segment. + + + + + + Returns the end point of this line segment. + + + + diff --git a/src/Mod/Part/App/Geom2d/Parabola2dPy.xml b/src/Mod/Part/App/Geom2d/Parabola2dPy.xml index fe98c758fe1d..32cb935c061f 100644 --- a/src/Mod/Part/App/Geom2d/Parabola2dPy.xml +++ b/src/Mod/Part/App/Geom2d/Parabola2dPy.xml @@ -18,22 +18,22 @@ The focal distance is the distance between -the apex and the focus of the parabola. + the apex and the focus of the parabola. The focus is on the positive side of the -'X Axis' of the local coordinate system of the parabola. + 'X Axis' of the local coordinate system of the parabola. Compute the parameter of this parabola -which is the distance between its focus -and its directrix. This distance is twice the focal length. + which is the distance between its focus + and its directrix. This distance is twice the focal length. From b63ba9b4f48adfa2a8ed8f39566cb62990d79e1f Mon Sep 17 00:00:00 2001 From: bdieterm <119257544+bdieterm@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:41:17 +0200 Subject: [PATCH 062/161] Gui: improve performance of macro execution and fix time measurement This commit improves the performance of Python code from FreeCAD macros by: * using the chrono C++ stdlib header instead of QTime * checking for the elapsed time ONLY every 1000th Python opcode execution And this commit fixes time measurement by using a monotonic time source instead of a normal one. The previous implementation using QTime would give a negative time duration if the start time is 23:59:59 and the end time is 00:00:01. related commit: e78f74b01a44bce0853a847252ec5f33294e1c36 --- src/Gui/PythonTracing.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/Gui/PythonTracing.cpp b/src/Gui/PythonTracing.cpp index e6063cdacf06..e80afb8ed8ca 100644 --- a/src/Gui/PythonTracing.cpp +++ b/src/Gui/PythonTracing.cpp @@ -25,16 +25,21 @@ #ifndef _PreComp_ #include #include -#include #include #endif +#include + #include "PythonTracing.h" #include #include using namespace Gui; +using Clock = std::chrono::steady_clock; +using TimePoint = std::chrono::time_point; + + struct PythonTracing::Private { bool active{false}; @@ -124,6 +129,10 @@ void PythonTracing::setPythonTraceEnabled(bool enabled) const * This callback ensures that Qt runs its event loop (i.e. updates the GUI, processes keyboard and * mouse events, etc.) at least every 200 ms, even when there is long-running Python code on the * main thread. It is registered as the global trace function of the Python environment. + * + * WARNING! THIS IS PERFORMANCE-CRITICAL CODE! + * This callback is even called for per-opcode events in the Python code, so unoptimized code could + * dramatically slow down the execution of Python code and FreeCAD macros. */ int PythonTracing::tracer_callback(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) { @@ -132,8 +141,15 @@ int PythonTracing::tracer_callback(PyObject *obj, PyFrameObject *frame, int what Q_UNUSED(what) Q_UNUSED(arg) - static QTime lastCalledTime = QTime::currentTime(); - QTime currTime = QTime::currentTime(); + // no need to check the time at every single Python opcode execution + static int skipCounter = 0; + if (++skipCounter < 1000) { + return 0; + } + skipCounter = 0; + + static TimePoint lastCalledTime = Clock::now(); + TimePoint currTime = Clock::now(); // if previous code object was executed if (Private::profilerDisabled) { @@ -141,9 +157,8 @@ int PythonTracing::tracer_callback(PyObject *obj, PyFrameObject *frame, int what lastCalledTime = currTime; } - int ms = lastCalledTime.msecsTo(currTime); - - if (ms >= Private::profilerInterval) { + const std::chrono::duration duration = currTime - lastCalledTime; + if (1000.0 * duration.count() >= static_cast(Private::profilerInterval)) { lastCalledTime = currTime; QGuiApplication::processEvents(); } From a9554c2fe08e4d600c5a4bcbbe87e9d06e705317 Mon Sep 17 00:00:00 2001 From: mwganson Date: Sat, 2 Nov 2024 22:11:08 +0000 Subject: [PATCH 063/161] [Part CheckGeometry] add results entry for valid shapes without any errors, show skipped objects, add report view generator link in results panel label, addresses issue #17545 --- src/Mod/Part/BasicShapes/ShapeContent.py | 2 +- src/Mod/Part/Gui/TaskCheckGeometry.cpp | 82 +++++++++++++++++++++--- src/Mod/Part/Gui/TaskCheckGeometry.h | 2 + 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/Mod/Part/BasicShapes/ShapeContent.py b/src/Mod/Part/BasicShapes/ShapeContent.py index 0e49c3880871..f41380884808 100644 --- a/src/Mod/Part/BasicShapes/ShapeContent.py +++ b/src/Mod/Part/BasicShapes/ShapeContent.py @@ -25,7 +25,7 @@ def buildShapeContent(objArg, decimals=2, advancedShapeContent=True): obj = objArg shp = Part.getShape(objArg) typeStr = str(shp.ShapeType) - lbl = "" if obj.Name == obj.Label else "(" + obj.Label + ")" + lbl = "" if obj.Name == obj.Label else " (" + obj.Label + ")" result = linkName + obj.Name + lbl + "\n" result += ( translate("TaskCheckGeometryResults", "Shape type") + ": " + typeStr + "\n" diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.cpp b/src/Mod/Part/Gui/TaskCheckGeometry.cpp index 7197d11fc6af..e7e98a73ee34 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.cpp +++ b/src/Mod/Part/Gui/TaskCheckGeometry.cpp @@ -391,6 +391,10 @@ TaskCheckGeometryResults::~TaskCheckGeometryResults() void TaskCheckGeometryResults::setupInterface() { message = new QLabel(this); + message->setTextFormat(Qt::RichText); + message->setTextInteractionFlags(Qt::TextBrowserInteraction); + message->setOpenExternalLinks(false); + connect(message, &QLabel::linkActivated, this, &TaskCheckGeometryResults::generateReport); message->setText(tr("Check is running...")); model = new ResultModel(this); treeView = new QTreeView(this); @@ -413,6 +417,8 @@ void TaskCheckGeometryResults::goCheck() int selectedCount(0), checkedCount(0), invalidShapes(0); ResultEntry *theRoot = new ResultEntry(); + reportViewStrings.clear(); + reportViewStrings << QLatin1String("\n"); std::string scopeName {tr("Boolean operation check...").toStdString()}; #if OCC_VERSION_HEX < 0x070500 @@ -432,21 +438,44 @@ void TaskCheckGeometryResults::goCheck() for(const auto &sel : selection) { selectedCount++; + int localInvalidShapeCount(0); + QString baseName; + QTextStream baseStream(&baseName); + baseStream << sel.DocName; + baseStream << "." << sel.FeatName; + std::string label = sel.pObject->Label.getValue(); + if (sel.FeatName != label) { + baseStream << " (" << label.c_str() << ")"; + } + TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true); if (shape.IsNull()) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = tr("Null shape"); + entry->error = tr("Skipped"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + theRoot->children.push_back(entry); continue; } if (shape.Infinite()) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = tr("Infinite shape"); + entry->error = tr("Skipped"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + theRoot->children.push_back(entry); continue; } currentSeparator = Gui::Application::Instance->getViewProvider(sel.pObject)->getRoot(); if (!currentSeparator) { continue; } - QString baseName; - QTextStream baseStream(&baseName); - baseStream << sel.DocName; - baseStream << "." << sel.FeatName; + checkedCount++; checkedMap.Clear(); @@ -456,12 +485,15 @@ void TaskCheckGeometryResults::goCheck() if (!shapeCheck.IsValid()) { invalidShapes++; + localInvalidShapeCount++; ResultEntry *entry = new ResultEntry(); entry->parent = theRoot; entry->shape = shape; entry->name = baseName; entry->type = shapeEnumToString(shape.ShapeType()); entry->error = tr("Invalid"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); @@ -485,29 +517,52 @@ void TaskCheckGeometryResults::goCheck() label += "..."; #if OCC_VERSION_HEX < 0x070500 theProgress->NewScope(label.c_str()); - invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theProgress); + localInvalidShapeCount += goBOPSingleCheck(shape, theRoot, baseName, theProgress); + invalidShapes += localInvalidShapeCount; theProgress->EndScope(); if (theProgress->UserBreak()) break; #else Message_ProgressScope theInnerScope(theScope.Next(), TCollection_AsciiString(label.c_str()), 1); theInnerScope.Show(); - invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theInnerScope); + localInvalidShapeCount += goBOPSingleCheck(shape, theRoot, baseName, theInnerScope); + invalidShapes += localInvalidShapeCount; theInnerScope.Close(); if (theScope.UserBreak()) break; #endif } } + // create an entry for shapes without errors + if (localInvalidShapeCount == 0) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = shapeEnumToString(shape.ShapeType()); + entry->error = tr("No errors"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + entry->viewProviderRoot = currentSeparator; + entry->viewProviderRoot->ref(); + theRoot->children.push_back(entry); + } } model->setResults(theRoot); treeView->expandAll(); treeView->header()->resizeSections(QHeaderView::ResizeToContents); QString aMessage {tr("%1 processed out of %2 selected").arg(checkedCount).arg(selectedCount)}; - aMessage += QLatin1String("\n ") + tr("%n invalid shapes.", "", invalidShapes); + aMessage += QLatin1String("
") + tr("%n invalid shapes.", "", invalidShapes); + aMessage += QLatin1String(" ") + tr("To Report view.") + QLatin1String(""); message->setText(aMessage); } +void TaskCheckGeometryResults::generateReport() +{ + QString reportString = reportViewStrings.join(QLatin1String("\n")); + Base::Console().Message(reportString.toStdString().c_str()); +} + + void TaskCheckGeometryResults::recursiveCheck(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape, ResultEntry *parent) { @@ -524,6 +579,8 @@ void TaskCheckGeometryResults::recursiveCheck(const BRepCheck_Analyzer &shapeChe entry->buildEntryName(); entry->type = shapeEnumToString(shape.ShapeType()); entry->error = checkStatusToString(listIt.Value()); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); dispatchError(entry, listIt.Value()); @@ -572,6 +629,8 @@ void TaskCheckGeometryResults::checkSub(const BRepCheck_Analyzer &shapeCheck, co entry->buildEntryName(); entry->type = shapeEnumToString(sub.ShapeType()); entry->error = checkStatusToString(itl.Value()); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); dispatchError(entry, itl.Value()); @@ -724,6 +783,8 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu entry->name = baseName; entry->type = shapeEnumToString(shapeIn.ShapeType()); entry->error = QObject::tr("Invalid"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); @@ -746,6 +807,8 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu faultyEntry->buildEntryName(); faultyEntry->type = shapeEnumToString(faultyShape.ShapeType()); faultyEntry->error = getBOPCheckString(current.GetCheckStatus()); + reportViewStrings.append(QLatin1String(" ") + faultyEntry->name + + QLatin1String(" | ") + faultyEntry->error); faultyEntry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(faultyEntry); @@ -841,7 +904,10 @@ void TaskCheckGeometryResults::currentRowChanged (const QModelIndex ¤t, co QString doc, object, sub; if (!this->split((*stringIt), doc, object, sub)) continue; - Gui::Selection().addSelection(doc.toLatin1(), object.toLatin1(), sub.toLatin1()); + // object might be "name (label)", so trim if necessary + int idx = object.indexOf(QLatin1String(" (")); + QString trimmed = (idx != -1) ? object.left(idx) : object; + Gui::Selection().addSelection(doc.toLatin1(), trimmed.toLatin1(), sub.toLatin1()); } } } diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.h b/src/Mod/Part/Gui/TaskCheckGeometry.h index 562dfafd5fac..1a8343b82517 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.h +++ b/src/Mod/Part/Gui/TaskCheckGeometry.h @@ -114,6 +114,8 @@ private Q_SLOTS: private: void setupInterface(); + QStringList reportViewStrings; + void generateReport(); void recursiveCheck(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape, ResultEntry *parent); void checkSub(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape, From be8dfbfc7e4435faf84c20d641ba67330e35cdab Mon Sep 17 00:00:00 2001 From: marioalexis Date: Tue, 5 Nov 2024 21:14:38 -0300 Subject: [PATCH 064/161] Fem: Add preference entry to set Gmsh log verbosity - fixes #17673 --- src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui | 54 ++++++++++++++++++++++- src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp | 27 ++++++++++++ src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h | 1 + src/Mod/Fem/femmesh/gmshtools.py | 5 ++- 4 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui b/src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui index acddbffe757f..e6981dc9f22b 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui +++ b/src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 105 + 420 + 193 @@ -55,6 +55,12 @@ false + + + 0 + 0 + + 100 @@ -111,6 +117,45 @@ + + + + Options + + + + + + + + Log verbosity + + + + + + + Level of verbosity printed on the task panel + + + QComboBox::AdjustToContents + + + LogVerbosity + + + Mod/Fem/Gmsh + + + + + + + + + + + @@ -143,6 +188,11 @@ QCheckBox
Gui/PrefWidgets.h
+ + Gui::PrefComboBox + QComboBox +
Gui/PrefWidgets.h
+
diff --git a/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp b/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp index 2ff086808697..3c0f8b6d918a 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp +++ b/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp @@ -27,6 +27,7 @@ #include #endif +#include #include "DlgSettingsFemGmshImp.h" #include "ui_DlgSettingsFemGmsh.h" @@ -51,12 +52,16 @@ void DlgSettingsFemGmshImp::saveSettings() { ui->cb_gmsh_binary_std->onSave(); ui->fc_gmsh_binary_path->onSave(); + ui->cb_log_verbosity->onSave(); } void DlgSettingsFemGmshImp::loadSettings() { ui->cb_gmsh_binary_std->onRestore(); ui->fc_gmsh_binary_path->onRestore(); + + populateLogVerbosity(); + ui->cb_log_verbosity->onRestore(); } /** @@ -83,4 +88,26 @@ void DlgSettingsFemGmshImp::onfileNameChanged(QString FileName) } } +void DlgSettingsFemGmshImp::populateLogVerbosity() +{ + std::list> mapValues = {{"Silent", 0}, + {"Errors", 1}, + {"Warnings", 2}, + {"Direct", 3}, + {"Information", 4}, + {"Status", 5}, + {"Debug", 99}}; + + for (const auto& val : mapValues) { + ui->cb_log_verbosity->addItem(QString::fromStdString(val.first), + QString::number(val.second)); + } + + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Fem/Gmsh"); + std::string current = hGrp->GetASCII("LogVerbosity", "3"); + int index = ui->cb_log_verbosity->findData(QString::fromStdString(current)); + ui->cb_log_verbosity->setCurrentIndex(index); +} + #include "moc_DlgSettingsFemGmshImp.cpp" diff --git a/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h b/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h index 18a04590cc4f..66f77c4a2285 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h +++ b/src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h @@ -47,6 +47,7 @@ protected Q_SLOTS: void saveSettings() override; void loadSettings() override; void changeEvent(QEvent* e) override; + void populateLogVerbosity(); private: std::unique_ptr ui; diff --git a/src/Mod/Fem/femmesh/gmshtools.py b/src/Mod/Fem/femmesh/gmshtools.py index 6feebb75ff5d..33093165b2d0 100644 --- a/src/Mod/Fem/femmesh/gmshtools.py +++ b/src/Mod/Fem/femmesh/gmshtools.py @@ -219,7 +219,10 @@ def prepare(self): self.write_gmsh_input_files() def compute(self): - command_list = ["-v", "4", "-", self.temp_file_geo] + log_level = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").GetString( + "LogVerbosity", "3" + ) + command_list = ["-v", log_level, "-", self.temp_file_geo] self.process.start(self.gmsh_bin, command_list) return self.process From 98a15bcc9de302710d4b7303c8a3cdaa2174c05a Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 13 Nov 2024 09:08:40 -0300 Subject: [PATCH 065/161] Fem: Avoid legacy Netgen meshing if there is no referenced shape - fixes #17814 --- src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp index a296b0b10b87..5fa6536ea67f 100644 --- a/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp +++ b/src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp @@ -86,7 +86,11 @@ App::DocumentObjectExecReturn* FemMeshShapeNetgenObject::execute() Fem::FemMesh newMesh; - Part::Feature* feat = Shape.getValue(); + const Part::Feature* feat = Shape.getValue(); + if (!feat) { + return App::DocumentObject::StdReturn; + } + TopoDS_Shape shape = feat->Shape.getValue(); NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(), shape, true); From b5a43eb2208b91feb76b2cc363e3956922c3ad75 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Fri, 22 Nov 2024 18:25:42 +0100 Subject: [PATCH 066/161] [App] clean AppJtReader.cpp (#15626) Clean code --- src/Mod/JtReader/App/AppJtReader.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Mod/JtReader/App/AppJtReader.cpp b/src/Mod/JtReader/App/AppJtReader.cpp index 3918ea2cdf53..f00d81eac1e0 100644 --- a/src/Mod/JtReader/App/AppJtReader.cpp +++ b/src/Mod/JtReader/App/AppJtReader.cpp @@ -38,16 +38,6 @@ PyMOD_INIT_FUNC(JtReader) // load dependent module Base::Interpreter().loadModule("Mesh"); - // Initialize JtTk - // JtkEntityFactory::init(); - - // Note, non-evaluation JT Open Toolkit licensees must uncomment the - // following line, inserting their "Sold_To_ID". Each licensee has a - // unique Sold_To_ID issued by UGS Corp. - // - // JtkEntityFactory::registerCustomer( 1103193 ); - // JtkEntityFactory::registerCustomer(1103103); - Base::Console().Log("Loading JtReader module... done\n"); PyMOD_Return(jtReaderModule); From 45134cef165ecc11aca69f81673e7b69421cebf1 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sat, 23 Nov 2024 02:52:16 -0300 Subject: [PATCH 067/161] App: Set PropertyColor to opaque by default --- src/App/PropertyStandard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index 3fce6611bb91..d592935d626c 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -1022,7 +1022,7 @@ class AppExport PropertyColor: public Property /** Sets the property */ void setValue(const Color& col); - void setValue(float r, float g, float b, float a = 0.0F); + void setValue(float r, float g, float b, float a = 1.0F); void setValue(uint32_t rgba); /** This method returns a string representation of the property From 51666cafc03a5527d5aeb5687648a8feadefb79f Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 22 Nov 2024 12:57:33 +0100 Subject: [PATCH 068/161] Draft: avoid listing status bar widgets in toolbar area context menu Fixes #16832. In V1.0 the two Draft status bar widgets appear as checkboxes without label in the toolbar area context menu. They should not be listed in that menu, as was the case in V0.21. Their visibility is controlled via preferences. Additionally, in case the Draft WB is only preloaded, the widgets would display in another workbench. This is prevented by using a delay. --- src/Mod/Draft/InitGui.py | 12 ++++++++---- src/Mod/Draft/draftutils/init_draft_statusbar.py | 14 ++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 72b2b09e0f00..108b5af924a2 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -151,8 +151,8 @@ def Activated(self): FreeCADGui.draftToolBar.Activated() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.show() - import draftutils.init_draft_statusbar as dsb - dsb.show_draft_statusbar() + from draftutils import init_draft_statusbar + init_draft_statusbar.show_draft_statusbar() import WorkingPlane WorkingPlane._view_observer_start() # Updates the draftToolBar when switching views. from draftutils import grid_observer @@ -165,8 +165,12 @@ def Deactivated(self): FreeCADGui.draftToolBar.Deactivated() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.hide() - import draftutils.init_draft_statusbar as dsb - dsb.hide_draft_statusbar() + from PySide import QtCore + from draftutils import init_draft_statusbar + # Delay required in case the Draft WB is preloaded, + # else show_draft_statusbar will not yet be done: + t = QtCore.QTimer() + t.singleShot(500, init_draft_statusbar.hide_draft_statusbar) import WorkingPlane WorkingPlane._view_observer_stop() from draftutils import grid_observer diff --git a/src/Mod/Draft/draftutils/init_draft_statusbar.py b/src/Mod/Draft/draftutils/init_draft_statusbar.py index 7554b6a0e1bd..3fd6e0232c1c 100644 --- a/src/Mod/Draft/draftutils/init_draft_statusbar.py +++ b/src/Mod/Draft/draftutils/init_draft_statusbar.py @@ -181,7 +181,11 @@ def init_draft_statusbar_scale(): sb = mw.statusBar() scale_widget = QtWidgets.QToolBar() + # prevent the widget from showing up in the toolbar area context menu: + scale_widget.toggleViewAction().setVisible(False) scale_widget.setObjectName("draft_scale_widget") + # WindowTitle is just in case, should not be visble in the GUI. + scale_widget.setWindowTitle(translate("draft", "Draft scale widget")) # get scales list according to system units draft_scales = get_scales() @@ -238,7 +242,11 @@ def _spacer(): # snap widget: snap_widget = QtWidgets.QToolBar() + # prevent the widget from showing up in the toolbar area context menu: + snap_widget.toggleViewAction().setVisible(False) snap_widget.setObjectName("draft_snap_widget") + # WindowTitle is just in case, should not be visble in the GUI. + snap_widget.setWindowTitle(translate("draft", "Draft snap widget")) snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) snap_widget.setIconSize(QtCore.QSize(16, 16)) sb.insertPermanentWidget(2, snap_widget) @@ -330,9 +338,6 @@ def hide_draft_statusbar(): scale_widget = mw.findChild(QtWidgets.QToolBar, "draft_scale_widget") if scale_widget: scale_widget.hide() - # prevent the widget from showing up as a blank item in the toolbar - # area context menu after switching to a different workbench: - scale_widget.toggleViewAction().setVisible(False) # hide snap widget snap_widget = sb.findChild(QtWidgets.QToolBar,"draft_snap_widget") @@ -342,8 +347,5 @@ def hide_draft_statusbar(): snap_widget = mw.findChild(QtWidgets.QToolBar,"draft_snap_widget") if snap_widget: snap_widget.hide() - # prevent the widget from showing up as a blank item in the toolbar - # area context menu after switching to a different workbench: - snap_widget.toggleViewAction().setVisible(False) ## @} From 638e677bd31214d17e8a297e127fd6381cd35084 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Sat, 23 Nov 2024 12:33:01 +0100 Subject: [PATCH 069/161] Increase the delay to be on the safe side. --- src/Mod/Draft/InitGui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 108b5af924a2..f05b5af56492 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -170,7 +170,7 @@ def Deactivated(self): # Delay required in case the Draft WB is preloaded, # else show_draft_statusbar will not yet be done: t = QtCore.QTimer() - t.singleShot(500, init_draft_statusbar.hide_draft_statusbar) + t.singleShot(700, init_draft_statusbar.hide_draft_statusbar) import WorkingPlane WorkingPlane._view_observer_stop() from draftutils import grid_observer From df97a3ad215519ad8ec5d2f0ef2e16d1575d3f9a Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:24:39 +0100 Subject: [PATCH 070/161] BIM: Fix calculation of fence sections (#18042) * BIM: Fix calculation of fence sections The length and placement of fence sections was only correct if they were cut to size. * Fix required another change. --- src/Mod/BIM/ArchFence.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Mod/BIM/ArchFence.py b/src/Mod/BIM/ArchFence.py index 442704684113..49901eeddbe2 100644 --- a/src/Mod/BIM/ArchFence.py +++ b/src/Mod/BIM/ArchFence.py @@ -147,10 +147,9 @@ def execute(self, obj): obj.Shape = compound def calculateNumberOfSections(self, pathLength, sectionLength, postLength): - withoutLastPost = pathLength - postLength realSectionLength = sectionLength + postLength - return math.ceil(withoutLastPost / realSectionLength) + return math.ceil(pathLength / realSectionLength) def calculatePostPlacements(self, obj, pathwire, rotation): postWidth = obj.Post.Shape.BoundBox.YMax @@ -159,7 +158,7 @@ def calculatePostPlacements(self, obj, pathwire, rotation): transformationVector = FreeCAD.Vector(0, - postWidth / 2, 0) return patharray.placements_on_path(rotation, pathwire, - obj.NumberOfSections + 1, + obj.NumberOfPosts, transformationVector, True) def calculatePosts(self, obj, postPlacements): @@ -204,11 +203,12 @@ def calculateSections(self, obj, postPlacements, postLength, sectionLength): sectionCopy = obj.Section.Shape.copy() - if sectionLength > sectionLine.length(): + if sectionLength > sectionLine.length() - postLength: # Part.show(Part.Shape([sectionLine]), 'line') sectionCopy = self.clipSection( sectionCopy, sectionLength, sectionLine.length() - postLength) + sectionCopy = Part.Compound([sectionCopy]) # nest in compound to ensure correct Placement sectionCopy.Placement = placement shapes.append(sectionCopy) From ed209dab68edbf8ad78674838c5bdb0f4f1b62c6 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:34:23 +0100 Subject: [PATCH 071/161] Draft: minor improvements for gui_edit.py (#17970) * Draft: minor improvements for gui_edit.py * Fix error... --- src/Mod/Draft/draftguitools/gui_edit.py | 49 ++++++++++++++----------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_edit.py b/src/Mod/Draft/draftguitools/gui_edit.py index bf571891d5fe..86f08299ba6e 100644 --- a/src/Mod/Draft/draftguitools/gui_edit.py +++ b/src/Mod/Draft/draftguitools/gui_edit.py @@ -364,17 +364,15 @@ def register_editing_callbacks(self): """ register editing callbacks (former action function) """ - viewer = Gui.ActiveDocument.ActiveView.getViewer() - self.render_manager = viewer.getSoRenderManager() - view = Gui.ActiveDocument.ActiveView + self.render_manager = self.view.getViewer().getSoRenderManager() if self._keyPressedCB is None: - self._keyPressedCB = view.addEventCallbackPivy( + self._keyPressedCB = self.view.addEventCallbackPivy( coin.SoKeyboardEvent.getClassTypeId(), self.keyPressed) if self._mouseMovedCB is None: - self._mouseMovedCB = view.addEventCallbackPivy( + self._mouseMovedCB = self.view.addEventCallbackPivy( coin.SoLocation2Event.getClassTypeId(), self.mouseMoved) if self._mousePressedCB is None: - self._mousePressedCB = view.addEventCallbackPivy( + self._mousePressedCB = self.view.addEventCallbackPivy( coin.SoMouseButtonEvent.getClassTypeId(), self.mousePressed) #App.Console.PrintMessage("Draft edit callbacks registered \n") @@ -382,17 +380,16 @@ def unregister_editing_callbacks(self): """ remove callbacks used during editing if they exist """ - view = Gui.ActiveDocument.ActiveView if self._keyPressedCB: - view.removeEventCallbackSWIG(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB) + self.view.removeEventCallbackSWIG(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB) self._keyPressedCB = None #App.Console.PrintMessage("Draft edit keyboard callback unregistered \n") if self._mouseMovedCB: - view.removeEventCallbackSWIG(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB) + self.view.removeEventCallbackSWIG(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB) self._mouseMovedCB = None #App.Console.PrintMessage("Draft edit location callback unregistered \n") if self._mousePressedCB: - view.removeEventCallbackSWIG(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB) + self.view.removeEventCallbackSWIG(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB) self._mousePressedCB = None #App.Console.PrintMessage("Draft edit mouse button callback unregistered \n") @@ -572,18 +569,25 @@ def resetTrackersBezier(self, obj): index, obj.ViewObject.LineColor, marker=marker)) def removeTrackers(self, obj=None): - """Remove Edit Trackers.""" - if obj: - if obj.Name in self.trackers: - for t in self.trackers[obj.Name]: + """Remove Edit Trackers. + + Attributes + ---------- + obj: FreeCAD object + Removes trackers only for given object, + if obj is None, removes all trackers + """ + if obj is None: + for key in self.trackers: + for t in self.trackers[key]: t.finalize() - self.trackers[obj.Name] = [] + self.trackers = {'object': []} else: - for key in self.trackers.keys(): + key = obj.Name + if key in self.trackers: for t in self.trackers[key]: t.finalize() - self.trackers = {'object': []} - + self.trackers[key] = [] def hideTrackers(self, obj=None): """Hide Edit Trackers. @@ -810,15 +814,18 @@ def deformat_objects_after_editing(self, objs): """Restore objects style during editing mode. """ for obj in objs: + if not obj.isAttachedToDocument(): + # Object has been deleted. + continue obj_gui_tools = self.get_obj_gui_tools(obj) - if obj_gui_tools and obj.isAttachedToDocument(): + if obj_gui_tools: obj_gui_tools.restore_object_style(obj, self.objs_formats[obj.Name]) def get_specific_object_info(self, obj, pos): """Return info of a specific object at a given position. """ - selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1])) + selobjs = self.view.getObjectsInfo((pos[0],pos[1])) if not selobjs: return for info in selobjs: @@ -834,7 +841,7 @@ def get_selected_obj_at_position(self, pos): If object is one of the edited objects (self.edited_objects). """ - selobjs = Gui.ActiveDocument.ActiveView.getObjectsInfo((pos[0],pos[1])) + selobjs = self.view.getObjectsInfo((pos[0],pos[1])) if not selobjs: return for info in selobjs: From 0656f19bde2a8b22a04a40ac46fdc10086e67718 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Thu, 21 Nov 2024 14:11:54 +0100 Subject: [PATCH 072/161] BIM+Draft: Bring back human figure * For the human figure attached to the Draft grid a hard-coded point list is used (instead deriving the points from human figure.brep). This is more efficient and avoids a dependency on the BIM WB. * The default for the human figure preference of the grid was changed to false. And the tooltip adjusted. --- src/Mod/BIM/Resources/create_qrc.py | 5 +- .../BIM/Resources/geometry/HumanFigure.brep | 1595 +++++++++++++++++ src/Mod/BIM/bimcommands/BimProjectManager.py | 30 +- .../Resources/ui/preferences-draftsnap.ui | 5 +- src/Mod/Draft/draftguitools/gui_trackers.py | 50 +- 5 files changed, 1644 insertions(+), 41 deletions(-) create mode 100644 src/Mod/BIM/Resources/geometry/HumanFigure.brep diff --git a/src/Mod/BIM/Resources/create_qrc.py b/src/Mod/BIM/Resources/create_qrc.py index 72ab565805dd..8919cc176cc8 100755 --- a/src/Mod/BIM/Resources/create_qrc.py +++ b/src/Mod/BIM/Resources/create_qrc.py @@ -3,14 +3,13 @@ import os txt = "\n \n" cdir = os.path.dirname(__file__) -for subdir in ["icons/IFC", "icons", "ui", "translations"]: +for subdir in ["geometry", "icons", "icons/IFC", "translations", "ui"]: subpath = os.path.join(cdir, subdir) for f in sorted(os.listdir(subpath)): if f not in ["Arch.ts", "BIM.ts", "IFC"]: ext = os.path.splitext(f)[1] - if ext.lower() in [".qm", ".svg", ".ui", ".png"]: + if ext.lower() in [".qm", ".svg", ".ui", ".png", "brep"]: txt += " " + subdir + "/" + f + "\n" txt += " \n\n" with open(os.path.join(cdir, "Arch.qrc"), "w") as resfile: resfile.write(txt) - diff --git a/src/Mod/BIM/Resources/geometry/HumanFigure.brep b/src/Mod/BIM/Resources/geometry/HumanFigure.brep new file mode 100644 index 000000000000..b99ea63d4881 --- /dev/null +++ b/src/Mod/BIM/Resources/geometry/HumanFigure.brep @@ -0,0 +1,1595 @@ +DBRep_DrawableShape + +CASCADE Topology V1, (c) Matra-Datavision +Locations 5 +1 + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 +1 + 1 0 0 0 + 0 1 0 0 + 0 0 1 0 +2 2 -1 0 +1 + 1 -3.06161699786838e-17 -3.06161699786838e-17 -25.6232564777987 +-3.06161699786838e-17 2.22044604925031e-16 -1 0 +3.06161699786838e-17 1 2.22044604925031e-16 -5.12168563026389e-15 +2 4 -1 0 +Curve2ds 0 +Curves 74 +7 0 0 3 4 2 131.21597610534553 1.066580304152452e-14 175.79749639716294 134.93457441114458 1.4599513290610294e-14 193.51335240912914 136.96375442754234 1.8182635470659675e-14 209.65030012402249 135.72526582532115 1.8628314419679277e-14 211.65745967275404 + 0 4 1 4 +7 0 0 3 4 2 135.72526582532115 1.8628314419679277e-14 211.65745967275404 134.48673431215292 1.9073961608217912e-14 213.66447618499535 137.35578168805802 2.0835636085662721e-14 221.5983527051639 142.10088851760185 2.254311130235556e-14 229.28813745480613 + 0 4 1 4 +7 0 0 3 4 2 142.10088851760185 2.254311130235556e-14 229.28813745480613 147.94985800479066 2.4647783093888126e-14 238.76673655088939 151.77123518062291 2.8009725284557702e-14 253.90757814803004 153.96650201761639 3.2982098542358063e-14 276.30115649900677 + 0 4 1 4 +7 0 0 3 4 2 153.96650201761639 3.2982098542358063e-14 276.30115649900677 155.74749941986815 3.7016076629822946e-14 294.46857871053436 160.07162125145535 4.271908387178298e-14 320.15264000031681 163.5756719737789 4.5655435617637831e-14 333.37679262877742 + 0 4 1 4 +7 0 0 3 4 2 163.5756719737789 4.5655435617637831e-14 333.37679262877742 167.0797298479269 4.8591803243733131e-14 346.601016775483 171.68636305130812 5.6399847522756811e-14 381.76532208098638 173.8125718708331 6.300666277129095e-14 411.51977277239041 + 0 4 1 4 +7 0 0 3 4 2 173.8125718708331 6.300666277129095e-14 411.51977277239041 176.26050551594039 7.0613202678887238e-14 445.77658306581986 180.74783198284578 7.7140378521423334e-14 475.17236975804718 186.04708363089793 8.0802790742180215e-14 491.66640807072497 + 0 4 1 4 +7 0 0 3 4 2 186.04708363089793 8.0802790742180215e-14 491.66640807072497 191.78725956364059 8.4769913017232014e-14 509.5327384703815 196.2179292767778 9.1756901222813322e-14 540.99933594947947 200.15345672361406 1.0304795864591204e-13 591.84973795276574 + 0 4 1 4 +7 0 0 3 4 2 200.15345672361406 1.0304795864591204e-13 591.84973795276574 205.51313413695121 1.1842474786019397e-13 661.10064012836051 211.71187075362602 1.295171434749109e-13 711.05634888544591 215.40410028245671 1.3033827894955566e-13 714.7544143030766 + 0 4 1 4 +7 0 0 3 4 2 215.40410028245671 1.3033827894955566e-13 714.7544143030766 217.77861329714435 1.3086636046641645e-13 717.13268202563222 221.3515289376746 1.2495374993038511e-13 690.50465141877453 224.0985447319656 1.1595014586672263e-13 649.9560235126728 + 0 4 1 4 +7 0 0 3 4 2 224.0985447319656 1.1595014586672263e-13 649.9560235126728 225.44242262016616 1.1154560236769984e-13 630.11972305173663 229.95234885252319 1.0413796247209258e-13 596.75867877818496 234.12066818715996 9.94887362277823e-14 575.82042519674792 + 0 4 1 4 +7 0 0 3 4 2 234.12066818715996 9.94887362277823e-14 575.82042519674792 244.81352550402462 8.7562183341228511e-14 522.10800606104976 251.79416394255333 7.4441055244945554e-14 463.01569845594935 251.87283401216331 6.6120984372184549e-14 425.54543037368671 + 0 4 1 4 +7 0 0 3 4 2 251.87283401216331 6.6120984372184549e-14 425.54543037368671 251.98282907312705 5.447983116750428e-14 373.11833713892582 245.32710517391223 3.4221853036247602e-14 281.8845143757186 240.7636832942205 3.2308347579591112e-14 273.26685191414902 + 0 4 1 4 +7 0 0 3 4 2 240.7636832942205 3.2308347579591112e-14 273.26685191414902 238.42942074787516 3.13295530774792e-14 268.85875335916552 236.25902795652735 2.8326456680894604e-14 255.33400954654945 235.9409148023226 2.5634787680327286e-14 243.21181003858976 + 0 4 1 4 +7 0 0 3 4 2 235.9409148023226 2.5634787680327286e-14 243.21181003858976 234.70625957803875 1.5193354883291139e-14 196.18777718464369 216.40376800881543 -1.8002492547937848e-15 119.65538792068271 197.30445591181038 -1.0238532637674244e-14 81.65273802189563 + 0 4 1 4 +7 0 0 3 4 2 197.30445591181038 -1.0238532637674244e-14 81.65273802189563 192.20897404769724 -1.2489779048820233e-14 71.514025523539388 189.35494550326314 -1.5786294648719784e-14 56.667839096210749 188.83479330665077 -2.0021427742321518e-14 37.594495274001517 + 0 4 1 4 +7 0 0 3 7 5 188.83479330665099 0 37.59449527400151 188.81804729658259 0 35.534995369910682 188.70749328063036 0 25.873575373538852 190.29694653857658 0 14.401661807644173 191.79999019372644 0 2.9725203999948375 194.1810244269208 -0 0.60917767764141784 195.05400824628035 0 3.5527136788005009e-15 + 0 4 6.2015166049759678 1 28.786223226349559 1 35.840755101499639 1 38.844696203109706 4 +1 278.80099487304688 0 2.4435839150736544e-14 1 -0 1.0674428405159396e-16 +7 0 0 3 7 5 278.80099487304688 0 7.3642018522178214e-15 280.65353933455947 2.9296309821036178e-08 3.0815257281628301 284.03854381717974 1.6924406321842872e-07 11.187324704010971 284.1043624062587 -2.6527270512866986e-06 44.59788375423657 289.39134817071442 3.4670464907071287e-05 81.308826491441479 293.35558706318221 1.0845452680844131e-05 113.11269747539635 294.510652894126 0 120.98820193636621 + 0 4 10.425398347995852 1 26.347595555611093 1 98.54052204492578 1 122.41410138806857 4 +7 0 0 3 4 2 294.51065289412639 -1.5043050932427195e-15 120.98820193636656 296.78271602270831 2.4108411547240534e-15 138.62045311981072 303.01646082035955 8.7380212486782325e-15 167.11553903324878 308.3633793787709 1.255607570636154e-14 184.31052766615159 + 0 4 1 4 +7 0 0 3 4 2 308.3633793787709 1.255607570636154e-14 184.31052766615159 313.71029793718219 1.6374146044285328e-14 201.5055878172995 318.08506898994915 2.0478378315625602e-14 219.98940674514952 318.08506898994915 2.1676590100424269e-14 225.38567289267974 + 0 4 1 4 +7 0 0 3 4 2 318.08506898994915 2.1676590100424269e-14 225.38567289267974 318.08506898994915 2.2874817765463466e-14 230.78201055845528 319.83934002400707 2.3855184411382721e-14 235.1971894197037 321.98338549385994 2.3855184411382721e-14 235.1971894197037 + 0 4 1 4 +7 0 0 3 4 2 321.98338549385994 2.3855184411382721e-14 235.1971894197037 329.14786873324272 2.3855184411382721e-14 235.1971894197037 337.49768106326377 2.8803086218606225e-14 257.48055815498128 340.09794141860959 3.4589385321874237e-14 283.53973264031333 + 0 4 1 4 +7 0 0 3 4 2 340.09794141860959 3.4589385321874237e-14 283.53973264031333 341.51350204387387 3.7739342182400807e-14 297.72587718361393 345.5131599010914 4.3519908518856244e-14 323.75923358246507 348.98615740139246 4.743505476682302e-14 341.39148476590924 + 0 4 1 4 +7 0 0 3 4 2 348.98615740139246 4.743505476682302e-14 341.39148476590924 355.25208540933869 5.4498839815356713e-14 373.20394447831086 356.65799107151457 6.5468179446608342e-14 422.60545835411614 354.17509215637784 8.7921251458680284e-14 523.72510510100619 + 0 4 1 4 +7 0 0 3 4 2 354.17509215637784 8.7921251458680284e-14 523.72510510100619 352.53932685445068 1.0271371134432778e-13 590.34442192990127 362.06047930636856 1.170340040398381e-13 654.83728677723798 383.10071790531794 1.3142677415289077e-13 719.65656089521121 + 0 4 1 4 +7 0 0 3 4 2 383.10071790531794 1.3142677415289077e-13 719.65656089521121 398.66752217027414 1.4207539644744547e-13 767.61369229297702 399.50693181301278 1.4320846748580277e-13 772.71659059910712 399.64853793831082 1.5376692177492248e-13 820.26764140119508 + 0 4 1 4 +7 0 0 3 4 2 399.64853793831082 1.5376692177492248e-13 820.26764140119508 399.92230978055363 1.7417231617853792e-13 912.16536803366557 390.88361941008037 1.96941960784542e-13 1014.7107309966243 381.19954839582459 2.0024211295951104e-13 1029.5732951020807 + 0 4 1 4 +7 0 0 3 4 2 381.19954839582459 2.0024211295951104e-13 1029.5732951020807 367.31435262790467 2.0497393233454819e-13 1050.8835150762825 370.07552903472543 2.236300388482918e-13 1134.9031494197625 385.61687280442607 2.300881594651087e-13 1163.9879390231727 + 0 4 1 4 +7 0 0 3 4 2 385.61687280442607 2.300881594651087e-13 1163.9879390231727 388.08496744282712 2.3111375303590977e-13 1168.6068018464659 390.10435661147068 2.3317705680099679e-13 1177.899095914064 390.10435661147068 2.3467326129836811e-13 1184.6374019308955 + 0 4 1 4 +7 0 0 3 4 2 390.10435661147068 2.3467326129836811e-13 1184.6374019308955 390.10435661147068 2.3646318672362355e-13 1192.6985094090969 392.92060206701854 2.3777664141357232e-13 1198.6137834613182 398.33818065158857 2.3851343693103754e-13 1201.9320154792229 + 0 4 1 4 +7 0 0 3 4 2 398.33818065158857 2.3851343693103754e-13 1201.9320154792229 410.9852525603373 2.4023344165746766e-13 1209.678228124249 426.42804418829007 2.4789223867240538e-13 1244.1703835068288 430.19955884363856 2.5431504004637478e-13 1273.0961093813121 + 0 4 1 4 +7 0 0 3 4 2 430.19955884363856 2.5431504004637478e-13 1273.0961093813121 432.06747236916044 2.5749609835787784e-13 1287.4223224076411 435.68572342525965 2.6230105259241317e-13 1309.0619125078267 438.24006906725123 2.6499271682890839e-13 1321.1840905603131 + 0 4 1 4 +7 0 0 3 4 2 438.24006906725123 2.6499271682890839e-13 1321.1840905603131 440.7944147092428 2.6768438106540355e-13 1333.3062686127992 442.17843578841803 2.7238228342282747e-13 1354.4637399191165 441.31578271602183 2.7543250443303099e-13 1368.2007141240667 + 0 4 1 4 +7 0 0 3 4 2 441.31578271602183 2.7543250443303099e-13 1368.2007141240667 440.00142040757402 2.800799108017824e-13 1389.1307717146149 437.86652927309399 2.8141494038644476e-13 1395.1432104546288 428.13775935565076 2.836732519165795e-13 1405.3137414202301 + 0 4 1 4 +7 0 0 3 4 2 428.13775935565076 2.836732519165795e-13 1405.3137414202301 421.50258264825322 2.8521345262019559e-13 1412.2501887351114 407.28961876303993 2.8701579956955308e-13 1420.3672377846301 394.96681057757468 2.8787966877132453e-13 1424.2577587998248 + 0 4 1 4 +7 0 0 3 4 2 394.96681057757468 2.8787966877132453e-13 1424.2577587998248 376.81240468665544 2.8915234935582156e-13 1429.9894026059274 372.15134609875315 2.8993786227502566e-13 1433.5270382961496 365.46882431309933 2.9285095264462809e-13 1446.6464309991877 + 0 4 1 4 +7 0 0 3 4 2 365.46882431309933 2.9285095264462809e-13 1446.6464309991877 359.42689144880626 2.9548477786925372e-13 1458.5081252993707 355.68913340514501 2.9620353819760796e-13 1461.7451340463156 349.81183554107207 2.9586173348958005e-13 1460.2057824906076 + 0 4 1 4 +7 0 0 3 4 2 349.81183554107207 2.9586173348958005e-13 1460.2057824906076 341.39270772790007 2.953721043870131e-13 1458.0006890467373 339.572568390105 2.9695074797677877e-13 1465.1102677293568 345.58103071569133 2.9953121400537373e-13 1476.7316535741793 + 0 4 1 4 +7 0 0 3 4 2 345.58103071569133 2.9953121400537373e-13 1476.7316535741793 349.13198310315141 3.0105625860747751e-13 1483.5998438759373 346.02794822932128 3.0947768987916252e-13 1521.5265986130241 337.92342917634414 3.2030667359297201e-13 1570.2960056313377 + 0 4 1 4 +7 0 0 3 4 2 337.92342917634414 3.2030667359297201e-13 1570.2960056313377 335.48259729297524 3.2356800810811626e-13 1584.9837505384719 333.17127064783347 3.2900396528607529e-13 1609.4651252595302 332.78721767164643 3.3238657560972718e-13 1624.6990478526684 + 0 4 1 4 +7 0 0 3 4 2 332.78721767164643 3.3238657560972718e-13 1624.6990478526684 332.22758740373894 3.3731493995709041e-13 1646.8944276909995 330.11529603471047 3.3917685210045742e-13 1655.2797345260637 322.15488624560982 3.417586234848197e-13 1666.9069991706335 + 0 4 1 4 +7 0 0 3 4 2 322.15488624560982 3.417586234848197e-13 1666.9069991706335 297.8371095102176 3.496455226859617e-13 1702.4264354740053 256.10735778628919 3.5080422284442669e-13 1707.6447570759024 216.24936726946899 3.4469927877584415e-13 1680.1505332435163 + 0 4 1 4 +7 0 0 3 4 2 216.24936726946899 3.4469927877584415e-13 1680.1505332435163 185.77369083535413 3.4003140118909229e-13 1659.1282814832095 179.93233088944396 3.3705401172579374e-13 1645.7193114057613 163.53334747632863 3.1782947994425463e-13 1559.1397172380496 + 0 4 1 4 +7 0 0 3 4 2 163.53334747632863 3.1782947994425463e-13 1559.1397172380496 161.06700503493263 3.149381899687806e-13 1546.1185047818847 170.43675336197381 3.0422878764181974e-13 1497.887644452823 179.78681271613897 2.9925212671909031e-13 1475.4747561756694 + 0 4 1 4 +7 0 0 3 4 2 179.78681271613897 2.9925212671909031e-13 1475.4747561756694 183.24425499813083 2.9741187204768745e-13 1467.1869859232727 188.94418046253119 2.9616731060500515e-13 1461.581979473769 195.62188907028974 2.9579458071667006e-13 1459.9033532875533 + 0 4 1 4 +7 0 0 3 4 2 195.62188907028974 2.9579458071667006e-13 1459.9033532875533 209.89326190627611 2.9499799768182862e-13 1456.3158622286717 208.72255114493612 2.9377737093759498e-13 1450.8186480781826 193.05163777058786 2.9311472502699444e-13 1447.8343562021234 + 0 4 1 4 +7 0 0 3 4 2 193.05163777058786 2.9311472502699444e-13 1447.8343562021234 183.32863937552418 2.9270358718903886e-13 1445.9827559883088 177.7599498908823 2.9167349157006223e-13 1441.3436177425297 170.97801774453953 2.8903154995452821e-13 1429.445370467276 + 0 4 1 4 +7 0 0 3 4 2 170.97801774453953 2.8903154995452821e-13 1429.445370467276 163.6506946128886 2.8617717518606973e-13 1416.5904093236707 156.21458507861612 2.8491324143802817e-13 1410.8981577669697 132.27946671363145 2.824538701831994e-13 1399.8221343001571 + 0 4 1 4 +7 0 0 3 4 2 132.27946671363145 2.824538701831994e-13 1399.8221343001571 111.3493018457155 2.8030326956015585e-13 1390.1366901355955 100.93091724989557 2.7866473523145086e-13 1382.7573875434059 96.791813118382052 2.768725945126487e-13 1374.686303270013 + 0 4 1 4 +7 0 0 3 4 2 96.791813118382052 2.768725945126487e-13 1374.686303270013 87.962892912611466 2.7304990620079389e-13 1357.4704456131901 79.328902835685597 2.6468686339729892e-13 1319.8066491596867 73.962745869342385 2.5475994403965901e-13 1275.0997788396826 + 0 4 1 4 +7 0 0 3 4 2 73.962745869342385 2.5475994403965901e-13 1275.0997788396826 68.414903953147174 2.4449679393839905e-13 1228.8786598680008 52.180720032215795 2.2115570681890857e-13 1123.7597486142413 46.247487748650187 2.1491154862217423e-13 1095.6385600861861 + 0 4 1 4 +7 0 0 3 4 2 46.247487748650187 2.1491154862217423e-13 1095.6385600861861 44.023134441374538 2.1257065825352901e-13 1085.0961270942403 40.292699866011439 2.0716508791572488e-13 1060.7516025351806 37.95759340437391 2.0289916303583595e-13 1041.5395848357223 + 0 4 1 4 +7 0 0 3 4 2 37.95759340437391 2.0289916303583595e-13 1041.5395848357223 35.622451183613762 1.986332222757066e-13 1022.3274956180192 29.883112014338799 1.9033797221881296e-13 984.96901055284798 25.20345868271049 1.8446523696662229e-13 958.52056225943647 + 0 4 1 4 +7 0 0 3 4 2 25.20345868271049 1.8446523696662229e-13 958.52056225943647 20.523812502906669 1.7859251759467212e-13 932.07218548427022 16.316172437113885 1.7171249868895173e-13 901.0873349041658 15.853163318336479 1.6917628136242509e-13 889.66522749748992 + 0 4 1 4 +7 0 0 3 4 2 15.853163318336479 1.6917628136242509e-13 889.66522749748992 15.307293160786207 1.6618614324207068e-13 876.19884257287549 10.614358891042817 1.6247537568905784e-13 859.48703120386836 2.5043472368420452 1.5862114604356528e-13 842.12912400862774 + 0 4 1 4 +7 0 0 3 4 2 2.5043472368420452 1.5862114604356528e-13 842.12912400862774 -11.574097981162561 1.5193049900554695e-13 811.99712850134074 -11.595059978801398 1.518985479617049e-13 811.85323379219972 -5.7611808413286978 1.4602490753580697e-13 785.4007089588174 + 0 4 1 4 +7 0 0 3 4 2 -5.7611808413286978 1.4602490753580697e-13 785.4007089588174 -2.1578985539289199 1.4239711423929252e-13 769.06258042045783 1.0809267564412337 1.413863369328576e-13 764.51044411984299 15.763493742630054 1.3930756581354487e-13 755.14849128151764 + 0 4 1 4 +7 0 0 3 4 2 15.763493742630054 1.3930756581354487e-13 755.14849128151764 35.803099118911845 1.3647035440899517e-13 742.37082705721627 38.010166466346867 1.3636646587578702e-13 741.90295469777197 38.010166466346867 1.3826054979833875e-13 750.43315034558441 + 0 4 1 4 +7 0 0 3 4 2 38.010166466346867 1.3826054979833875e-13 750.43315034558441 38.010166466346867 1.3911315990961122e-13 754.27296492500341 40.74774185228469 1.3954502304941482e-13 756.21790360049795 45.012038671845701 1.3936513168527821e-13 755.40774492000514 + 0 4 1 4 +7 0 0 3 4 2 45.012038671845701 1.3936513168527821e-13 755.40774492000514 50.232119622572149 1.3914492039056756e-13 754.41600141520348 52.294991884236559 1.3805275685168204e-13 749.49733410845101 53.11844580649344 1.3507330613316944e-13 736.07908096278879 + 0 4 1 4 +7 0 0 3 4 2 53.11844580649344 1.3507330613316944e-13 736.07908096278879 55.334681792950306 1.2705434050011482e-13 699.9648703258672 66.579209397042902 1.094987981724697e-13 620.90173644079778 76.427765223204091 9.8681543604277395e-14 572.18515279831513 + 0 4 1 4 +7 0 0 3 4 2 76.427765223204091 9.8681543604277395e-14 572.18515279831513 82.594812105475143 9.1907938190001114e-14 541.67954597862558 85.391204096183145 8.6706174858493731e-14 518.25288657717942 83.615563410489372 8.5310968690563454e-14 511.96943659918367 + 0 4 1 4 +7 0 0 3 4 2 83.615563410489372 8.5310968690563454e-14 511.96943659918367 82.017137784328852 8.4054952830424254e-14 506.31284403948933 80.957459098506703 8.2758601159470502e-14 500.4745951372409 81.260338866505194 8.2430197786382157e-14 498.99559782857295 + 0 4 1 4 +7 0 0 3 4 2 81.260338866505194 8.2430197786382157e-14 498.99559782857295 81.563418885589968 8.2101778533053326e-14 497.51652900165993 78.308788043052672 7.8297857489395553e-14 480.385191606896 74.027841776032346 7.3977034618173665e-14 460.92593533412725 + 0 4 1 4 +7 0 0 3 4 2 74.027841776032346 7.3977034618173665e-14 460.92593533412725 69.746895509012006 6.9656211746951802e-14 441.46667906135849 64.269313116803005 5.9914589387307223e-14 397.59431223247913 61.855507978257428 5.2328995516901658e-14 363.43183450433668 + 0 4 1 4 +7 0 0 3 4 2 61.855507978257428 5.2328995516901658e-14 363.43183450433668 59.441659928764757 4.4743385766255613e-14 329.26928525794915 55.650928320957881 3.5333692193085581e-14 286.89179278815004 53.431652809084319 3.1418530064878319e-14 269.25947008646074 + 0 4 1 4 +7 0 0 3 4 2 53.431652809084319 3.1418530064878319e-14 269.25947008646074 47.802187119756439 2.1487170592000714e-14 224.53260326512671 46.682046909526733 1.8986159758614186e-14 213.26905180783757 44.529991396222627 1.1542805202171476e-14 179.7471630010557 + 0 4 1 4 +7 0 0 3 4 2 44.529991396222627 1.1542805202171476e-14 179.7471630010557 42.881553061263666 5.8413701040187348e-15 154.07018201753795 40.483431873868511 4.206642268956339e-15 146.70802234869876 25.602566249490934 -1.3593820186391022e-15 121.6408774411488 + 0 4 1 4 +7 0 0 3 4 2 25.602566249490934 -1.3593820186391022e-15 121.6408774411488 16.230658071447696 -4.8648498227502738e-15 105.85365394479446 4.9626510274887412 -9.3717097111738205e-15 85.556561430679139 0.56251245318479559 -1.1374620921722352e-14 76.536251249196582 + 0 4 1 4 +7 0 0 3 4 2 0.56251245318479559 -1.1374620921722352e-14 76.536251249196582 -5.6474310724972234 -1.4201383128037438e-14 63.805646030170962 -11.082245554136431 -1.5296532152132849e-14 58.873533293339712 -23.724182452886939 -1.6268561671801081e-14 54.495901510768725 + 0 4 1 4 +7 0 0 3 4 2 -23.724182452886939 -1.6268561671801081e-14 54.495901510768725 -37.629782376133896 -1.733774650271472e-14 49.680721104675882 -40.563732559467269 -1.8018802376101594e-14 46.613518127072261 -43.793675303796022 -2.0927268419676802e-14 33.514951537007221 + 0 4 1 4 +7 0 0 3 4 2 -43.793675303796022 -2.0927268419676802e-14 33.514951537007221 -48.471047203405611 -2.5139057559775632e-14 14.546739535095025 -44.09603298860528 -2.6930872733647987e-14 6.4771213857266847 -25.623256477798822 -2.8369082592793141e-14 1.3322676295501878e-15 + 0 4 1 4 +1 0 0 0 1 3.0616169978683836e-17 -3.0616169978683818e-17 +7 0 0 3 9 7 117.85780334472656 -8.4703294725430034e-22 3.6639968674107709e-15 123.49837607882323 8.7393675794295915e-08 0.43053728442160866 134.75961322403282 1.4963320673300469e-07 5.5279970558758684 131.32369483069974 -2.2278472433766349e-06 40.12852314570037 125.2821326243639 2.1306848920662667e-05 84.255659692741347 124.04462184692069 1.1633085274635299e-05 130.71338654050848 128.61827710101142 1.3608574502573682e-05 162.95891714097738 130.29708433924711 5.782682051221206e-06 171.6450635956034 131.21597610534599 0 175.7974963971632 + 0 4 12.959615782738467 1 37.514705781905263 1 86.558124950630912 1 157.90450709093241 1 171.66995756583 1 184.42275453323856 4 +Polygon3D 74 +4 1 +3.6510390343707 +131.215976105346 5.33290152070746e-15 175.797496397163 136.019235548183 1.83673760154439e-14 210.482297572673 135.9016950205 1.85254620503788e-14 211.194253780698 135.725265825321 1.86283144196793e-14 211.657459672754 +0 0.888888888888889 0.944444444444444 1 +6 1 +3.6510390343707 +135.725265825321 1.86283144196793e-14 211.657459672754 135.53671573252 1.87302323195849e-14 212.116457088791 135.445823122956 1.88649798679732e-14 212.723306097502 135.597855569247 1.9277039995383e-14 214.579059933759 137.802374997773 2.07381925139791e-14 221.15950587204 142.100888517602 2.25431113023556e-14 229.288137454806 +0 0.0642964565687631 0.12962962962963 0.278426521014584 0.639213260507292 1 +4 1 +3.6510390343707 +142.100888517602 2.25431113023556e-14 229.288137454806 147.288863603691 2.50799532516743e-14 240.713057912456 151.214328698324 2.85334556155275e-14 256.266249871428 153.966502017616 3.29820985423581e-14 276.301156499007 +0 0.333333333333333 0.666666666666667 1 +2 1 +3.6510390343707 +153.966502017616 3.29820985423581e-14 276.301156499007 163.575671973779 4.56554356176378e-14 333.376792628777 +0 1 +2 1 +3.6510390343707 +163.575671973779 4.56554356176378e-14 333.376792628777 173.812571870833 6.30066627712909e-14 411.51977277239 +0 1 +3 1 +3.6510390343707 +173.812571870833 6.30066627712909e-14 411.51977277239 178.860583499761 7.33837746393004e-14 458.25412991434 186.047083630898 8.08027907421802e-14 491.666408070725 +0 0.5 1 +3 1 +3.6510390343707 +186.047083630898 8.08027907421802e-14 491.666408070725 193.777013359471 8.91788990135285e-14 529.389046160384 200.153456723614 1.03047958645912e-13 591.849737952766 +0 0.5 1 +7 1 +3.6510390343707 +200.153456723614 1.03047958645912e-13 591.849737952766 208.404071459725 1.22151488950098e-13 677.884389912158 212.263822235657 1.27944804170714e-13 703.975162180965 213.940745623906 1.29585292916927e-13 711.363266687115 214.698319380532 1.30073226611712e-13 713.560724693131 215.057972094571 1.30234128603745e-13 714.285362844494 215.404100282457 1.30338278949556e-13 714.754414303077 +0 0.5 0.753282659160131 0.877517971909646 0.938758985954823 0.969379492977411 1 +6 1 +3.6510390343707 +215.404100282457 1.30338278949556e-13 714.754414303077 215.849295577011 1.30363999493147e-13 714.870249333608 216.323537289962 1.30249849758405e-13 714.356164630763 217.348484159465 1.29604657301685e-13 711.450476123095 219.61163396486 1.26718594500835e-13 698.452804768621 224.098544731966 1.15950145866723e-13 649.956023512673 +0 0.0607003581242926 0.122066998402518 0.246534991237423 0.5 1 +2 1 +3.6510390343707 +224.098544731966 1.15950145866723e-13 649.956023512673 234.12066818716 9.94887362277823e-14 575.820425196748 +0 1 +3 1 +3.6510390343707 +234.12066818716 9.94887362277823e-14 575.820425196748 246.977071317382 8.14524295448111e-14 494.592121140179 251.872834012163 6.61209843721845e-14 425.545430373687 +0 0.5 1 +3 1 +3.6510390343707 +251.872834012163 6.61209843721845e-14 425.545430373687 248.070790005938 4.55667980703789e-14 332.977604603971 240.76368329422 3.23083475795911e-14 273.266851914149 +0 0.5 1 +4 1 +3.6510390343707 +240.76368329422 3.23083475795911e-14 273.266851914149 239.100625420756 3.125729929975e-14 268.533351272708 237.596243026219 2.961389556688e-14 261.132118833735 235.940914802323 2.56347876803273e-14 243.21181003859 +0 0.245265387793594 0.5 1 +4 1 +3.6510390343707 +235.940914802323 2.56347876803273e-14 243.21181003859 229.619611011843 1.35688345139139e-14 188.871587854461 215.535530950771 4.91987585968694e-16 129.978704902586 197.30445591181 -1.02385326376742e-14 81.6527380218956 +0 0.333333333333333 0.666666666666667 1 +4 1 +3.6510390343707 +197.30445591181 -1.02385326376742e-14 81.6527380218956 192.959548229373 -1.28342520489584e-14 69.9626570484779 190.129481210754 -1.61031172094002e-14 55.2409971299879 188.834793306651 -1.0010713871068e-14 37.5944952740015 +0 0.333333333333333 0.666666666666667 1 +5 1 +3.6510390343707 +188.834793306651 -1.0010713871068e-14 37.5944952740015 192.314095099058 0 3.23953892928056 193.269397803583 0 1.65727089078675 194.081685301692 0 0.780639362383997 195.05400824628 0 9.52452034608454e-15 +0 34.5286188472086 36.4333424534991 37.6390193283044 38.8446962031097 +2 1 +3.6510390343707 +195.05400824628 0 9.52452034608454e-15 278.800994873047 0 1.5900020497641e-14 +-83.7469866267665 -0 +4 1 +3.6510390343707 +278.800994873047 0 1.5900020497641e-14 282.256280040111 3.52702463963436e-08 7.64438541674681 287.19179330861 1.47096384757817e-05 64.5007690572978 294.510652894126 -7.5215254661846e-16 120.988201936366 +0 8.3458399805105 65.3799706842895 122.414101388069 +2 1 +3.6510390343707 +294.510652894126 -7.5215254661846e-16 120.988201936366 308.363379378771 1.25560757063615e-14 184.310527666152 +0 1 +2 1 +3.6510390343707 +308.363379378771 1.25560757063615e-14 184.310527666152 318.085068989949 2.16765901004243e-14 225.38567289268 +0 1 +8 1 +3.6510390343707 +318.085068989949 2.16765901004243e-14 225.38567289268 318.619289090255 2.27739564766161e-14 230.327771695586 319.571953244797 2.33852612903298e-14 233.080843826837 320.202978840025 2.36131474364121e-14 234.107151789416 320.62102176004 2.37171138427243e-14 234.575374858143 321.053473598987 2.37921358716276e-14 234.913244039556 321.515976861684 2.38394971016288e-14 235.126540057342 321.98338549386 2.38551844113827e-14 235.197189419704 +0 0.333333333333333 0.576333333333333 0.701333333333333 0.776776001 0.850666666666667 0.926258667666667 1 +10 1 +3.6510390343707 +321.98338549386 2.38551844113827e-14 235.197189419704 322.876915240473 2.38802288254672e-14 235.309979433642 323.779649352541 2.39542030340645e-14 235.643129651916 324.688653987115 2.40753684866903e-14 236.188810339212 325.905343473003 2.43073261232753e-14 237.233454664902 327.726287448028 2.47977568504192e-14 239.442158304918 330.402047826145 2.58264880044003e-14 244.075151546652 334.133686095777 2.79361223362165e-14 253.576099937307 337.702993241132 3.10260380638319e-14 267.491843256802 340.09794141861 3.45893853218742e-14 283.539732640313 +0 0.0413125686141469 0.0826251372282939 0.123937705842441 0.179021130661303 0.261646267889597 0.385583973732038 0.571490532495699 0.78574526624785 1 +2 1 +3.6510390343707 +340.09794141861 3.45893853218742e-14 283.539732640313 348.986157401392 4.7435054766823e-14 341.391484765909 +0 1 +3 1 +3.6510390343707 +348.986157401392 4.7435054766823e-14 341.391484765909 354.861434875041 6.19071705014248e-14 406.568099795525 354.175092156378 8.79212514586803e-14 523.725105101006 +0 0.5 1 +4 1 +3.6510390343707 +354.175092156378 8.79212514586803e-14 523.725105101006 358.637373875653 1.0741254369133e-13 611.506081536937 368.22587834058 1.19437902614531e-13 665.663483502462 383.100717905318 1.31426774152891e-13 719.656560895211 +0 0.444444444444444 0.722222222222222 1 +3 1 +3.6510390343707 +383.100717905318 1.31426774152891e-13 719.656560895211 397.159077224186 1.42630660965945e-13 770.114381371582 399.648537938311 1.53766921774922e-13 820.267641401195 +0 0.5 1 +5 1 +3.6510390343707 +399.648537938311 1.53766921774922e-13 820.267641401195 395.255966985195 1.80458334558471e-13 940.475078067177 384.391780079656 1.98450920186504e-13 1021.50647999702 382.806098359735 1.99515558301981e-13 1026.30118381717 381.199548395825 2.00242112959511e-13 1029.57329510208 +0 0.444444444444444 0.888888888888889 0.944444444444444 1 +7 1 +3.6510390343707 +381.199548395825 2.00242112959511e-13 1029.57329510208 377.818576540473 2.01860748173231e-13 1036.86298004744 374.567777503237 2.0489147679969e-13 1050.51216836022 372.210116332175 2.12263736777086e-13 1083.7138756473 374.496192756584 2.20562347974791e-13 1121.08749794498 378.943854828017 2.25976451821394e-13 1145.47045401108 385.616872804426 2.30088159465109e-13 1163.98793902317 +0 0.0910289570470168 0.212400899776372 0.437584185009217 0.667545685011456 0.833772842505728 1 +4 1 +3.6510390343707 +385.616872804426 2.30088159465109e-13 1163.98793902317 387.877225482579 2.31400219046524e-13 1169.89693006512 389.489400358919 2.3304746109924e-13 1177.31544875992 390.104356611471 2.34673261298368e-13 1184.6374019309 +0 0.333333333333333 0.666666666666667 1 +6 1 +3.6510390343707 +390.104356611471 2.34673261298368e-13 1184.6374019309 390.858940251652 2.36152841994761e-13 1191.30084100384 392.561049970721 2.37151548586547e-13 1195.79861563846 394.710869014512 2.37840493986219e-13 1198.9013498837 396.396829602372 2.38204358911804e-13 1200.54005182697 398.338180651589 2.38513436931038e-13 1201.93201547922 +0 0.3 0.543 0.7455 0.87275 1 +6 1 +3.6510390343707 +398.338180651589 2.38513436931038e-13 1201.93201547922 402.568425159978 2.39281341075156e-13 1205.39034829653 406.885749858225 2.40419032998551e-13 1210.51405721879 414.402602378686 2.43170769050092e-13 1222.90677467514 421.298627526101 2.46649704449245e-13 1238.57450684241 430.199558843639 2.54315040046375e-13 1273.09610938131 +0 0.10935 0.2187 0.412552655550429 0.60935 1 +2 1 +3.6510390343707 +430.199558843639 2.54315040046375e-13 1273.09610938131 438.240069067251 2.64992716828908e-13 1321.18409056031 +0 1 +2 1 +3.6510390343707 +438.240069067251 2.64992716828908e-13 1321.18409056031 441.315782716022 2.75432504433031e-13 1368.20071412407 +0 1 +5 1 +3.6510390343707 +441.315782716022 2.75432504433031e-13 1368.20071412407 438.482417813552 2.80038011124927e-13 1388.94207234554 436.843791621101 2.81019855131678e-13 1393.36390464848 434.632401705855 2.8191426344757e-13 1397.39196160665 428.137759355651 2.83673251916579e-13 1405.31374142023 +0 0.444444444444444 0.582586562862472 0.722222222222222 1 +4 1 +3.6510390343707 +428.137759355651 2.83673251916579e-13 1405.31374142023 419.327318140002 2.85256367146801e-13 1412.44345858114 407.569006111935 2.86747441209e-13 1419.15865917204 394.966810577575 2.87879668771325e-13 1424.25775879982 +0 0.333333333333333 0.666666666666667 1 +6 1 +3.6510390343707 +394.966810577575 2.87879668771325e-13 1424.25775879982 380.735564509855 2.8908680254575e-13 1429.69420601651 375.915860905862 2.89750157038562e-13 1432.68168906316 371.30475304018 2.90747083362659e-13 1437.17144608488 368.367779866441 2.9168360801445e-13 1441.38917815771 365.468824313099 2.92850952644628e-13 1446.64643099919 +0 0.333333333333333 0.5 0.7025 0.85125 1 +8 1 +3.6510390343707 +365.468824313099 2.92850952644628e-13 1446.64643099919 360.030367698608 2.94878071046789e-13 1455.77576067979 357.578591802003 2.95472204291849e-13 1458.45149894086 355.755513790692 2.95753776395339e-13 1459.71958696121 354.361943502366 2.95879443830363e-13 1460.28554277476 352.783584872167 2.95938488822934e-13 1460.5514577813 351.339457629381 2.95927351393698e-13 1460.50129925914 349.811835541072 2.9586173348958e-13 1460.20578249061 +0 0.333333333333333 0.5 0.625 0.71875 0.821265625 0.9106328125 1 +14 1 +3.6510390343707 +349.811835541072 2.9586173348958e-13 1460.20578249061 347.845244096055 2.9578179806965e-13 1459.8457853632 346.157879994416 2.95784337726299e-13 1459.85722295993 344.998734208479 2.95844310669022e-13 1460.12731708244 344.093269865929 2.95944211544874e-13 1460.57723062969 343.417848120518 2.96069273137663e-13 1461.14045797238 342.924087273101 2.96209323415692e-13 1461.77118835232 342.539431580227 2.96374560484622e-13 1462.51534995438 342.264838268747 2.96564154136364e-13 1463.36920385372 342.071576468432 2.96853398762165e-13 1464.6718458427 342.092898759278 2.97226342245543e-13 1466.35143397547 342.519947991169 2.97797225349968e-13 1468.92246291183 343.689242922394 2.98610775510635e-13 1472.58636711226 345.581030715691 2.99531214005374e-13 1476.73165357418 +0 0.0833333333333333 0.166666666666667 0.234166666666667 0.296666666666667 0.352916666666667 0.403541666666667 0.454166666666667 0.504791666666667 0.572291666666666 0.648229166666666 0.749479166666666 0.874739583333333 1 +4 1 +3.6510390343707 +345.581030715691 2.99531214005374e-13 1476.73165357418 346.243160774565 2.99964290039778e-13 1478.68205464135 345.811077151592 3.07233237168369e-13 1511.41848222104 337.923429176344 3.20306673592972e-13 1570.29600563134 +0 0.071744535 0.5358722675 1 +2 1 +3.6510390343707 +337.923429176344 3.20306673592972e-13 1570.29600563134 332.787217671646 3.32386575609727e-13 1624.69904785267 +0 1 +4 1 +3.6510390343707 +332.787217671646 3.32386575609727e-13 1624.69904785267 330.743843893178 3.37472977154295e-13 1647.60616395344 327.526896511865 3.3969262762006e-13 1657.60258096395 322.15488624561 3.4175862348482e-13 1666.90699917063 +0 0.444444444444444 0.722222222222222 1 +9 1 +3.6510390343707 +322.15488624561 3.4175862348482e-13 1666.90699917063 311.055116244793 3.44656410478809e-13 1679.95747159696 298.247113790334 3.4676535902824e-13 1689.45533149832 284.041750954222 3.48076837250149e-13 1695.36170432982 268.74989980845 3.48582213261576e-13 1697.63771554656 252.682432425008 3.48272855179559e-13 1696.24449060367 236.150220875886 3.47140131121136e-13 1691.14315495624 226.194172552493 3.46068680722717e-13 1686.31777134117 216.249367269469 3.44699278775844e-13 1680.15053324352 +0 0.139020792078109 0.278041584156217 0.417062376234326 0.556083168312435 0.695103960390543 0.834124752468652 0.917062376234326 1 +5 1 +3.6510390343707 +216.249367269469 3.44699278775844e-13 1680.15053324352 197.891528538365 3.41338475523699e-13 1665.01482096949 188.272143536723 3.38380568067525e-13 1651.69359005207 175.992152500346 3.30890655478587e-13 1617.96202250749 163.533347476329 3.17829479944255e-13 1559.13971723805 +0 0.243 0.420147 0.7100735 1 +5 1 +3.6510390343707 +163.533347476329 3.17829479944255e-13 1559.13971723805 163.13515729866 3.16502856103435e-13 1553.16513460288 163.647734515212 3.1456386121192e-13 1544.43267793198 167.228929422898 3.09322817436893e-13 1520.82911513973 179.786812716139 2.9925212671909e-13 1475.47475617567 +0 0.11791155500416 0.241150007067103 0.5 1 +6 1 +3.6510390343707 +179.786812716139 2.9925212671909e-13 1475.47475617567 183.469834328128 2.97764190421374e-13 1468.77368681972 187.650573781907 2.96737052305963e-13 1464.1478679859 191.531788111973 2.96145024883122e-13 1461.481613505 193.53962255258 2.95941585765421e-13 1460.56540517033 195.62188907029 2.9579458071667e-13 1459.90335328755 +0 0.3 0.57 0.7887 0.89435 1 +15 1 +3.6510390343707 +195.62188907029 2.9579458071667e-13 1459.90335328755 201.475095748618 2.95365498633388e-13 1457.97093937717 203.444744913161 2.95132979378513e-13 1456.92376574756 204.505997101646 2.94953521576733e-13 1456.11555965833 205.068875442363 2.94817047519269e-13 1455.50093514399 205.432634120872 2.94679635730721e-13 1454.88208746429 205.574434905425 2.9457715147109e-13 1454.42053939081 205.607196613637 2.94477767850526e-13 1453.97295535427 205.537858329229 2.94379437424689e-13 1453.53011448511 205.363791902563 2.94280084180353e-13 1453.08266725094 204.94558321919 2.94142457643011e-13 1452.46285242865 203.883353139011 2.93931577423467e-13 1451.51313235049 202.083574179697 2.93702278282843e-13 1450.48046082622 199.701117396457 2.93490034071775e-13 1449.52459787635 193.051637770588 2.93114725026994e-13 1447.83435620212 +0 0.166666666666667 0.25 0.3125 0.359375 0.40625 0.441125558415979 0.474966889241924 0.50854742700279 0.542655934397876 0.590359306988357 0.665016323289729 0.749511005709764 0.832508161644865 1 +6 1 +3.6510390343707 +193.051637770588 2.93114725026994e-13 1447.83435620212 186.622476802815 2.92691112168424e-13 1445.92657349012 181.712726145168 2.92051714874669e-13 1443.04698407622 177.714812613394 2.91213681960864e-13 1439.27281935788 174.372371932877 2.90248749203647e-13 1434.92714855204 170.97801774454 2.89031549954528e-13 1429.44537046728 +0 0.243 0.4617 0.65853 0.829265 1 +5 1 +3.6510390343707 +170.97801774454 2.89031549954528e-13 1429.44537046728 163.911518591787 2.86816813018194e-13 1419.47108202608 155.306906620656 2.85184846760976e-13 1412.12135939819 145.592510186271 2.83902074451818e-13 1406.34426650466 132.279466713631 2.82453870183199e-13 1399.82213430016 +0 0.3 0.57 0.785 1 +5 1 +3.6510390343707 +132.279466713631 2.82453870183199e-13 1399.82213430016 110.230205860727 2.7983140897847e-13 1388.01161899574 100.729706473999 2.78101091426963e-13 1380.21896151554 98.4885422784277 2.77489920760324e-13 1377.46649352901 96.7918131183821 2.76872594512649e-13 1374.68630327001 +0 0.444444444444444 0.768444444444444 0.884222222222222 1 +3 1 +3.6510390343707 +96.7918131183821 2.76872594512649e-13 1374.68630327001 84.0787432790769 2.68105355918323e-13 1335.20217080354 73.9627458693424 2.54759944039659e-13 1275.09977883968 +0 0.5 1 +2 1 +3.6510390343707 +73.9627458693424 2.54759944039659e-13 1275.09977883968 46.2474877486502 2.14911548622174e-13 1095.63856008619 +0 1 +2 1 +3.6510390343707 +46.2474877486502 2.14911548622174e-13 1095.63856008619 37.9575934043739 2.02899163035836e-13 1041.53958483572 +0 1 +2 1 +3.6510390343707 +37.9575934043739 2.02899163035836e-13 1041.53958483572 25.2034586827105 1.84465236966622e-13 958.520562259436 +0 1 +2 1 +3.6510390343707 +25.2034586827105 1.84465236966622e-13 958.520562259436 15.8531633183365 1.69176281362425e-13 889.66522749749 +0 1 +4 1 +3.6510390343707 +15.8531633183365 1.69176281362425e-13 889.66522749749 13.9519750021935 1.65967309999339e-13 875.213305262454 9.448296550752 1.6240617842341e-13 859.175394424081 2.50434723684205 1.58621146043565e-13 842.129124008628 +0 0.333333333333333 0.666666666666667 1 +5 1 +3.6510390343707 +2.50434723684205 1.58621146043565e-13 842.129124008628 -8.65667484019326 1.5254874972594e-13 814.781482215326 -9.4221963789386 1.5083290631735e-13 807.054010479774 -8.37395483455675 1.48798549184847e-13 797.892080455896 -5.7611808413287 1.46024907535807e-13 785.400708958817 +0 0.444444444444444 0.624444444444444 0.812222222222222 1 +6 1 +3.6510390343707 +-5.7611808413287 1.46024907535807e-13 785.400708958817 -1.84204352209256 1.43132971058098e-13 772.37658491543 0.846424688604787 1.42085353358225e-13 767.658534232655 6.00110124036718 1.40856887578927e-13 762.12601620677 10.3253128800827 1.40114063212218e-13 758.780632665657 15.7634937426301 1.39307565813545e-13 755.148491281518 +0 0.333333333333333 0.5 0.725 0.8625 1 +10 1 +3.6510390343707 +15.7634937426301 1.39307565813545e-13 755.148491281518 33.2873210689599 1.37079806648387e-13 745.115555935442 34.9983792073597 1.36988480260282e-13 744.704258448003 35.8202193382018 1.36989085169032e-13 744.706982714824 36.4898879990614 1.37033078886121e-13 744.905112802712 37.0344762634968 1.37125191719725e-13 745.319952125807 37.4411757268561 1.37265513739189e-13 745.951906320377 37.7147757761166 1.37445456755245e-13 746.762297620433 37.8932981495294 1.37676627236376e-13 747.803396913115 38.0101664663469 1.38260549798339e-13 750.433150345584 +0 0.444444444444444 0.534444444444444 0.59 0.64625 0.705208333333333 0.764903645833333 0.822657331260317 0.882451822916667 1 +10 1 +3.6510390343707 +38.0101664663469 1.38260549798339e-13 750.433150345584 38.1908661728086 1.38615179277415e-13 752.030259535407 38.5913123202227 1.38858135506089e-13 753.124437116329 39.1526199054027 1.39045816210874e-13 753.969675868465 39.8865036202028 1.39195976662867e-13 754.645938424104 40.7826191771476 1.39306985090685e-13 755.145875938264 41.8306222887618 1.3937720972295e-13 755.462139565961 43.0201686675697 1.39405018788278e-13 755.587380462213 43.9824738661925 1.39397390720239e-13 755.553026697835 45.0120386718457 1.39365131685278e-13 755.407744920005 +0 0.15 0.2715 0.384 0.4965 0.609 0.7215 0.834 0.917 1 +8 1 +3.6510390343707 +45.0120386718457 1.39365131685278e-13 755.407744920005 46.7783754408968 1.39244427618986e-13 754.86414213203 48.1460398790327 1.39060729791478e-13 754.036840664514 49.2099981731111 1.38827763982795e-13 752.987655935339 50.1271775203883 1.38524698320419e-13 751.622769531194 51.2174808451832 1.37949768817659e-13 749.0335172368 52.0621088396674 1.37191261323724e-13 745.617503169758 53.1184458064934 1.35073306133169e-13 736.079080962789 +0 0.1215 0.23085 0.329265 0.42768 0.570189239 0.71384 1 +3 1 +3.6510390343707 +53.1184458064934 1.35073306133169e-13 736.079080962789 61.9109855749596 1.179267832194e-13 658.858006757637 76.4277652232041 9.86815436042774e-14 572.185152798315 +0 0.5 1 +5 1 +3.6510390343707 +76.4277652232041 9.86815436042774e-14 572.185152798315 83.0001721548335 8.99793564300407e-14 532.993985883114 84.1122245009134 8.70108012780178e-14 519.624802006635 84.0650585814093 8.59928976930914e-14 515.040571800862 83.6155634104894 8.53109686905635e-14 511.969436599184 +0 0.5 0.752686073375261 0.877219380724318 1 +5 1 +3.6510390343707 +83.6155634104894 8.53109686905635e-14 511.969436599184 81.7249616156876 8.35227285558287e-14 503.915918994743 81.2709927787598 8.28311035067902e-14 500.801116681613 81.2087928700088 8.25905411800635e-14 499.717720276608 81.2603388665052 8.24301977863822e-14 498.995597828573 +0 0.5 0.754975790856534 0.878754291453967 1 +3 1 +3.6510390343707 +81.2603388665052 8.24301977863822e-14 498.995597828573 79.3631001785582 7.97007675589878e-14 486.703336873546 74.0278417760323 7.39770346181737e-14 460.925935334127 +0 0.5 1 +2 1 +3.6510390343707 +74.0278417760323 7.39770346181737e-14 460.925935334127 61.8555079782574 5.23289955169017e-14 363.431834504337 +0 1 +2 1 +3.6510390343707 +61.8555079782574 5.23289955169017e-14 363.431834504337 53.4316528090843 3.14185300648783e-14 269.259470086461 +0 1 +2 1 +3.6510390343707 +53.4316528090843 3.14185300648783e-14 269.259470086461 44.5299913962226 1.15428052021715e-14 179.747163001056 +0 1 +4 1 +3.6510390343707 +44.5299913962226 1.15428052021715e-14 179.747163001056 40.8577540913619 5.6486356335167e-15 153.202183128004 35.3652436573471 2.5403742041399e-15 139.203818112892 25.6025662494909 -1.3593820186391e-15 121.640877441149 +0 0.444444444444444 0.722222222222222 1 +2 1 +3.6510390343707 +25.6025662494909 -1.3593820186391e-15 121.640877441149 0.562512453184796 -1.13746209217224e-14 76.5362512491966 +0 1 +5 1 +3.6510390343707 +0.562512453184796 -1.13746209217224e-14 76.5362512491966 -5.68469366748866 -1.36837525738825e-14 66.1368468009789 -10.9301609162909 -1.48444961926106e-14 60.9093222722021 -16.584578296638 -1.56189727381174e-14 57.4213899904504 -23.7241824528869 -1.62685616718011e-14 54.4959015107687 +0 0.333333333333333 0.576333333333333 0.788166666666667 1 +6 1 +3.6510390343707 +-23.7241824528869 -1.62685616718011e-14 54.4959015107687 -34.3898858813816 -1.73052420030841e-14 49.8271083571 -37.7623003204358 -1.79081845909909e-14 47.1116963428776 -39.996445876744 -1.85679242737973e-14 44.140492953229 -42.0523750951416 -1.95830791478908e-14 39.5686418405379 -43.793675303796 -2.09272684196768e-14 33.5149515370072 +0 0.333333333333333 0.5 0.6476225 0.82381125 1 +9 1 +3.6510390343707 +-43.793675303796 -2.09272684196768e-14 33.5149515370072 -45.3546375210037 -2.28410650140754e-14 24.8959779076108 -45.2667193807654 -2.44089317433112e-14 17.8349338900577 -44.0831225575265 -2.53668008764978e-14 13.5210748187691 -42.3313416158295 -2.60639360049034e-14 10.3814573142546 -40.0596748472589 -2.66394472099801e-14 7.78958526552382 -37.137738405088 -2.71581540675699e-14 5.45353725496758 -32.0437901228183 -2.77941194111739e-14 2.58940397049232 -25.6232564777988 -1.41845412970638e-14 -1.89470900020505e-15 +0 0.166666666666667 0.333333333333333 0.454833333333333 0.556083333333333 0.649833333333333 0.743583333333333 0.871791666666667 1 +2 1 +3.6510390343707 +-6.03961325396085e-14 3.22697663005884e-15 1.41845412970638e-14 143.481059822525 4.39284124883733e-15 -4.39284009273166e-15 +0 143.481059822525 +12 1 +3.6510390343707 +117.857803344727 -4.2351647362715e-22 3.66399613482157e-15 122.780967132141 6.18668535542194e-08 0.827881769042764 126.314216831932 7.1558497906994e-08 2.25935206559221 128.576818677177 4.06962240828973e-08 3.87984745904236 130.170628943486 -2.11306745813298e-08 5.68052802397271 131.36989624836 -1.11957605880745e-07 7.78510452838152 132.218286013982 -2.1608036440195e-07 10.1535312968658 132.882558070258 -3.46283133953284e-07 13.649125900968 133.098215023271 -4.41450416635233e-07 19.4135070186867 125.526905526465 1.50118258987236e-05 97.7928966983905 125.884872887108 1.31444255647522e-05 139.13460340653 131.215976105346 5.33290152070746e-15 175.797496397163 +0 4.18364260084207 7.94892094159993 10.9987963976138 13.7436843080263 16.4885722184388 19.2334601288512 22.8933106760679 28.3830864968929 106.402920515066 147.411751794371 184.422754533239 +PolygonOnTriangulations 0 +Surfaces 0 +Triangulations 0 + +TShapes 150 +Ve +1.00000260931117e-07 +131.215976105346 5.33290152070746e-15 175.797496397163 +0 0 + +0101101 +* +Ve +1e-07 +135.725265825321 1.86283144196793e-14 211.657459672754 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 1 0 0 1 +5 1 0 +0 + +0101000 ++150 0 -149 0 * +Ve +1e-07 +142.100888517602 2.25431113023556e-14 229.288137454806 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 2 0 0 1 +5 2 0 +0 + +0101000 ++149 0 -147 0 * +Ve +1e-07 +153.966502017616 3.29820985423581e-14 276.301156499007 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 3 0 0 1 +5 3 0 +0 + +0101000 ++147 0 -145 0 * +Ve +1e-07 +163.575671973779 4.56554356176378e-14 333.376792628777 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 4 0 0 1 +5 4 0 +0 + +0101000 ++145 0 -143 0 * +Ve +1e-07 +173.812571870833 6.30066627712909e-14 411.51977277239 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 5 0 0 1 +5 5 0 +0 + +0101000 ++143 0 -141 0 * +Ve +1e-07 +186.047083630898 8.08027907421802e-14 491.666408070725 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 6 0 0 1 +5 6 0 +0 + +0101000 ++141 0 -139 0 * +Ve +1e-07 +200.153456723614 1.03047958645912e-13 591.849737952766 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 7 0 0 1 +5 7 0 +0 + +0101000 ++139 0 -137 0 * +Ve +1e-07 +215.404100282457 1.30338278949556e-13 714.754414303077 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 8 0 0 1 +5 8 0 +0 + +0101000 ++137 0 -135 0 * +Ve +1e-07 +224.098544731966 1.15950145866723e-13 649.956023512673 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 9 0 0 1 +5 9 0 +0 + +0101000 ++135 0 -133 0 * +Ve +1e-07 +234.12066818716 9.94887362277823e-14 575.820425196748 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 10 0 0 1 +5 10 0 +0 + +0101000 ++133 0 -131 0 * +Ve +1e-07 +251.872834012163 6.61209843721845e-14 425.545430373687 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 11 0 0 1 +5 11 0 +0 + +0101000 ++131 0 -129 0 * +Ve +1e-07 +240.76368329422 3.23083475795911e-14 273.266851914149 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 12 0 0 1 +5 12 0 +0 + +0101000 ++129 0 -127 0 * +Ve +1e-07 +235.940914802323 2.56347876803273e-14 243.21181003859 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 13 0 0 1 +5 13 0 +0 + +0101000 ++127 0 -125 0 * +Ve +1e-07 +197.30445591181 -1.02385326376742e-14 81.6527380218956 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 14 0 0 1 +5 14 0 +0 + +0101000 ++125 0 -123 0 * +Ve +1.00000114182018e-07 +188.834793306651 -1.0010713871068e-14 37.5944952740015 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 15 0 0 1 +5 15 0 +0 + +0101000 ++123 0 -121 0 * +Ve +1.00000005971807e-07 +195.05400824628 0 9.52452034608454e-15 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 16 0 0 38.8446962031097 +5 16 0 +0 + +0101000 ++121 3 -119 0 * +Ve +1.00000008535819e-07 +278.800994873047 0 1.5900020497641e-14 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 17 0 -83.7469866267665 -0 +5 17 0 +0 + +0101000 ++119 2 -117 0 * +Ve +1.00000266714992e-07 +294.510652894126 -7.5215254661846e-16 120.988201936366 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 18 0 0 122.414101388069 +5 18 0 +0 + +0101000 ++117 0 -115 0 * +Ve +1e-07 +308.363379378771 1.25560757063615e-14 184.310527666152 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 19 0 0 1 +5 19 0 +0 + +0101000 ++115 0 -113 0 * +Ve +1e-07 +318.085068989949 2.16765901004243e-14 225.38567289268 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 20 0 0 1 +5 20 0 +0 + +0101000 ++113 0 -111 0 * +Ve +1e-07 +321.98338549386 2.38551844113827e-14 235.197189419704 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 21 0 0 1 +5 21 0 +0 + +0101000 ++111 0 -109 0 * +Ve +1e-07 +340.09794141861 3.45893853218742e-14 283.539732640313 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 22 0 0 1 +5 22 0 +0 + +0101000 ++109 0 -107 0 * +Ve +1e-07 +348.986157401392 4.7435054766823e-14 341.391484765909 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 23 0 0 1 +5 23 0 +0 + +0101000 ++107 0 -105 0 * +Ve +1e-07 +354.175092156378 8.79212514586803e-14 523.725105101006 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 24 0 0 1 +5 24 0 +0 + +0101000 ++105 0 -103 0 * +Ve +1e-07 +383.100717905318 1.31426774152891e-13 719.656560895211 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 25 0 0 1 +5 25 0 +0 + +0101000 ++103 0 -101 0 * +Ve +1e-07 +399.648537938311 1.53766921774922e-13 820.267641401195 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 26 0 0 1 +5 26 0 +0 + +0101000 ++101 0 -99 0 * +Ve +1e-07 +381.199548395825 2.00242112959511e-13 1029.57329510208 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 27 0 0 1 +5 27 0 +0 + +0101000 ++99 0 -97 0 * +Ve +1e-07 +385.616872804426 2.30088159465109e-13 1163.98793902317 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 28 0 0 1 +5 28 0 +0 + +0101000 ++97 0 -95 0 * +Ve +1e-07 +390.104356611471 2.34673261298368e-13 1184.6374019309 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 29 0 0 1 +5 29 0 +0 + +0101000 ++95 0 -93 0 * +Ve +1e-07 +398.338180651589 2.38513436931038e-13 1201.93201547922 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 30 0 0 1 +5 30 0 +0 + +0101000 ++93 0 -91 0 * +Ve +1e-07 +430.199558843639 2.54315040046375e-13 1273.09610938131 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 31 0 0 1 +5 31 0 +0 + +0101000 ++91 0 -89 0 * +Ve +1e-07 +438.240069067251 2.64992716828908e-13 1321.18409056031 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 32 0 0 1 +5 32 0 +0 + +0101000 ++89 0 -87 0 * +Ve +1e-07 +441.315782716022 2.75432504433031e-13 1368.20071412407 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 33 0 0 1 +5 33 0 +0 + +0101000 ++87 0 -85 0 * +Ve +1e-07 +428.137759355651 2.83673251916579e-13 1405.31374142023 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 34 0 0 1 +5 34 0 +0 + +0101000 ++85 0 -83 0 * +Ve +1e-07 +394.966810577575 2.87879668771325e-13 1424.25775879982 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 35 0 0 1 +5 35 0 +0 + +0101000 ++83 0 -81 0 * +Ve +1e-07 +365.468824313099 2.92850952644628e-13 1446.64643099919 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 36 0 0 1 +5 36 0 +0 + +0101000 ++81 0 -79 0 * +Ve +1e-07 +349.811835541072 2.9586173348958e-13 1460.20578249061 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 37 0 0 1 +5 37 0 +0 + +0101000 ++79 0 -77 0 * +Ve +1e-07 +345.581030715691 2.99531214005374e-13 1476.73165357418 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 38 0 0 1 +5 38 0 +0 + +0101000 ++77 0 -75 0 * +Ve +1e-07 +337.923429176344 3.20306673592972e-13 1570.29600563134 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 39 0 0 1 +5 39 0 +0 + +0101000 ++75 0 -73 0 * +Ve +1e-07 +332.787217671646 3.32386575609727e-13 1624.69904785267 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 40 0 0 1 +5 40 0 +0 + +0101000 ++73 0 -71 0 * +Ve +1e-07 +322.15488624561 3.4175862348482e-13 1666.90699917063 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 41 0 0 1 +5 41 0 +0 + +0101000 ++71 0 -69 0 * +Ve +1e-07 +216.249367269469 3.44699278775844e-13 1680.15053324352 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 42 0 0 1 +5 42 0 +0 + +0101000 ++69 0 -67 0 * +Ve +1e-07 +163.533347476329 3.17829479944255e-13 1559.13971723805 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 43 0 0 1 +5 43 0 +0 + +0101000 ++67 0 -65 0 * +Ve +1e-07 +179.786812716139 2.9925212671909e-13 1475.47475617567 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 44 0 0 1 +5 44 0 +0 + +0101000 ++65 0 -63 0 * +Ve +1e-07 +195.62188907029 2.9579458071667e-13 1459.90335328755 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 45 0 0 1 +5 45 0 +0 + +0101000 ++63 0 -61 0 * +Ve +1e-07 +193.051637770588 2.93114725026994e-13 1447.83435620212 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 46 0 0 1 +5 46 0 +0 + +0101000 ++61 0 -59 0 * +Ve +1e-07 +170.97801774454 2.89031549954528e-13 1429.44537046728 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 47 0 0 1 +5 47 0 +0 + +0101000 ++59 0 -57 0 * +Ve +1e-07 +132.279466713631 2.82453870183199e-13 1399.82213430016 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 48 0 0 1 +5 48 0 +0 + +0101000 ++57 0 -55 0 * +Ve +1e-07 +96.7918131183821 2.76872594512649e-13 1374.68630327001 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 49 0 0 1 +5 49 0 +0 + +0101000 ++55 0 -53 0 * +Ve +1e-07 +73.9627458693424 2.54759944039659e-13 1275.09977883968 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 50 0 0 1 +5 50 0 +0 + +0101000 ++53 0 -51 0 * +Ve +1e-07 +46.2474877486502 2.14911548622174e-13 1095.63856008619 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 51 0 0 1 +5 51 0 +0 + +0101000 ++51 0 -49 0 * +Ve +1e-07 +37.9575934043739 2.02899163035836e-13 1041.53958483572 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 52 0 0 1 +5 52 0 +0 + +0101000 ++49 0 -47 0 * +Ve +1e-07 +25.2034586827105 1.84465236966622e-13 958.520562259436 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 53 0 0 1 +5 53 0 +0 + +0101000 ++47 0 -45 0 * +Ve +1e-07 +15.8531633183365 1.69176281362425e-13 889.66522749749 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 54 0 0 1 +5 54 0 +0 + +0101000 ++45 0 -43 0 * +Ve +1e-07 +2.50434723684205 1.58621146043565e-13 842.129124008628 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 55 0 0 1 +5 55 0 +0 + +0101000 ++43 0 -41 0 * +Ve +1e-07 +-5.7611808413287 1.46024907535807e-13 785.400708958817 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 56 0 0 1 +5 56 0 +0 + +0101000 ++41 0 -39 0 * +Ve +1e-07 +15.7634937426301 1.39307565813545e-13 755.148491281518 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 57 0 0 1 +5 57 0 +0 + +0101000 ++39 0 -37 0 * +Ve +1e-07 +38.0101664663469 1.38260549798339e-13 750.433150345584 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 58 0 0 1 +5 58 0 +0 + +0101000 ++37 0 -35 0 * +Ve +1e-07 +45.0120386718457 1.39365131685278e-13 755.407744920005 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 59 0 0 1 +5 59 0 +0 + +0101000 ++35 0 -33 0 * +Ve +1e-07 +53.1184458064934 1.35073306133169e-13 736.079080962789 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 60 0 0 1 +5 60 0 +0 + +0101000 ++33 0 -31 0 * +Ve +1e-07 +76.4277652232041 9.86815436042774e-14 572.185152798315 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 61 0 0 1 +5 61 0 +0 + +0101000 ++31 0 -29 0 * +Ve +1e-07 +83.6155634104894 8.53109686905635e-14 511.969436599184 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 62 0 0 1 +5 62 0 +0 + +0101000 ++29 0 -27 0 * +Ve +1e-07 +81.2603388665052 8.24301977863822e-14 498.995597828573 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 63 0 0 1 +5 63 0 +0 + +0101000 ++27 0 -25 0 * +Ve +1e-07 +74.0278417760323 7.39770346181737e-14 460.925935334127 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 64 0 0 1 +5 64 0 +0 + +0101000 ++25 0 -23 0 * +Ve +1e-07 +61.8555079782574 5.23289955169017e-14 363.431834504337 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 65 0 0 1 +5 65 0 +0 + +0101000 ++23 0 -21 0 * +Ve +1e-07 +53.4316528090843 3.14185300648783e-14 269.259470086461 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 66 0 0 1 +5 66 0 +0 + +0101000 ++21 0 -19 0 * +Ve +1e-07 +44.5299913962226 1.15428052021715e-14 179.747163001056 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 67 0 0 1 +5 67 0 +0 + +0101000 ++19 0 -17 0 * +Ve +1e-07 +25.6025662494909 -1.3593820186391e-15 121.640877441149 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 68 0 0 1 +5 68 0 +0 + +0101000 ++17 0 -15 0 * +Ve +1e-07 +0.562512453184796 -1.13746209217224e-14 76.5362512491966 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 69 0 0 1 +5 69 0 +0 + +0101000 ++15 0 -13 0 * +Ve +1e-07 +-23.7241824528869 -1.62685616718011e-14 54.4959015107687 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 70 0 0 1 +5 70 0 +0 + +0101000 ++13 0 -11 0 * +Ve +1e-07 +-43.793675303796 -2.09272684196768e-14 33.5149515370072 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 71 0 0 1 +5 71 0 +0 + +0101000 ++11 0 -9 0 * +Ve +1.00000062123324e-07 +-25.6232564777988 -1.41845412970638e-14 -1.89470900020505e-15 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 72 0 0 1 +5 72 0 +0 + +0101000 ++9 0 -7 0 * +Ve +1.00000007105427e-07 +143.481059822525 4.39284124883733e-15 -4.39284009273166e-15 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 73 0 0 143.481059822525 +5 73 0 +0 + +0101000 ++7 5 -5 0 * +Ed + 1e-07 1 1 0 +1 74 0 0 184.422754533239 +5 74 0 +0 + +0101000 ++5 4 -150 0 * +Wi + +0101100 ++148 0 +146 0 +144 0 +142 0 +140 0 +138 0 +136 0 +134 0 +132 0 +130 0 ++128 0 +126 0 +124 0 +122 0 +120 0 +118 2 +116 0 +114 0 +112 0 +110 0 ++108 0 +106 0 +104 0 +102 0 +100 0 +98 0 +96 0 +94 0 +92 0 +90 0 ++88 0 +86 0 +84 0 +82 0 +80 0 +78 0 +76 0 +74 0 +72 0 +70 0 ++68 0 +66 0 +64 0 +62 0 +60 0 +58 0 +56 0 +54 0 +52 0 +50 0 ++48 0 +46 0 +44 0 +42 0 +40 0 +38 0 +36 0 +34 0 +32 0 +30 0 ++28 0 +26 0 +24 0 +22 0 +20 0 +18 0 +16 0 +14 0 +12 0 +10 0 ++8 0 +6 0 +4 4 +3 0 * +Co + +1100000 ++2 1 * + ++1 0 \ No newline at end of file diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index 39c68a542679..24fc94c29941 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -130,16 +130,11 @@ def accept(self): ).Value human = None if self.form.addHumanFigure.isChecked(): - # TODO ; fix loading of human shape - humanpath = os.path.join( - os.path.dirname(__file__), "geometry", "human figure.brep" - ) - if os.path.exists(humanpath): - humanshape = Part.Shape() - humanshape.importBrep(humanpath) - human = FreeCAD.ActiveDocument.addObject("Part::Feature", "Human") - human.Shape = humanshape - human.Placement.move(FreeCAD.Vector(500, 500, 0)) + humanshape = Part.Shape() + humanshape.importBrep(":/geometry/HumanFigure.brep") + human = FreeCAD.ActiveDocument.addObject("Part::Feature", "Human") + human.Shape = humanshape + human.Placement.move(FreeCAD.Vector(500, 500, 0)) if self.form.groupBuilding.isChecked(): building = Arch.makeBuilding() if site: @@ -714,19 +709,4 @@ def loadTemplate(self): self.reject() -def getHuman(loc=None): - """Return a list of points defining a human figure, - optionally translated to a given location""" - - import Part - - humanshape = Part.Shape() - humanpath = os.path.join(os.path.dirname(__file__), "geometry", "human figure.brep") - humanshape.importBrep(humanpath) - pts = [v.Point for v in humanshape.Vertexes] - if loc: - pts = [p.add(loc) for p in pts] - return pts - - FreeCADGui.addCommand("BIM_ProjectManager", BIM_ProjectManager()) diff --git a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui index bd8f771208ac..2393fe6ba712 100644 --- a/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui +++ b/src/Mod/Draft/Resources/ui/preferences-draftsnap.ui @@ -90,14 +90,13 @@ showing the main square size in the bottom left corner
If checked, the outline of a human figure is displayed at the bottom left -corner of the grid. Only effective if the BIM workbench is installed and -"Show grid border" is enabled. +corner of the grid. Only effective if "Show grid border" is enabled. Show human figure - true + false gridShowHuman diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py index 2389bc82409b..588e34d24675 100644 --- a/src/Mod/Draft/draftguitools/gui_trackers.py +++ b/src/Mod/Draft/draftguitools/gui_trackers.py @@ -1214,10 +1214,45 @@ def getGridColors(self): blue = col return col, red, green, blue, gtrans + def get_human_figure(self, loc=None): + """Return a list of points defining a human figure, + optionally translated to a given location. + Based on "HumanFigure.brep" from the BIM Workbench. + """ + pts = [ + Vector (131.2, 0.0, 175.8), Vector (135.7, 0.0, 211.7), Vector (142.1, 0.0, 229.3), + Vector (154.0, 0.0, 276.3), Vector (163.6, 0.0, 333.4), Vector (173.8, 0.0, 411.5), + Vector (186.0, 0.0, 491.7), Vector (200.2, 0.0, 591.8), Vector (215.4, 0.0, 714.8), + Vector (224.1, 0.0, 650.0), Vector (234.1, 0.0, 575.8), Vector (251.9, 0.0, 425.5), + Vector (240.8, 0.0, 273.3), Vector (235.9, 0.0, 243.2), Vector (197.3, 0.0, 81.7), + Vector (188.8, 0.0, 37.6), Vector (195.1, 0.0, 0.0), Vector (278.8, 0.0, 0.0), + Vector (294.5, 0.0, 121.0), Vector (308.4, 0.0, 184.3), Vector (318.1, 0.0, 225.4), + Vector (322.0, 0.0, 235.2), Vector (340.1, 0.0, 283.5), Vector (349.0, 0.0, 341.4), + Vector (354.2, 0.0, 523.7), Vector (383.1, 0.0, 719.7), Vector (399.6, 0.0, 820.3), + Vector (381.2, 0.0, 1029.6), Vector (385.6, 0.0, 1164.0), Vector (390.1, 0.0, 1184.6), + Vector (398.3, 0.0, 1201.9), Vector (430.2, 0.0, 1273.1), Vector (438.2, 0.0, 1321.2), + Vector (441.3, 0.0, 1368.2), Vector (428.1, 0.0, 1405.3), Vector (395.0, 0.0, 1424.3), + Vector (365.5, 0.0, 1446.6), Vector (349.8, 0.0, 1460.2), Vector (345.6, 0.0, 1476.7), + Vector (337.9, 0.0, 1570.3), Vector (332.8, 0.0, 1624.7), Vector (322.2, 0.0, 1666.9), + Vector (216.2, 0.0, 1680.2), Vector (163.5, 0.0, 1559.1), Vector (179.8, 0.0, 1475.5), + Vector (195.6, 0.0, 1459.9), Vector (193.1, 0.0, 1447.8), Vector (171.0, 0.0, 1429.4), + Vector (132.3, 0.0, 1399.8), Vector (96.8, 0.0, 1374.7), Vector (74.0, 0.0, 1275.1), + Vector (46.2, 0.0, 1095.6), Vector (38.0, 0.0, 1041.5), Vector (25.2, 0.0, 958.5), + Vector (15.9, 0.0, 889.7), Vector (2.5, 0.0, 842.1), Vector (-5.8, 0.0, 785.4), + Vector (15.8, 0.0, 755.1), Vector (38.0, 0.0, 750.4), Vector (45.0, 0.0, 755.4), + Vector (53.1, 0.0, 736.1), Vector (76.4, 0.0, 572.2), Vector (83.6, 0.0, 512.0), + Vector (81.3, 0.0, 499.0), Vector (74.0, 0.0, 460.9), Vector (61.9, 0.0, 363.4), + Vector (53.4, 0.0, 269.3), Vector (44.5, 0.0, 179.7), Vector (25.6, 0.0, 121.6), + Vector (0.6, 0.0, 76.5), Vector (-23.7, 0.0, 54.5), Vector (-43.8, 0.0, 33.5), + Vector (-25.6, 0.0, 0.0), Vector (117.9, 0.0, 0.0), Vector (131.2, 0.0, 175.8) + ] + if loc: + pts = [p.add(loc) for p in pts] + return pts + def displayHumanFigure(self, wp): """ Display the human figure at the grid corner. The silhouette is displayed only if: - - BIM Workbench is available; - preference BaseApp/Preferences/Mod/Draft/gridBorder is True; - preference BaseApp/Preferences/Mod/Draft/gridShowHuman is True; - the working plane normal is vertical. @@ -1229,15 +1264,10 @@ def displayHumanFigure(self, wp): if params.get_param("gridBorder") \ and params.get_param("gridShowHuman") \ and wp.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001: - try: - import BimProjectManager - loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) - hpts = BimProjectManager.getHuman(loc) - pts.extend([tuple(p) for p in hpts]) - pidx.append(len(hpts)) - except Exception: - # BIM not installed - return + loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) + hpts = self.get_human_figure(loc) + pts.extend([tuple(p) for p in hpts]) + pidx.append(len(hpts)) self.human.numVertices.deleteValues(0) self.coords_human.point.setValues(pts) self.human.numVertices.setValues(pidx) From 6c85c37b38d7c031638386b8641b6db9a941915e Mon Sep 17 00:00:00 2001 From: paul <40677073+paullee0@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:47:06 +0800 Subject: [PATCH 073/161] [Draft Gui_Stretch] Improve Stretch Rectangle Behaviour (#18063) * [Draft gui_stretch] Improve Stretch Rectangle Behaviour Feature Improvement discussed at FreeCAD Forum : - https://forum.freecad.org/viewtopic.php?t=92124#p792118 (Draft_Stretching the whole rectangle creates a new wire) Currently, 3 cases in general, proposed PR improve Case 3 below : 1. The original object is a Rectangle, if after stretching it is no longer a rectangle, it makes a copy turning it into a Wire which reflect the result of stretching. - Current behanviour is good for user, no change. 2. If after stretching it is still a rectangle, the code just resize the original. - Current behanviour is good for user, no change. 3. Now, if the user 'stretch' the whole rectangle, the code creates a copy as DWire in the 'stretched location'. ** - Users find this not intuitive, better just move the whole rectangle. --- src/Mod/Draft/draftguitools/gui_stretch.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftguitools/gui_stretch.py b/src/Mod/Draft/draftguitools/gui_stretch.py index 3ccdf8c32657..3dcd699bdac9 100644 --- a/src/Mod/Draft/draftguitools/gui_stretch.py +++ b/src/Mod/Draft/draftguitools/gui_stretch.py @@ -337,6 +337,8 @@ def doStretch(self): optype = 3 elif ops[1] == [True, True, False, False]: optype = 4 + elif ops[1] == [True, True, True, True]: + optype = 5 else: optype = 0 # print("length:", ops[0].Length, @@ -344,7 +346,7 @@ def doStretch(self): # " - ", ops[1], # " - ", self.displacement) done = False - if optype > 0: + if 0 < optype < 5: v1 = ops[0].Placement.multVec(p2).sub(ops[0].Placement.multVec(p1)) a1 = round(self.displacement.getAngle(v1), 4) v2 = ops[0].Placement.multVec(p4).sub(ops[0].Placement.multVec(p1)) @@ -443,6 +445,12 @@ def doStretch(self): commitops.append(_cmd) commitops.append(_pl) done = True + elif optype == 5: + _pl = _doc + ops[0].Name + _pl += ".Placement.Base=FreeCAD." + _pl += str(ops[0].Placement.Base.add(self.displacement)) + commitops.append(_pl) + done = True if not done: # otherwise create a wire copy and stretch it instead _msg(translate("draft", "Turning one Rectangle into a Wire")) From 298e6921a7040ae3fbe66d1acbd1dc7f5d26aa4d Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Mon, 25 Nov 2024 17:43:56 +0100 Subject: [PATCH 074/161] Draft: fix color of arrays If `get_diffuse_color` returned a list with a single color, the list was wrongly multiplied. Regression introduced in V0.21, but in that version the error was masked by how Core handled the diffuse color. Fixes #17052. --- src/Mod/Draft/draftviewproviders/view_array.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftviewproviders/view_array.py b/src/Mod/Draft/draftviewproviders/view_array.py index b6b1b9acb65d..0a3a1810d8e9 100644 --- a/src/Mod/Draft/draftviewproviders/view_array.py +++ b/src/Mod/Draft/draftviewproviders/view_array.py @@ -56,7 +56,9 @@ def resetColors(self, vobj): obj = vobj.Object if obj.Base is not None: colors = gui_utils.get_diffuse_color(obj.Base) - if colors: + if not colors: + return + if len(colors) > 1: n = 1 if hasattr(obj, "ArrayType"): if obj.ArrayType == "ortho": @@ -68,7 +70,7 @@ def resetColors(self, vobj): elif hasattr(obj, "Count"): n = obj.Count colors = colors * n - vobj.DiffuseColor = colors + vobj.DiffuseColor = colors # Alias for compatibility with v0.18 and earlier From 1de4dc600dd95f3ab7189324ad731ef1f740dafc Mon Sep 17 00:00:00 2001 From: wandererfan Date: Thu, 17 Oct 2024 15:27:11 -0400 Subject: [PATCH 075/161] [TD]fix area calculation --- src/Mod/TechDraw/App/DimensionGeometry.cpp | 8 +- src/Mod/TechDraw/App/DimensionGeometry.h | 11 +- src/Mod/TechDraw/App/DrawViewDimension.cpp | 79 +++++++++++-- src/Mod/TechDraw/App/DrawViewDimension.h | 5 + src/Mod/TechDraw/App/DrawViewDimensionPy.xml | 5 + .../TechDraw/App/DrawViewDimensionPyImp.cpp | 16 +++ src/Mod/TechDraw/App/Geometry.cpp | 110 +++++++++++++++++- src/Mod/TechDraw/App/Geometry.h | 8 ++ src/Mod/TechDraw/App/ShapeUtils.cpp | 29 +++++ src/Mod/TechDraw/App/ShapeUtils.h | 4 + 10 files changed, 261 insertions(+), 14 deletions(-) diff --git a/src/Mod/TechDraw/App/DimensionGeometry.cpp b/src/Mod/TechDraw/App/DimensionGeometry.cpp index fad87f130863..9483443e4c21 100644 --- a/src/Mod/TechDraw/App/DimensionGeometry.cpp +++ b/src/Mod/TechDraw/App/DimensionGeometry.cpp @@ -365,6 +365,7 @@ void arcPoints::dump(const std::string& text) const areaPoint::areaPoint() : area(0.0), + actualArea(0.0), center(Base::Vector3d()) { } @@ -373,6 +374,7 @@ areaPoint& areaPoint::operator=(const areaPoint& ap) { area = ap.area; center = ap.center; + actualArea = ap.actualArea; return *this; } @@ -383,10 +385,14 @@ void areaPoint::move(const Base::Vector3d& offset) void areaPoint::project(const DrawViewPart* dvp) { - area = area * dvp->getScale(); center = dvp->projectPoint(center) * dvp->getScale(); } +void areaPoint::invertY() +{ + center = DU::invertY(center); +} + void areaPoint::dump(const std::string& text) const { Base::Console().Message("areaPoint - %s\n", text.c_str()); diff --git a/src/Mod/TechDraw/App/DimensionGeometry.h b/src/Mod/TechDraw/App/DimensionGeometry.h index 0a74b2e2ebf2..da9dc69da91c 100644 --- a/src/Mod/TechDraw/App/DimensionGeometry.h +++ b/src/Mod/TechDraw/App/DimensionGeometry.h @@ -167,11 +167,16 @@ class TechDrawExport areaPoint void move(const Base::Vector3d& offset); void project(const DrawViewPart* dvp); + void invertY(); void dump(const std::string& text) const; -//TODO: setters and getters - double area; - Base::Vector3d center; + double getFilledArea() const { return area; } + double getActualArea() const { return actualArea; } + Base::Vector3d getCenter() const { return center; } + + double area{0}; // this is the outer area without considering holes + double actualArea{0}; // this is the net area after holes are removed + Base::Vector3d center; // this is geometric center of the outer face }; } //end namespace TechDraw diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 661f8ce81722..05a9da911987 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +226,11 @@ DrawViewDimension::DrawViewDimension() UnderTolerance.setStatus(App::Property::ReadOnly, true); FormatSpecUnderTolerance.setStatus(App::Property::ReadOnly, true); + // legacy behaviour if this is false + ADD_PROPERTY_TYPE(UseActualArea, (true), "Area", App::Prop_Output, + "If true, area dimensions return the area of the face minus the areas of any enclosed faces. \ + If false, the area of the face's outer boundary is returned."); + measurement = new Measure::Measurement(); // TODO: should have better initial datumLabel position than (0, 0) in the DVP?? something // closer to the object being measured? @@ -277,6 +284,7 @@ void DrawViewDimension::resetArea() { m_areaPoint.center = Base::Vector3d(0, 0, 0); m_areaPoint.area = 0.0; + m_areaPoint.actualArea = 0.0; } void DrawViewDimension::onChanged(const App::Property* prop) @@ -686,7 +694,6 @@ double DrawViewDimension::getDimValue() //! retrieve the dimension value for "true" dimensions. The returned value is in internal units (mm). double DrawViewDimension::getTrueDimValue() const { - // Base::Console().Message("DVD::getTrueDimValue()\n"); double result = 0.0; if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) { @@ -763,7 +770,17 @@ double DrawViewDimension::getProjectedDimValue() const result = legAngle; } else if (Type.isValue("Area")) { - result = m_areaPoint.area / scale / scale; + // 2d reference makes scaled values in areaPoint + // 3d reference makes actual values in areaPoint :p + double divisor{scale / scale}; + if (has3DReferences()) { + divisor = 1.0; + } + if (UseActualArea.getValue()) { + result = m_areaPoint.actualArea / divisor; + } else { + result = m_areaPoint.area / divisor; + } } return result; @@ -1383,27 +1400,71 @@ areaPoint DrawViewDimension::getAreaParameters(ReferenceVector references) ssMessage << getNameInDocument() << " can not find geometry for 2d reference (4)"; throw Base::RuntimeError(ssMessage.str()); } + auto dvp = static_cast(refObject); - pts.area = face->getArea(); - pts.center = face->getCenter(); + auto filteredFaces = GeometryUtils::findHolesInFace(dvp, references.front().getSubName()); + auto perforatedFace = GeometryUtils::makePerforatedFace(face, filteredFaces); + + // these areas are scaled because the source geometry is scaled, but it makes no sense to + // report a scaled area. + auto unscale = getViewPart()->getScale() * getViewPart()->getScale(); + pts.area = face->getArea() / unscale; // this will be the 2d area as projected onto the page? not really filled area? + pts.actualArea = getActualArea(perforatedFace) / unscale; + pts.center = getFaceCenter(perforatedFace); + pts.invertY(); // geometry class is over, back to -Y up/. } else { - // this is a 3d reference + // this is a 3d reference. perforations should be handled for us by OCC TopoDS_Shape geometry = references[0].getGeometry(); if (geometry.IsNull() || geometry.ShapeType() != TopAbs_FACE) { throw Base::RuntimeError("Geometry for dimension reference is null."); } const TopoDS_Face& face = TopoDS::Face(geometry); - GProp_GProps props; - BRepGProp::SurfaceProperties(face, props); - pts.area = props.Mass(); - pts.center = DrawUtil::toVector3d(props.CentreOfMass()); + // these areas are unscaled as the source is 3d geometry. + pts.area = getFilledArea(face); + pts.actualArea = getActualArea(face); + pts.center = getFaceCenter(face); + pts.move(getViewPart()->getCurrentCentroid()); + pts.project(getViewPart()); } return pts; } + +//! returns the center of mass of a face (density = k) +Base::Vector3d DrawViewDimension::getFaceCenter(const TopoDS_Face& face) +{ + GProp_GProps props; + BRepGProp::SurfaceProperties(face, props); + auto center = DrawUtil::toVector3d(props.CentreOfMass()); + return center; +} + + +//! returns the "net" area of a face (area of the face's outer boundary less the area of any holes) +double DrawViewDimension::getActualArea(const TopoDS_Face& face) +{ + GProp_GProps props; + BRepGProp::SurfaceProperties(face, props); + return props.Mass(); +} + + +//! returns the "gross" area of a face (area of the face's outer boundary) +double DrawViewDimension::getFilledArea(const TopoDS_Face& face) +{ + TopoDS_Wire outerwire = ShapeAnalysis::OuterWire(face); + if (outerwire.IsNull()) { + return 0.0; + } + + double area = ShapeAnalysis::ContourArea(outerwire); + return area; +} + + DrawViewPart* DrawViewDimension::getViewPart() const { if (References2D.getValues().empty()) { diff --git a/src/Mod/TechDraw/App/DrawViewDimension.h b/src/Mod/TechDraw/App/DrawViewDimension.h index 110d0238d8ca..5f3bd1ec28b5 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.h +++ b/src/Mod/TechDraw/App/DrawViewDimension.h @@ -92,6 +92,7 @@ class TechDrawExport DrawViewDimension: public TechDraw::DrawView Part::PropertyTopoShapeList SavedGeometry; App::PropertyVectorList BoxCorners; + App::PropertyBool UseActualArea; enum RefType { @@ -212,6 +213,10 @@ class TechDrawExport DrawViewDimension: public TechDraw::DrawView Base::BoundBox3d getSavedBox(); Base::BoundBox3d getFeatureBox(); + static double getActualArea(const TopoDS_Face& face); + static double getFilledArea(const TopoDS_Face& face); + static Base::Vector3d getFaceCenter(const TopoDS_Face& face); + protected: void handleChangedPropertyType(Base::XMLReader&, const char*, App::Property*) override; void Restore(Base::XMLReader& reader) override; diff --git a/src/Mod/TechDraw/App/DrawViewDimensionPy.xml b/src/Mod/TechDraw/App/DrawViewDimensionPy.xml index c6ac4074d3d2..62ca01526ed4 100644 --- a/src/Mod/TechDraw/App/DrawViewDimensionPy.xml +++ b/src/Mod/TechDraw/App/DrawViewDimensionPy.xml @@ -38,6 +38,11 @@ getAnglePoints() - returns list of points for angle Dimension
+ + + getAreaPoints() - returns list of values (center, filled area, actual area) for area Dimension. + + getArrowPositions() - returns list of locations or Dimension Arrowheads. Locations are in unscaled coordinates of parent View diff --git a/src/Mod/TechDraw/App/DrawViewDimensionPyImp.cpp b/src/Mod/TechDraw/App/DrawViewDimensionPyImp.cpp index 1890835cc6d9..8a18240c29a9 100644 --- a/src/Mod/TechDraw/App/DrawViewDimensionPyImp.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimensionPyImp.cpp @@ -111,6 +111,22 @@ PyObject* DrawViewDimensionPy::getAnglePoints(PyObject* args) return Py::new_reference_to(ret); } + +PyObject* DrawViewDimensionPy::getAreaPoints(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + + DrawViewDimension* dvd = getDrawViewDimensionPtr(); + areaPoint pts = dvd->getAreaPoint(); + Py::List ret; + ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.getCenter())))); + ret.append(Py::asObject(PyFloat_FromDouble(pts.getFilledArea()))); + ret.append(Py::asObject(PyFloat_FromDouble(pts.getActualArea()))); + return Py::new_reference_to(ret); +} + PyObject* DrawViewDimensionPy::getArrowPositions(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index 9b9343004791..0ecc3c4a92ea 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -82,9 +82,11 @@ #include #include +#include #include #include +#include "DrawViewPart.h" #include "Geometry.h" #include "ShapeUtils.h" #include "DrawUtil.h" @@ -145,10 +147,14 @@ void Wire::dump(std::string s) BRepTools::Write(toOccWire(), s.c_str()); //debug } +// note that the face returned is inverted in Y TopoDS_Face Face::toOccFace() const { + if (wires.empty()) { + return {}; + } + TopoDS_Face result; - //if (!wires.empty) { BRepBuilderAPI_MakeFace mkFace(wires.front()->toOccWire(), true); int limit = wires.size(); int iwire = 1; @@ -1734,3 +1740,105 @@ double GeometryUtils::edgeLength(TopoDS_Edge occEdge) } } +//! return a perforated shape/face (using Part::FaceMakerCheese) formed by creating holes in the input face. +TopoDS_Face GeometryUtils::makePerforatedFace(FacePtr bigCheese, const std::vector &holesAll) +{ + std::vector cheeseIngredients; + + // v0.0 brute force + + // Note: TD Faces are not perforated and should only ever have 1 wire. They are capable of + // having voids, but for now we will just take the first contour wire in all cases. + + if (bigCheese->wires.empty()) { + // run in circles. scream and shout. + return {}; + } + + auto flippedFace = ShapeUtils::fromQtAsFace(bigCheese->toOccFace()); + + if (holesAll.empty()) { + return flippedFace; + } + + auto outer = ShapeUtils::fromQtAsWire(bigCheese->wires.front()->toOccWire()); + cheeseIngredients.push_back(outer); + for (auto& hole : holesAll) { + if (hole->wires.empty()) { + continue; + } + auto holeR3 = ShapeUtils::fromQtAsWire(hole->wires.front()->toOccWire()); + cheeseIngredients.push_back(holeR3); + } + + TopoDS_Shape faceShape; + try { + faceShape = Part::FaceMakerCheese::makeFace(cheeseIngredients); + } + catch (const Standard_Failure &e) { + Base::Console().Warning("Area - could not make holes in face\n"); + return flippedFace; + } + + + // v0.0 just grab the first face + TopoDS_Face foundFace; + TopExp_Explorer expFaces(faceShape, TopAbs_FACE); + if (expFaces.More()) { + foundFace = TopoDS::Face(expFaces.Current()); + } + // TODO: sort out the compound => shape but !compound => face business in FaceMakerCheese here. + // first guess is it does not affect us? + + return foundFace; +} + + +//! find faces within the bounds of the input face +std::vector GeometryUtils::findHolesInFace(const DrawViewPart* dvp, const std::string& bigCheeseSubRef) +{ + if (!dvp || bigCheeseSubRef.empty()) { + return {}; + } + + std::vector holes; + auto bigCheeseIndex = DU::getIndexFromName(bigCheeseSubRef); + + // v0.0 brute force + auto facesAll = dvp->getFaceGeometry(); + if (facesAll.empty()) { + // tarfu + throw Base::RuntimeError("GU::findHolesInFace - no holes to find!!"); + } + + auto bigCheeseFace = facesAll.at(bigCheeseIndex); + auto bigCheeseOCCFace = bigCheeseFace->toOccFace(); + auto bigCheeseArea = bigCheeseFace->getArea(); + + int iFace{0}; + for (auto& face : facesAll) { + if (iFace == bigCheeseIndex) { + iFace++; + continue; + } + if (face->getArea() > bigCheeseArea) { + iFace++; + continue; + } + auto faceCenter = DU::togp_Pnt(face->getCenter()); + auto faceCenterVertex = BRepBuilderAPI_MakeVertex(faceCenter); + auto distance = DU::simpleMinDist(faceCenterVertex, bigCheeseOCCFace); + if (distance > EWTOLERANCE) { + // hole center not within outer contour. not the best test but cheese maker handles it + // for us? + // FaceMakerCheese does not support partial overlaps and just ignores them? + iFace++; + continue; + } + holes.push_back(face); + iFace++; + } + + return holes; +} + diff --git a/src/Mod/TechDraw/App/Geometry.h b/src/Mod/TechDraw/App/Geometry.h index a417a41b659f..93909deaddd4 100644 --- a/src/Mod/TechDraw/App/Geometry.h +++ b/src/Mod/TechDraw/App/Geometry.h @@ -29,6 +29,7 @@ #include #include #include + #include #include @@ -42,6 +43,8 @@ class TopoShape; namespace TechDraw { +class DrawViewPart; + enum ExtractionType { //obs Plain, WithHidden, @@ -339,6 +342,7 @@ class TechDrawExport Wire void dump(std::string s); BaseGeomPtrVector geoms; }; +using WirePtr = std::shared_ptr; /// Simple Collection of geometric features based on BaseGeom inherited classes in order class TechDrawExport Face @@ -429,6 +433,7 @@ class TechDrawExport GeometryUtils {} }; + // TODO: prune unused methods /// Find an unused geom starts or ends at atPoint. /*! * returns index[1:geoms.size()), reversed [true, false] @@ -452,6 +457,9 @@ class TechDrawExport GeometryUtils static double edgeLength(TopoDS_Edge occEdge); + static TopoDS_Face makePerforatedFace(FacePtr bigCheese, const std::vector& holesAll); + static std::vector findHolesInFace(const DrawViewPart* dvp, const std::string& bigCheeseSubRef); + }; diff --git a/src/Mod/TechDraw/App/ShapeUtils.cpp b/src/Mod/TechDraw/App/ShapeUtils.cpp index 2ea0b837ee46..1e134c8e93c9 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.cpp +++ b/src/Mod/TechDraw/App/ShapeUtils.cpp @@ -222,6 +222,7 @@ Base::Vector3d ShapeUtils::findCentroidVec(const TopoDS_Shape& shape, const gp_A return Base::Vector3d(p.X(), p.Y(), p.Z()); } + //!scales & mirrors a shape about a center TopoDS_Shape ShapeUtils::mirrorShapeVec(const TopoDS_Shape& input, const Base::Vector3d& inputCenter, double scale) @@ -349,6 +350,34 @@ TopoDS_Shape ShapeUtils::fromQt(const TopoDS_Shape& inShape) return mkTrf.Shape(); } +//! specialization offromQt for Faces. should be templated? +TopoDS_Face ShapeUtils::fromQtAsFace(const TopoDS_Shape& inShape) +{ + auto flippedShape = ShapeUtils::fromQt(inShape); + + TopoDS_Face foundFace; + TopExp_Explorer expFaces(flippedShape, TopAbs_FACE); + if (expFaces.More()) { + foundFace = TopoDS::Face(expFaces.Current()); + } + + return foundFace; +} + +//! specialization offromQt for Wire. should be templated? +TopoDS_Wire ShapeUtils::fromQtAsWire(const TopoDS_Shape& inShape) +{ + auto flippedShape = ShapeUtils::fromQt(inShape); + + TopoDS_Wire foundWire; + TopExp_Explorer expWires(flippedShape, TopAbs_WIRE); + if (expWires.More()) { + foundWire = TopoDS::Wire(expWires.Current()); + } + + return foundWire; +} + //! transforms a shape defined in conventional coordinates coordinates into one defined by //! invertedY (Qt) coordinates TopoDS_Shape ShapeUtils::toQt(const TopoDS_Shape& inShape) diff --git a/src/Mod/TechDraw/App/ShapeUtils.h b/src/Mod/TechDraw/App/ShapeUtils.h index dab431248f5e..755da53d987b 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.h +++ b/src/Mod/TechDraw/App/ShapeUtils.h @@ -31,6 +31,8 @@ #include #include +#include +#include #include #include @@ -113,6 +115,8 @@ class TechDrawExport ShapeUtils static TopoDS_Shape fromQt(const TopoDS_Shape& inShape); static TopoDS_Shape toQt(const TopoDS_Shape& inShape); + static TopoDS_Wire fromQtAsWire(const TopoDS_Shape& inShape); + static TopoDS_Face fromQtAsFace(const TopoDS_Shape& inShape); }; } From c016e81a7faaf863da93178b2bfcfefaa4c59b76 Mon Sep 17 00:00:00 2001 From: Syres916 <46537884+Syres916@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:50:58 +0000 Subject: [PATCH 076/161] [Part] [Post 1.0] Preferences > Shape view > Maximum angle deflection warn user... (#16007) * [Part] Preferences max angle deflection alert * [Part] Comment added as requested --- src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp | 65 +++++++++++++++---- src/Mod/Part/Gui/DlgSettings3DViewPartImp.h | 1 + 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp index cb6210b5cd20..554051d96889 100644 --- a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp +++ b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.cpp @@ -42,15 +42,27 @@ using namespace PartGui; * name 'name' and widget flags set to 'f' */ DlgSettings3DViewPart::DlgSettings3DViewPart(QWidget* parent) - : PreferencePage(parent), ui(new Ui_DlgSettings3DViewPart), checkValue(false) + : PreferencePage(parent) + , ui(new Ui_DlgSettings3DViewPart) + , checkValue(false) { ui->setupUi(this); - connect(ui->maxDeviation, qOverload(&QDoubleSpinBox::valueChanged), - this, &DlgSettings3DViewPart::onMaxDeviationValueChanged); - ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/Mod/Part"); - double lowerLimit = hPart->GetFloat("MinimumDeviation", ui->maxDeviation->minimum()); - ui->maxDeviation->setMinimum(lowerLimit); + connect(ui->maxDeviation, + qOverload(&QDoubleSpinBox::valueChanged), + this, + &DlgSettings3DViewPart::onMaxDeviationValueChanged); + connect(ui->maxAngularDeflection, + qOverload(&QDoubleSpinBox::valueChanged), + this, + &DlgSettings3DViewPart::onMaxAngularDeflectionValueChanged); + ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Part"); + const double minDeviationlowerLimit = hPart->GetFloat( + "MinimumDeviation", ui->maxDeviation->minimum()); + ui->maxDeviation->setMinimum(minDeviationlowerLimit); + const double minAngleDeflectionlowerLimit = hPart->GetFloat( + "MinimumDeviation", ui->maxAngularDeflection->minimum()); + ui->maxAngularDeflection->setMinimum(minAngleDeflectionlowerLimit); } /** @@ -58,15 +70,40 @@ DlgSettings3DViewPart::DlgSettings3DViewPart(QWidget* parent) */ DlgSettings3DViewPart::~DlgSettings3DViewPart() = default; -void DlgSettings3DViewPart::onMaxDeviationValueChanged(double v) +void DlgSettings3DViewPart::onMaxDeviationValueChanged(double vMaxDev) { - if (!this->isVisible()) + if (!this->isVisible()) { return; - if (v < 0.01 && !checkValue) { + } + const double maxDevMinThreshold = 0.01; + if (vMaxDev < maxDevMinThreshold && !checkValue) { checkValue = true; - QMessageBox::warning(this, tr("Deviation"), + QMessageBox::warning( + this, + tr("Deviation"), tr("Setting a too small deviation causes the tessellation to take longer" - "and thus freezes or slows down the GUI.")); + " and thus freezes or slows down the GUI.")); + } +} + +void DlgSettings3DViewPart::onMaxAngularDeflectionValueChanged(double vMaxAngle) +{ + if (!this->isVisible()) { + return; + } + /** + * The lower threshold of 2.0 was determined by testing + * as laid out in the table as per comment hyperlink: + * https://github.com/FreeCAD/FreeCAD/issues/15951#issuecomment-2304308163 + */ + const double vMaxAngleMinThreshold = 2.0; + if (vMaxAngle < vMaxAngleMinThreshold && !checkValue) { + checkValue = true; + QMessageBox::warning( + this, + tr("Angle Deflection"), + tr("Setting a too small angle deviation causes the tessellation to take longer" + " and thus freezes or slows down the GUI.")); } } @@ -79,13 +116,13 @@ void DlgSettings3DViewPart::saveSettings() std::vector docs = App::GetApplication().getDocuments(); for (auto it : docs) { Gui::Document* doc = Gui::Application::Instance->getDocument(it); - std::vector views = doc->getViewProvidersOfType(ViewProviderPart::getClassTypeId()); + std::vector views = + doc->getViewProvidersOfType(ViewProviderPart::getClassTypeId()); for (auto view : views) { static_cast(view)->reload(); } } } - void DlgSettings3DViewPart::loadSettings() { ui->maxDeviation->onRestore(); diff --git a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.h b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.h index 3e62ee18f6f3..d3d9d5f3049a 100644 --- a/src/Mod/Part/Gui/DlgSettings3DViewPartImp.h +++ b/src/Mod/Part/Gui/DlgSettings3DViewPartImp.h @@ -49,6 +49,7 @@ class DlgSettings3DViewPart : public Gui::Dialog::PreferencePage private: void onMaxDeviationValueChanged(double); + void onMaxAngularDeflectionValueChanged(double); private: std::unique_ptr ui; From eebe20806df6f25c2c9f40fe6650caba78ecd521 Mon Sep 17 00:00:00 2001 From: hasecilu Date: Wed, 4 Sep 2024 14:26:50 -0600 Subject: [PATCH 077/161] Gui: Add "px" suffix on preference page as width unit --- src/Gui/PreferencePages/DlgSettingsNotificationArea.ui | 3 +++ src/Gui/PreferencePages/DlgSettingsPythonConsole.ui | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Gui/PreferencePages/DlgSettingsNotificationArea.ui b/src/Gui/PreferencePages/DlgSettingsNotificationArea.ui index 3b3ddd961a13..3e0ce0013ee8 100644 --- a/src/Gui/PreferencePages/DlgSettingsNotificationArea.ui +++ b/src/Gui/PreferencePages/DlgSettingsNotificationArea.ui @@ -210,6 +210,9 @@ Width of the notification in pixels + + px + 300 diff --git a/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui b/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui index a8a896bdfe0e..91afbf2f212e 100644 --- a/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui +++ b/src/Gui/PreferencePages/DlgSettingsPythonConsole.ui @@ -90,6 +90,9 @@ horizontal space in Python console The interval at which the profiler runs when there's Python code running (to keep the GUI responding). Set to 0 to disable. + + ms + 0 From fe1cfca339f1e5f694404d62061efbf9e853ce20 Mon Sep 17 00:00:00 2001 From: hasecilu Date: Wed, 4 Sep 2024 19:05:56 -0600 Subject: [PATCH 078/161] Gui: Add suffix to programatically generated preference page's spinboxes Units contain a leading space. Command to generate the C++ code on `src` dir: $ python3 -m cogapp -r Gui/PreferencePages/DlgSettingsAdvanced.{h,cpp} --- src/Gui/OverlayParams.py | 32 ++--- .../PreferencePages/DlgSettingsAdvanced.cpp | 119 +++++++++++------- src/Gui/PreferencePages/DlgSettingsAdvanced.h | 1 - src/Gui/TreeParams.py | 4 +- src/Tools/params_utils.py | 15 ++- 5 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/Gui/OverlayParams.py b/src/Gui/OverlayParams.py index effa6816c15b..fde13a371b62 100644 --- a/src/Gui/OverlayParams.py +++ b/src/Gui/OverlayParams.py @@ -99,9 +99,9 @@ def init_widget(self, param, row, group_name): Params = [ ParamBool('DockOverlayAutoView', True, on_change=True, title="Auto hide in non 3D view"), - ParamInt('DockOverlayDelay', 200, "Overlay dock (re),layout delay.", title="Layout delay (ms)", proxy=ParamSpinBox(0, 5000, 100)), + ParamInt('DockOverlayDelay', 200, "Overlay dock (re),layout delay.", title="Layout delay", proxy=ParamSpinBox(0, 5000, 100, suffix=" ms")), ParamInt('DockOverlayRevealDelay', 2000), - ParamInt('DockOverlaySplitterHandleTimeout', 0, title="Splitter auto hide delay (ms)", proxy=ParamSpinBox(0, 99999, 100), + ParamInt('DockOverlaySplitterHandleTimeout', 0, title="Splitter auto hide delay", proxy=ParamSpinBox(0, 99999, 100, suffix=" ms"), doc="Overlay splitter handle auto hide delay. Set zero to disable auto hiding."), ParamBool('DockOverlayActivateOnHover', True, title="Activate on hover", doc="Show auto hidden dock overlay on mouse over.\n" @@ -110,41 +110,41 @@ def init_widget(self, param, row, group_name): "Auto mouse click through transparent part of dock overlay.", title="Auto mouse pass through"), ParamBool('DockOverlayWheelPassThrough', True, "Auto pass through mouse wheel event on transparent dock overlay.", title="Auto mouse wheel pass through"), - ParamInt('DockOverlayWheelDelay', 1000, title="Delay mouse wheel pass through (ms)", proxy=ParamSpinBox(0, 99999, 1), + ParamInt('DockOverlayWheelDelay', 1000, title="Delay mouse wheel pass through", proxy=ParamSpinBox(0, 99999, 1, suffix=" ms"), doc="Delay capturing mouse wheel event for passing through if it is\n" "previously handled by other widget."), - ParamInt('DockOverlayAlphaRadius', 2, title="Alpha test radius", proxy=ParamSpinBox(1, 100, 1), doc=\ + ParamInt('DockOverlayAlphaRadius', 2, title="Alpha test radius", proxy=ParamSpinBox(1, 100, 1, suffix=" px"), doc=\ "If auto mouse click through is enabled, then this radius\n" "defines a region of alpha test under the mouse cursor.\n" "Auto click through is only activated if all pixels within\n" "the region are non-opaque."), ParamBool('DockOverlayCheckNaviCube', True, on_change=True, title="Check Navigation Cube", doc="Leave space for Navigation Cube in dock overlay"), - ParamInt('DockOverlayHintTriggerSize', 16, title="Hint trigger size", proxy=ParamSpinBox(1, 100, 1), + ParamInt('DockOverlayHintTriggerSize', 16, title="Hint trigger size", proxy=ParamSpinBox(1, 100, 1, suffix=" px"), doc="Auto hide hint visual display triggering width"), - ParamInt('DockOverlayHintSize', 8, title="Hint width", proxy=ParamSpinBox(1, 100, 1), + ParamInt('DockOverlayHintSize', 8, title="Hint width", proxy=ParamSpinBox(1, 100, 1, suffix=" px"), doc="Auto hide hint visual display width"), - ParamInt('DockOverlayHintLeftLength', 100, title='Left panel hint length', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintLeftLength', 100, title='Left panel hint length', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display length for left panel. Set to zero to fill the space."), - ParamInt('DockOverlayHintRightLength', 100, title='Right panel hint length', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintRightLength', 100, title='Right panel hint length', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display length for right panel. Set to zero to fill the space."), - ParamInt('DockOverlayHintTopLength', 100, title='Top panel hint length', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintTopLength', 100, title='Top panel hint length', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display length for top panel. Set to zero to fill the space."), - ParamInt('DockOverlayHintBottomLength', 100, title='Bottom panel hint length', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintBottomLength', 100, title='Bottom panel hint length', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display length for bottom panel. Set to zero to fill the space."), - ParamInt('DockOverlayHintLeftOffset', 0, title='Left panel hint offset', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintLeftOffset', 0, title='Left panel hint offset', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display offset for left panel"), - ParamInt('DockOverlayHintRightOffset', 0, title='Right panel hint offset', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintRightOffset', 0, title='Right panel hint offset', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display offset for right panel"), - ParamInt('DockOverlayHintTopOffset', 0, title='Top panel hint offset', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintTopOffset', 0, title='Top panel hint offset', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display offset for top panel"), - ParamInt('DockOverlayHintBottomOffset', 0, title='Bottom panel hint offset', proxy=ParamSpinBox(0, 10000, 10), + ParamInt('DockOverlayHintBottomOffset', 0, title='Bottom panel hint offset', proxy=ParamSpinBox(0, 10000, 10, suffix=" px"), doc="Auto hide hint visual display offset for bottom panel"), ParamBool('DockOverlayHintTabBar', False, "Show tab bar on mouse over when auto hide", title="Hint show tab bar"), ParamBool('DockOverlayHideTabBar', True, on_change=True, doc="Hide tab bar in dock overlay", title='Hide tab bar'), - ParamInt('DockOverlayHintDelay', 200, "Delay before show hint visual", title="Hint delay (ms)", proxy=ParamSpinBox(0, 1000, 100)), + ParamInt('DockOverlayHintDelay', 200, "Delay before show hint visual", title="Hint delay", proxy=ParamSpinBox(0, 1000, 100, suffix=" ms")), ParamInt('DockOverlayAnimationDuration', 200, "Auto hide animation duration, 0 to disable", - title="Animation duration (ms)", proxy=ParamSpinBox(0, 5000, 100)), + title="Animation duration", proxy=ParamSpinBox(0, 5000, 100, suffix=" ms")), ParamInt('DockOverlayAnimationCurve', 7, "Auto hide animation curve type", title="Animation curve type", proxy=ParamAnimationCurve()), ParamBool('DockOverlayHidePropertyViewScrollBar', False, "Hide property view scroll bar in dock overlay", title="Hide property view scroll bar"), ParamInt('DockOverlayMinimumSize', 30, on_change=True, diff --git a/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp b/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp index ca70006b7455..8000159f39fc 100644 --- a/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp +++ b/src/Gui/PreferencePages/DlgSettingsAdvanced.cpp @@ -70,10 +70,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) ItemBackgroundPadding->setValue(Gui::TreeParams::defaultItemBackgroundPadding()); ItemBackgroundPadding->setEntryName("ItemBackgroundPadding"); ItemBackgroundPadding->setParamGrpPath("TreeView"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) ItemBackgroundPadding->setMinimum(0); ItemBackgroundPadding->setMaximum(100); ItemBackgroundPadding->setSingleStep(1); + ItemBackgroundPadding->setAlignment(Qt::AlignRight); + ItemBackgroundPadding->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelFontSize = new QLabel(this); @@ -83,6 +85,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) FontSize->setValue(Gui::TreeParams::defaultFontSize()); FontSize->setEntryName("FontSize"); FontSize->setParamGrpPath("TreeView"); + // Auto generated code (Tools/params_utils.py:1135) + FontSize->setMinimum(0); + FontSize->setMaximum(100); + FontSize->setSingleStep(1); + FontSize->setAlignment(Qt::AlignRight); + FontSize->setSuffix(QLatin1String(" pt")); // Auto generated code (Tools/params_utils.py:420) @@ -101,10 +109,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayWheelDelay->setValue(Gui::OverlayParams::defaultDockOverlayWheelDelay()); DockOverlayWheelDelay->setEntryName("DockOverlayWheelDelay"); DockOverlayWheelDelay->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayWheelDelay->setMinimum(0); DockOverlayWheelDelay->setMaximum(99999); DockOverlayWheelDelay->setSingleStep(1); + DockOverlayWheelDelay->setAlignment(Qt::AlignRight); + DockOverlayWheelDelay->setSuffix(QLatin1String(" ms")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayAlphaRadius = new QLabel(this); @@ -114,10 +124,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayAlphaRadius->setValue(Gui::OverlayParams::defaultDockOverlayAlphaRadius()); DockOverlayAlphaRadius->setEntryName("DockOverlayAlphaRadius"); DockOverlayAlphaRadius->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayAlphaRadius->setMinimum(1); DockOverlayAlphaRadius->setMaximum(100); DockOverlayAlphaRadius->setSingleStep(1); + DockOverlayAlphaRadius->setAlignment(Qt::AlignRight); + DockOverlayAlphaRadius->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) DockOverlayCheckNaviCube = new Gui::PrefCheckBox(this); @@ -134,10 +146,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintTriggerSize->setValue(Gui::OverlayParams::defaultDockOverlayHintTriggerSize()); DockOverlayHintTriggerSize->setEntryName("DockOverlayHintTriggerSize"); DockOverlayHintTriggerSize->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintTriggerSize->setMinimum(1); DockOverlayHintTriggerSize->setMaximum(100); DockOverlayHintTriggerSize->setSingleStep(1); + DockOverlayHintTriggerSize->setAlignment(Qt::AlignRight); + DockOverlayHintTriggerSize->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintSize = new QLabel(this); @@ -147,10 +161,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintSize->setValue(Gui::OverlayParams::defaultDockOverlayHintSize()); DockOverlayHintSize->setEntryName("DockOverlayHintSize"); DockOverlayHintSize->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintSize->setMinimum(1); DockOverlayHintSize->setMaximum(100); DockOverlayHintSize->setSingleStep(1); + DockOverlayHintSize->setAlignment(Qt::AlignRight); + DockOverlayHintSize->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintLeftOffset = new QLabel(this); @@ -160,10 +176,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintLeftOffset->setValue(Gui::OverlayParams::defaultDockOverlayHintLeftOffset()); DockOverlayHintLeftOffset->setEntryName("DockOverlayHintLeftOffset"); DockOverlayHintLeftOffset->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintLeftOffset->setMinimum(0); DockOverlayHintLeftOffset->setMaximum(10000); DockOverlayHintLeftOffset->setSingleStep(10); + DockOverlayHintLeftOffset->setAlignment(Qt::AlignRight); + DockOverlayHintLeftOffset->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintLeftLength = new QLabel(this); @@ -173,10 +191,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintLeftLength->setValue(Gui::OverlayParams::defaultDockOverlayHintLeftLength()); DockOverlayHintLeftLength->setEntryName("DockOverlayHintLeftLength"); DockOverlayHintLeftLength->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintLeftLength->setMinimum(0); DockOverlayHintLeftLength->setMaximum(10000); DockOverlayHintLeftLength->setSingleStep(10); + DockOverlayHintLeftLength->setAlignment(Qt::AlignRight); + DockOverlayHintLeftLength->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintRightOffset = new QLabel(this); @@ -186,10 +206,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintRightOffset->setValue(Gui::OverlayParams::defaultDockOverlayHintRightOffset()); DockOverlayHintRightOffset->setEntryName("DockOverlayHintRightOffset"); DockOverlayHintRightOffset->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintRightOffset->setMinimum(0); DockOverlayHintRightOffset->setMaximum(10000); DockOverlayHintRightOffset->setSingleStep(10); + DockOverlayHintRightOffset->setAlignment(Qt::AlignRight); + DockOverlayHintRightOffset->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintRightLength = new QLabel(this); @@ -199,10 +221,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintRightLength->setValue(Gui::OverlayParams::defaultDockOverlayHintRightLength()); DockOverlayHintRightLength->setEntryName("DockOverlayHintRightLength"); DockOverlayHintRightLength->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintRightLength->setMinimum(0); DockOverlayHintRightLength->setMaximum(10000); DockOverlayHintRightLength->setSingleStep(10); + DockOverlayHintRightLength->setAlignment(Qt::AlignRight); + DockOverlayHintRightLength->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintTopOffset = new QLabel(this); @@ -212,10 +236,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintTopOffset->setValue(Gui::OverlayParams::defaultDockOverlayHintTopOffset()); DockOverlayHintTopOffset->setEntryName("DockOverlayHintTopOffset"); DockOverlayHintTopOffset->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintTopOffset->setMinimum(0); DockOverlayHintTopOffset->setMaximum(10000); DockOverlayHintTopOffset->setSingleStep(10); + DockOverlayHintTopOffset->setAlignment(Qt::AlignRight); + DockOverlayHintTopOffset->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintTopLength = new QLabel(this); @@ -225,10 +251,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintTopLength->setValue(Gui::OverlayParams::defaultDockOverlayHintTopLength()); DockOverlayHintTopLength->setEntryName("DockOverlayHintTopLength"); DockOverlayHintTopLength->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintTopLength->setMinimum(0); DockOverlayHintTopLength->setMaximum(10000); DockOverlayHintTopLength->setSingleStep(10); + DockOverlayHintTopLength->setAlignment(Qt::AlignRight); + DockOverlayHintTopLength->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintBottomOffset = new QLabel(this); @@ -238,10 +266,12 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintBottomOffset->setValue(Gui::OverlayParams::defaultDockOverlayHintBottomOffset()); DockOverlayHintBottomOffset->setEntryName("DockOverlayHintBottomOffset"); DockOverlayHintBottomOffset->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintBottomOffset->setMinimum(0); DockOverlayHintBottomOffset->setMaximum(10000); DockOverlayHintBottomOffset->setSingleStep(10); + DockOverlayHintBottomOffset->setAlignment(Qt::AlignRight); + DockOverlayHintBottomOffset->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintBottomLength = new QLabel(this); @@ -251,82 +281,85 @@ DlgSettingsAdvanced::DlgSettingsAdvanced(QWidget* parent) DockOverlayHintBottomLength->setValue(Gui::OverlayParams::defaultDockOverlayHintBottomLength()); DockOverlayHintBottomLength->setEntryName("DockOverlayHintBottomLength"); DockOverlayHintBottomLength->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintBottomLength->setMinimum(0); DockOverlayHintBottomLength->setMaximum(10000); DockOverlayHintBottomLength->setSingleStep(10); - - // Auto generated code (Tools/params_utils.py:433) - DockOverlayHintTabBar = new Gui::PrefCheckBox(this); - layoutOverlay->addWidget(DockOverlayHintTabBar, 13, 0); - DockOverlayHintTabBar->setChecked(Gui::OverlayParams::defaultDockOverlayHintTabBar()); - DockOverlayHintTabBar->setEntryName("DockOverlayHintTabBar"); - DockOverlayHintTabBar->setParamGrpPath("View"); + DockOverlayHintBottomLength->setAlignment(Qt::AlignRight); + DockOverlayHintBottomLength->setSuffix(QLatin1String(" px")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayHintDelay = new QLabel(this); - layoutOverlay->addWidget(labelDockOverlayHintDelay, 14, 0); + layoutOverlay->addWidget(labelDockOverlayHintDelay, 13, 0); DockOverlayHintDelay = new Gui::PrefSpinBox(this); - layoutOverlay->addWidget(DockOverlayHintDelay, 14, 1); + layoutOverlay->addWidget(DockOverlayHintDelay, 13, 1); DockOverlayHintDelay->setValue(Gui::OverlayParams::defaultDockOverlayHintDelay()); DockOverlayHintDelay->setEntryName("DockOverlayHintDelay"); DockOverlayHintDelay->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayHintDelay->setMinimum(0); DockOverlayHintDelay->setMaximum(1000); DockOverlayHintDelay->setSingleStep(100); + DockOverlayHintDelay->setAlignment(Qt::AlignRight); + DockOverlayHintDelay->setSuffix(QLatin1String(" ms")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlaySplitterHandleTimeout = new QLabel(this); - layoutOverlay->addWidget(labelDockOverlaySplitterHandleTimeout, 15, 0); + layoutOverlay->addWidget(labelDockOverlaySplitterHandleTimeout, 14, 0); DockOverlaySplitterHandleTimeout = new Gui::PrefSpinBox(this); - layoutOverlay->addWidget(DockOverlaySplitterHandleTimeout, 15, 1); + layoutOverlay->addWidget(DockOverlaySplitterHandleTimeout, 14, 1); DockOverlaySplitterHandleTimeout->setValue(Gui::OverlayParams::defaultDockOverlaySplitterHandleTimeout()); DockOverlaySplitterHandleTimeout->setEntryName("DockOverlaySplitterHandleTimeout"); DockOverlaySplitterHandleTimeout->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlaySplitterHandleTimeout->setMinimum(0); DockOverlaySplitterHandleTimeout->setMaximum(99999); DockOverlaySplitterHandleTimeout->setSingleStep(100); + DockOverlaySplitterHandleTimeout->setAlignment(Qt::AlignRight); + DockOverlaySplitterHandleTimeout->setSuffix(QLatin1String(" ms")); // Auto generated code (Tools/params_utils.py:433) DockOverlayActivateOnHover = new Gui::PrefCheckBox(this); - layoutOverlay->addWidget(DockOverlayActivateOnHover, 16, 0); + layoutOverlay->addWidget(DockOverlayActivateOnHover, 15, 0); DockOverlayActivateOnHover->setChecked(Gui::OverlayParams::defaultDockOverlayActivateOnHover()); DockOverlayActivateOnHover->setEntryName("DockOverlayActivateOnHover"); DockOverlayActivateOnHover->setParamGrpPath("View"); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayDelay = new QLabel(this); - layoutOverlay->addWidget(labelDockOverlayDelay, 17, 0); + layoutOverlay->addWidget(labelDockOverlayDelay, 16, 0); DockOverlayDelay = new Gui::PrefSpinBox(this); - layoutOverlay->addWidget(DockOverlayDelay, 17, 1); + layoutOverlay->addWidget(DockOverlayDelay, 16, 1); DockOverlayDelay->setValue(Gui::OverlayParams::defaultDockOverlayDelay()); DockOverlayDelay->setEntryName("DockOverlayDelay"); DockOverlayDelay->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayDelay->setMinimum(0); DockOverlayDelay->setMaximum(5000); DockOverlayDelay->setSingleStep(100); + DockOverlayDelay->setAlignment(Qt::AlignRight); + DockOverlayDelay->setSuffix(QLatin1String(" ms")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayAnimationDuration = new QLabel(this); - layoutOverlay->addWidget(labelDockOverlayAnimationDuration, 18, 0); + layoutOverlay->addWidget(labelDockOverlayAnimationDuration, 17, 0); DockOverlayAnimationDuration = new Gui::PrefSpinBox(this); - layoutOverlay->addWidget(DockOverlayAnimationDuration, 18, 1); + layoutOverlay->addWidget(DockOverlayAnimationDuration, 17, 1); DockOverlayAnimationDuration->setValue(Gui::OverlayParams::defaultDockOverlayAnimationDuration()); DockOverlayAnimationDuration->setEntryName("DockOverlayAnimationDuration"); DockOverlayAnimationDuration->setParamGrpPath("View"); - // Auto generated code (Tools/params_utils.py:1134) + // Auto generated code (Tools/params_utils.py:1135) DockOverlayAnimationDuration->setMinimum(0); DockOverlayAnimationDuration->setMaximum(5000); DockOverlayAnimationDuration->setSingleStep(100); + DockOverlayAnimationDuration->setAlignment(Qt::AlignRight); + DockOverlayAnimationDuration->setSuffix(QLatin1String(" ms")); // Auto generated code (Tools/params_utils.py:433) labelDockOverlayAnimationCurve = new QLabel(this); - layoutOverlay->addWidget(labelDockOverlayAnimationCurve, 19, 0); + layoutOverlay->addWidget(labelDockOverlayAnimationCurve, 18, 0); DockOverlayAnimationCurve = new Gui::PrefComboBox(this); - layoutOverlay->addWidget(DockOverlayAnimationCurve, 19, 1); + layoutOverlay->addWidget(DockOverlayAnimationCurve, 18, 1); DockOverlayAnimationCurve->setEntryName("DockOverlayAnimationCurve"); DockOverlayAnimationCurve->setParamGrpPath("View"); // Auto generated code (Gui/OverlayParams.py:94) @@ -363,7 +396,6 @@ void DlgSettingsAdvanced::saveSettings() DockOverlayHintTopLength->onSave(); DockOverlayHintBottomOffset->onSave(); DockOverlayHintBottomLength->onSave(); - DockOverlayHintTabBar->onSave(); DockOverlayHintDelay->onSave(); DockOverlaySplitterHandleTimeout->onSave(); DockOverlayActivateOnHover->onSave(); @@ -391,7 +423,6 @@ void DlgSettingsAdvanced::loadSettings() DockOverlayHintTopLength->onRestore(); DockOverlayHintBottomOffset->onRestore(); DockOverlayHintBottomLength->onRestore(); - DockOverlayHintTabBar->onRestore(); DockOverlayHintDelay->onRestore(); DockOverlaySplitterHandleTimeout->onRestore(); DockOverlayActivateOnHover->onRestore(); @@ -409,11 +440,11 @@ void DlgSettingsAdvanced::retranslateUi() labelItemBackgroundPadding->setText(QObject::tr("Item background padding")); labelItemBackgroundPadding->setToolTip(ItemBackgroundPadding->toolTip()); FontSize->setToolTip(QApplication::translate("TreeParams", Gui::TreeParams::docFontSize())); - labelFontSize->setText(QObject::tr("FontSize")); + labelFontSize->setText(QObject::tr("Font size")); labelFontSize->setToolTip(FontSize->toolTip()); groupOverlay->setTitle(QObject::tr("Overlay")); DockOverlayWheelDelay->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayWheelDelay())); - labelDockOverlayWheelDelay->setText(QObject::tr("Delay mouse wheel pass through (ms)")); + labelDockOverlayWheelDelay->setText(QObject::tr("Delay mouse wheel pass through")); labelDockOverlayWheelDelay->setToolTip(DockOverlayWheelDelay->toolTip()); DockOverlayAlphaRadius->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayAlphaRadius())); labelDockOverlayAlphaRadius->setText(QObject::tr("Alpha test radius")); @@ -450,21 +481,19 @@ void DlgSettingsAdvanced::retranslateUi() DockOverlayHintBottomLength->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayHintBottomLength())); labelDockOverlayHintBottomLength->setText(QObject::tr("Bottom panel hint length")); labelDockOverlayHintBottomLength->setToolTip(DockOverlayHintBottomLength->toolTip()); - DockOverlayHintTabBar->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayHintTabBar())); - DockOverlayHintTabBar->setText(QObject::tr("Hint show tab bar")); DockOverlayHintDelay->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayHintDelay())); - labelDockOverlayHintDelay->setText(QObject::tr("Hint delay (ms)")); + labelDockOverlayHintDelay->setText(QObject::tr("Hint delay")); labelDockOverlayHintDelay->setToolTip(DockOverlayHintDelay->toolTip()); DockOverlaySplitterHandleTimeout->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlaySplitterHandleTimeout())); - labelDockOverlaySplitterHandleTimeout->setText(QObject::tr("Splitter auto hide delay (ms)")); + labelDockOverlaySplitterHandleTimeout->setText(QObject::tr("Splitter auto hide delay")); labelDockOverlaySplitterHandleTimeout->setToolTip(DockOverlaySplitterHandleTimeout->toolTip()); DockOverlayActivateOnHover->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayActivateOnHover())); DockOverlayActivateOnHover->setText(QObject::tr("Activate on hover")); DockOverlayDelay->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayDelay())); - labelDockOverlayDelay->setText(QObject::tr("Layout delay (ms)")); + labelDockOverlayDelay->setText(QObject::tr("Layout delay")); labelDockOverlayDelay->setToolTip(DockOverlayDelay->toolTip()); DockOverlayAnimationDuration->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayAnimationDuration())); - labelDockOverlayAnimationDuration->setText(QObject::tr("Animation duration (ms)")); + labelDockOverlayAnimationDuration->setText(QObject::tr("Animation duration")); labelDockOverlayAnimationDuration->setToolTip(DockOverlayAnimationDuration->toolTip()); DockOverlayAnimationCurve->setToolTip(QApplication::translate("OverlayParams", Gui::OverlayParams::docDockOverlayAnimationCurve())); labelDockOverlayAnimationCurve->setText(QObject::tr("Animation curve type")); diff --git a/src/Gui/PreferencePages/DlgSettingsAdvanced.h b/src/Gui/PreferencePages/DlgSettingsAdvanced.h index ac54174c4975..01ae6411c79e 100644 --- a/src/Gui/PreferencePages/DlgSettingsAdvanced.h +++ b/src/Gui/PreferencePages/DlgSettingsAdvanced.h @@ -105,7 +105,6 @@ class DlgSettingsAdvanced : public Gui::Dialog::PreferencePage Gui::PrefSpinBox *DockOverlayHintBottomOffset = nullptr; QLabel *labelDockOverlayHintBottomLength = nullptr; Gui::PrefSpinBox *DockOverlayHintBottomLength = nullptr; - Gui::PrefCheckBox *DockOverlayHintTabBar = nullptr; QLabel *labelDockOverlayHintDelay = nullptr; Gui::PrefSpinBox *DockOverlayHintDelay = nullptr; QLabel *labelDockOverlaySplitterHandleTimeout = nullptr; diff --git a/src/Gui/TreeParams.py b/src/Gui/TreeParams.py index ff1e59858e57..abc2b592fa00 100644 --- a/src/Gui/TreeParams.py +++ b/src/Gui/TreeParams.py @@ -63,11 +63,11 @@ ParamInt('Indentation', 0, on_change=True), ParamBool('LabelExpression', False), ParamInt('IconSize', 0, on_change=True), - ParamInt('FontSize', 0, on_change=True, title='Font size'), + ParamInt('FontSize', 0, on_change=True, title='Font size', proxy=ParamSpinBox(0, 100, 1, suffix=" pt")), ParamInt('ItemSpacing', 0, on_change=True), ParamHex('ItemBackground', 0, on_change=True, title='Item background color', proxy=ParamColor(), doc = "Tree view item background. Only effective in overlay."), - ParamInt('ItemBackgroundPadding', 0, on_change=True, title="Item background padding", proxy=ParamSpinBox(0, 100, 1), + ParamInt('ItemBackgroundPadding', 0, on_change=True, title="Item background padding", proxy=ParamSpinBox(0, 100, 1, suffix=" px"), doc = "Tree view item background padding."), ParamBool('HideColumn', True, on_change=True, title="Hide Description", doc = "Hide extra tree view column for item description."), diff --git a/src/Tools/params_utils.py b/src/Tools/params_utils.py index 74ee71bea5ef..8c9537463bb8 100644 --- a/src/Tools/params_utils.py +++ b/src/Tools/params_utils.py @@ -19,8 +19,8 @@ # * USA * # * * # *************************************************************************** -"""Utilities for generating C++ code for parameter management using Python Cog -""" +"""Utilities for generating C++ code for parameter management using Python Cog""" + import cog import inspect import re @@ -1120,12 +1120,13 @@ class ParamFile(ParamProxy): class ParamSpinBox(ParamProxy): - def __init__(self, value_min, value_max, value_step, decimals=0, param_bool=None): + def __init__(self, value_min, value_max, value_step, decimals=0, param_bool=None, suffix=""): super().__init__(param_bool) self.value_min = value_min self.value_max = value_max self.value_step = value_step self.decimals = decimals + self.suffix = suffix def init_widget(self, param, row, group_name): super().init_widget(param, row, group_name) @@ -1134,13 +1135,19 @@ def init_widget(self, param, row, group_name): {trace_comment()} {param.widget_name}->setMinimum({self.value_min}); {param.widget_name}->setMaximum({self.value_max}); - {param.widget_name}->setSingleStep({self.value_step});""" + {param.widget_name}->setSingleStep({self.value_step}); + {param.widget_name}->setAlignment(Qt::AlignRight);""" ) if self.decimals: cog.out( f""" {param.widget_name}->setDecimals({self.decimals});""" ) + if self.suffix: + cog.out( + f""" + {param.widget_name}->setSuffix(QLatin1String("{self.suffix}"));""" + ) class ParamShortcutEdit(ParamProxy): From 89fcfe95ee08bdd0144d94a75425bc9cac66dbd7 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 25 Nov 2024 17:57:16 +0100 Subject: [PATCH 079/161] Sketcher: Offset & tranforms: enable external geos input. (#17615) * Sketcher: Offset & tranforms: enable external geos input. * Sketcher: enable delGeometries to handle external geos. --- src/Mod/Sketcher/App/SketchObject.cpp | 29 ++++++++++-- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 46 +++++++++++-------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index eb346a71874c..7bbc06c2c0c7 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1681,10 +1681,33 @@ int SketchObject::delGeometry(int GeoId, bool deleteinternalgeo) return 0; } - int SketchObject::delGeometries(const std::vector& GeoIds) { - std::vector sGeoIds(GeoIds); + std::vector sGeoIds; + std::vector negativeGeoIds; + + // Separate GeoIds into negative (external) and non-negative GeoIds + for (int geoId : GeoIds) { + if (geoId < 0 && geoId <= GeoEnum::RefExt) { + negativeGeoIds.push_back(geoId); + } + else if (geoId >= 0){ + sGeoIds.push_back(geoId); + } + } + + // Handle negative GeoIds by calling delExternal + if (!negativeGeoIds.empty()) { + int result = delExternal(negativeGeoIds); + if (result != 0) { + return result; // Return if deletion of external geometries failed + } + } + + // Proceed with non-negative GeoIds + if (sGeoIds.empty()) { + return 0; // No positive GeoIds to delete + } // if a GeoId has internal geometry, it must delete internal geometries too for (auto c : Constraints.getValues()) { @@ -7732,7 +7755,7 @@ int SketchObject::delExternal(const std::vector& ExtGeoIds) { std::set geoIds; for (int ExtGeoId : ExtGeoIds) { - int GeoId = GeoEnum::RefExt - ExtGeoId; + int GeoId = ExtGeoId > 0 ? GeoEnum::RefExt - ExtGeoId : ExtGeoId; if (GeoId > GeoEnum::RefExt || -GeoId - 1 >= ExternalGeo.getSize()) return -1; diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index a2ddc72884fe..7bfa00b82eb2 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -88,12 +88,13 @@ std::vector getListOfSelectedGeoIds(bool forceInternalSelection) if (!subNames.empty()) { for (auto& name : subNames) { - // only handle non-external edges if (name.size() > 4 && name.substr(0, 4) == "Edge") { int geoId = std::atoi(name.substr(4, 4000).c_str()) - 1; - if (geoId >= 0) { - listOfGeoIds.push_back(geoId); - } + listOfGeoIds.push_back(geoId); + } + else if (name.size() > 12 && name.substr(0, 12) == "ExternalEdge") { + int geoId = -std::atoi(name.substr(12, 4000).c_str()) - 2; + listOfGeoIds.push_back(geoId); } else if (name.size() > 6 && name.substr(0, 6) == "Vertex") { // only if it is a GeomPoint @@ -2341,23 +2342,28 @@ void CmdSketcherOffset::activated(int iMsg) const std::vector& subNames = selection[0].getSubNames(); if (!subNames.empty()) { for (auto& name : subNames) { - // only handle non-external edges + int geoId; if (name.size() > 4 && name.substr(0, 4) == "Edge") { - int geoId = std::atoi(name.substr(4, 4000).c_str()) - 1; - if (geoId >= 0) { - const Part::Geometry* geo = Obj->getGeometry(geoId); - if (!isPoint(*geo) - && !isBSplineCurve(*geo) - && !isEllipse(*geo) - && !isArcOfEllipse(*geo) - && !isArcOfHyperbola(*geo) - && !isArcOfParabola(*geo) - && !GeometryFacade::isInternalAligned(geo)) { - // Currently ellipse/parabola/hyperbola/bspline are not handled correctly. - // Occ engine gives offset of those as set of lines and arcs and does not seem to work consistently. - listOfGeoIds.push_back(geoId); - } - } + geoId = std::atoi(name.substr(4, 4000).c_str()) - 1; + } + else if (name.size() > 12 && name.substr(0, 12) == "ExternalEdge") { + geoId = -std::atoi(name.substr(12, 4000).c_str()) - 2; + } + else { + continue; + } + + const Part::Geometry* geo = Obj->getGeometry(geoId); + if (!isPoint(*geo) + && !isBSplineCurve(*geo) + && !isEllipse(*geo) + && !isArcOfEllipse(*geo) + && !isArcOfHyperbola(*geo) + && !isArcOfParabola(*geo) + && !GeometryFacade::isInternalAligned(geo)) { + // Currently ellipse/parabola/hyperbola/bspline are not handled correctly. + // Occ engine gives offset of those as set of lines and arcs and does not seem to work consistently. + listOfGeoIds.push_back(geoId); } } } From 89049add9eda58763348eec8062573106600f81b Mon Sep 17 00:00:00 2001 From: David Carter Date: Thu, 24 Oct 2024 00:10:46 -0400 Subject: [PATCH 080/161] Materials: Physical property attributes Add dynamic attributes to report the physical attributes of a part that are automatically recalculaated when the shape or material changes. These values are accessible from the part data display and as attributes within Python --- src/Mod/Material/App/MaterialFilter.cpp | 12 ++++++ src/Mod/Material/App/MaterialFilter.h | 10 +++++ src/Mod/Material/App/Materials.cpp | 10 +++++ src/Mod/Material/App/Materials.h | 2 + src/Mod/Material/Gui/DlgMaterialImp.cpp | 12 +++--- src/Mod/Part/App/PartFeature.cpp | 57 ++++++++++++++++++++++++- src/Mod/Part/App/PartFeature.h | 10 +++++ 7 files changed, 105 insertions(+), 8 deletions(-) diff --git a/src/Mod/Material/App/MaterialFilter.cpp b/src/Mod/Material/App/MaterialFilter.cpp index 3efe8087f752..e01654a696db 100644 --- a/src/Mod/Material/App/MaterialFilter.cpp +++ b/src/Mod/Material/App/MaterialFilter.cpp @@ -62,10 +62,22 @@ TYPESYSTEM_SOURCE(Materials::MaterialFilter, Base::BaseClass) MaterialFilter::MaterialFilter() : _required() , _requiredComplete() + , _requirePhysical(false) + , _requireAppearance(false) {} bool MaterialFilter::modelIncluded(const std::shared_ptr& material) const { + if (_requirePhysical) { + if (!material->hasPhysicalProperties()) { + return false; + } + } + if (_requireAppearance) { + if (!material->hasAppearanceProperties()) { + return false; + } + } for (const auto& complete : _requiredComplete) { if (!material->isModelComplete(complete)) { return false; diff --git a/src/Mod/Material/App/MaterialFilter.h b/src/Mod/Material/App/MaterialFilter.h index 0d2b5d7b2169..7645d75971c4 100644 --- a/src/Mod/Material/App/MaterialFilter.h +++ b/src/Mod/Material/App/MaterialFilter.h @@ -172,6 +172,14 @@ class MaterialsExport MaterialFilter: public Base::BaseClass void addRequired(const QString& uuid); void addRequiredComplete(const QString& uuid); + /* Require that the materials have physical properties defined. + */ + void requirePhysical(bool required) { _requirePhysical = required; } + + /* Require that the materials have appearance properties defined. + */ + void requireAppearance(bool required) { _requireAppearance = required; } + /* These functions shouldn't normally be called directly. They are * for use by conversion methods, such as MaterialFilterPy */ @@ -190,6 +198,8 @@ class MaterialsExport MaterialFilter: public Base::BaseClass QString _name; QSet _required; QSet _requiredComplete; + bool _requirePhysical; + bool _requireAppearance; }; } // namespace Materials diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index 0b6f1c3e179f..3a5bc13fddb3 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -1108,6 +1108,16 @@ bool Material::hasLegacyProperties() const return !_legacy.empty(); } +bool Material::hasPhysicalProperties() const +{ + return !_physicalUuids.isEmpty(); +} + +bool Material::hasAppearanceProperties() const +{ + return !_appearanceUuids.isEmpty(); +} + bool Material::isInherited(const QString& uuid) const { if (_physicalUuids.contains(uuid)) { diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index 46ae8d99439a..52597f1ba079 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -335,6 +335,8 @@ class MaterialsExport Material: public Base::BaseClass bool hasNonLegacyProperty(const QString& name) const; bool hasLegacyProperty(const QString& name) const; bool hasLegacyProperties() const; + bool hasPhysicalProperties() const; + bool hasAppearanceProperties() const; // Test if the model is defined, and if values are provided for all properties bool hasModel(const QString& uuid) const; diff --git a/src/Mod/Material/Gui/DlgMaterialImp.cpp b/src/Mod/Material/Gui/DlgMaterialImp.cpp index c970752e6483..e89c718c73f4 100644 --- a/src/Mod/Material/Gui/DlgMaterialImp.cpp +++ b/src/Mod/Material/Gui/DlgMaterialImp.cpp @@ -83,13 +83,11 @@ DlgMaterialImp::DlgMaterialImp(bool floating, QWidget* parent, Qt::WindowFlags f d->floating = floating; - // // Create a filter to only include current format materials - // // that contain the basic render model. - // auto filter = std::make_shared(); - // filter->setIncludeEmptyFolders(false); - // filter->setIncludeLegacy(false); - // filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); - // d->ui.widgetMaterial->setFilter(filter); + // Create a filter to only include current format materials + // that contain physical properties. + auto filter = std::make_shared(); + filter->requirePhysical(true); + d->ui.widgetMaterial->setFilter(filter); std::vector objects = getSelectionObjects(); setMaterial(objects); diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index ad967dd3a8e8..408b7a79f9bd 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -89,8 +89,34 @@ Feature::Feature() { ADD_PROPERTY(Shape, (TopoDS_Shape())); auto mat = Materials::MaterialManager::defaultMaterial(); - // ADD_PROPERTY_TYPE(ShapeMaterial, (mat), osgroup, App::Prop_None, "Shape material"); ADD_PROPERTY(ShapeMaterial, (*mat)); + + // Read only properties based on the material + static const char* group = "PhysicalProperties"; + ADD_PROPERTY_TYPE(MaterialName, + (""), + group, + static_cast(App::Prop_ReadOnly | App::Prop_Output + | App::Prop_NoRecompute | App::Prop_NoPersist), + "Feature material"); + ADD_PROPERTY_TYPE(Density, + (0.0), + group, + static_cast(App::Prop_ReadOnly | App::Prop_Output + | App::Prop_NoRecompute | App::Prop_NoPersist), + "Feature density"); + ADD_PROPERTY_TYPE(Mass, + (0.0), + group, + static_cast(App::Prop_ReadOnly | App::Prop_Output + | App::Prop_NoRecompute | App::Prop_NoPersist), + "Feature mass"); + ADD_PROPERTY_TYPE(Volume, + (1.0), + group, + static_cast(App::Prop_ReadOnly | App::Prop_Output + | App::Prop_NoRecompute | App::Prop_NoPersist), + "Feature volume"); } Feature::~Feature() = default; @@ -1477,11 +1503,40 @@ void Feature::onChanged(const App::Property* prop) } } } + updatePhysicalProperties(); + } else if (prop == &this->ShapeMaterial) { + updatePhysicalProperties(); } GeoFeature::onChanged(prop); } +void Feature::updatePhysicalProperties() +{ + MaterialName.setValue(ShapeMaterial.getValue().getName().toStdString()); + if (ShapeMaterial.getValue().hasPhysicalProperty(QString::fromLatin1("Density"))) { + Density.setValue(ShapeMaterial.getValue() + .getPhysicalQuantity(QString::fromLatin1("Density")) + .getValue()); + } else { + Base::Console().Log("Density is undefined\n"); + Density.setValue(0.0); + } + + auto topoShape = Shape.getValue(); + if (!topoShape.IsNull()) { + GProp_GProps props; + BRepGProp::VolumeProperties(topoShape, props); + Volume.setValue(props.Mass()); + Mass.setValue(Volume.getValue() * Density.getValue()); + } else { + // No shape + Base::Console().Log("No shape defined\n"); + Volume.setValue(0.0); + Mass.setValue(0.0); + } +} + const std::vector& Feature::searchElementCache(const std::string& element, Data::SearchOptions options, diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index c865f0ab4c1c..4311fe2be27b 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -60,6 +61,12 @@ class PartExport Feature : public App::GeoFeature PropertyPartShape Shape; Materials::PropertyMaterial ShapeMaterial; + // Convenience properties set when material or shape changes + App::PropertyString MaterialName; + App::PropertyDensity Density; + App::PropertyMass Mass; + App::PropertyVolume Volume; + /** @name methods override feature */ //@{ short mustExecute() const override; @@ -172,6 +179,9 @@ class PartExport Feature : public App::GeoFeature void copyMaterial(Feature* feature); void copyMaterial(App::DocumentObject* link); + /// Update the mass and volume properties + void updatePhysicalProperties(); + void registerElementCache(const std::string &prefix, PropertyPartShape *prop); /** Helper function to obtain mapped and indexed element name from a shape From 7f0d69a3bde4596872dbca67ce641ace3f442882 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Thu, 14 Nov 2024 19:20:20 +0000 Subject: [PATCH 081/161] BIM: Replace use of ArchWorkbench in ArchSelectionObserver --- src/Mod/BIM/ArchComponent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index f4dd0da94593..abf57a075a0f 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -1645,7 +1645,7 @@ def addSelection(self,document, object, element, position): self.origin.ViewObject.Transparency = 0 self.origin.ViewObject.Selectable = True self.watched.ViewObject.hide() - FreeCADGui.activateWorkbench("ArchWorkbench") + FreeCADGui.activateWorkbench("BIMWorkbench") if hasattr(FreeCAD,"ArchObserver"): FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver) del FreeCAD.ArchObserver From 96cc00b74e317415084cdfd2237165383faf62ea Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 14 Nov 2024 12:07:21 -0300 Subject: [PATCH 082/161] Fem: Check empty remaining femelements array - fixes #17570 --- src/Mod/Fem/femmesh/meshtools.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/femmesh/meshtools.py b/src/Mod/Fem/femmesh/meshtools.py index 9faffc1c1ecf..766836c9d66a 100644 --- a/src/Mod/Fem/femmesh/meshtools.py +++ b/src/Mod/Fem/femmesh/meshtools.py @@ -411,7 +411,11 @@ def get_femelement_sets(femmesh, femelement_table, fem_objects, femnodes_ele_tab femelement_table_array = np.zeros_like(referenced_femelements) femelement_table_array[list(femelement_table)] = 1 remaining_femelements_array = femelement_table_array > referenced_femelements - remaining_femelements = [i.item() for i in np.nditer(remaining_femelements_array.nonzero())] + (non_zeros,) = remaining_femelements_array.nonzero() + if non_zeros.size: + remaining_femelements = [i.item() for i in np.nditer(non_zeros)] + else: + remaining_femelements = [] count_femelements += len(remaining_femelements) for fem_object in fem_objects: obj = fem_object["Object"] From c32628ec0df839bff092283a66a716657c78e7f1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 16 Nov 2024 12:37:32 +0100 Subject: [PATCH 083/161] Part: Fix alpha <> transparency conversion --- src/Mod/Import/TestImportGui.py | 24 ++++----- .../materialtests/TestMaterialDocument.py | 10 ++-- src/Mod/Part/Gui/ViewProviderPartExtPyImp.cpp | 8 ++- src/Mod/Part/parttests/ColorPerFaceTest.py | 50 +++++++++---------- 4 files changed, 45 insertions(+), 47 deletions(-) diff --git a/src/Mod/Import/TestImportGui.py b/src/Mod/Import/TestImportGui.py index 8f2d3f7d4874..9f2d6eb25a70 100644 --- a/src/Mod/Import/TestImportGui.py +++ b/src/Mod/Import/TestImportGui.py @@ -45,12 +45,12 @@ def testSaveLoadStepFile(self): self.doc.recompute() box.ViewObject.DiffuseColor = [ - (1.0, 0.0, 0.0, 0.0), - (1.0, 0.0, 0.0, 0.0), - (1.0, 0.0, 0.0, 0.0), - (1.0, 0.0, 0.0, 0.0), - (1.0, 1.0, 0.0, 0.0), - (1.0, 1.0, 0.0, 0.0), + (1.0, 0.0, 0.0, 1.0), + (1.0, 0.0, 0.0, 1.0), + (1.0, 0.0, 0.0, 1.0), + (1.0, 0.0, 0.0, 1.0), + (1.0, 1.0, 0.0, 1.0), + (1.0, 1.0, 0.0, 1.0), ] ImportGui.export([part], self.fileName) @@ -63,12 +63,12 @@ def testSaveLoadStepFile(self): feature = part_features[0] self.assertEqual(len(feature.ViewObject.DiffuseColor), 6) - self.assertEqual(feature.ViewObject.DiffuseColor[0], (1.0, 0.0, 0.0, 0.0)) - self.assertEqual(feature.ViewObject.DiffuseColor[1], (1.0, 0.0, 0.0, 0.0)) - self.assertEqual(feature.ViewObject.DiffuseColor[2], (1.0, 0.0, 0.0, 0.0)) - self.assertEqual(feature.ViewObject.DiffuseColor[3], (1.0, 0.0, 0.0, 0.0)) - self.assertEqual(feature.ViewObject.DiffuseColor[4], (1.0, 1.0, 0.0, 0.0)) - self.assertEqual(feature.ViewObject.DiffuseColor[5], (1.0, 1.0, 0.0, 0.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[0], (1.0, 0.0, 0.0, 1.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[1], (1.0, 0.0, 0.0, 1.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[2], (1.0, 0.0, 0.0, 1.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[3], (1.0, 0.0, 0.0, 1.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[4], (1.0, 1.0, 0.0, 1.0)) + self.assertEqual(feature.ViewObject.DiffuseColor[5], (1.0, 1.0, 0.0, 1.0)) sa = coin.SoSearchAction() sa.setType(coin.SoMaterialBinding.getClassTypeId()) diff --git a/src/Mod/Material/materialtests/TestMaterialDocument.py b/src/Mod/Material/materialtests/TestMaterialDocument.py index 821cec09e79b..4b2bb86ecf71 100644 --- a/src/Mod/Material/materialtests/TestMaterialDocument.py +++ b/src/Mod/Material/materialtests/TestMaterialDocument.py @@ -36,7 +36,7 @@ def tearDown(self): def testApplyDiffuseColorCheckShapeAppearance(self): """ Test that applying a DiffuseColor with transparency results in a correct ShapeAppearance """ - dif_col_1 = (1.0, 1.0, 0.0, 0.0) # yellow 0% transparent + dif_col_1 = (1.0, 1.0, 0.0, 1.0) # yellow 0% transparent dif_col_2 = (1.0, 0.0, 0.0, 0.5) # red 50% transparent dif_col = [dif_col_1] + [dif_col_2] + 4 * [dif_col_1] @@ -45,17 +45,17 @@ def testApplyDiffuseColorCheckShapeAppearance(self): vobj.DiffuseColor = dif_col self.assertEqual( - [m.DiffuseColor[:3] + (m.Transparency, ) for m in vobj.ShapeAppearance], + [m.DiffuseColor[:3] + (1.0 - m.Transparency, ) for m in vobj.ShapeAppearance], vobj.DiffuseColor ) def testApplyShapeAppearanceCheckDiffuseColor(self): """ Test that applying a ShapeAppearance with transparency results in a correct DiffuseColor """ sapp_1 = FreeCAD.Material() - sapp_1.DiffuseColor = (0.0, 1.0, 1.0, 1.0) # cyan + sapp_1.DiffuseColor = (0.0, 1.0, 1.0, 0.0) # cyan sapp_1.Transparency = 0.0 # 0% transparent sapp_2 = FreeCAD.Material() - sapp_2.DiffuseColor = (0.0, 1.0, 0.0, 1.0) # green + sapp_2.DiffuseColor = (0.0, 1.0, 0.0, 0.0) # green sapp_2.Transparency = 0.3 # 30% transparent sapp = [sapp_1] + [sapp_2] + 4 * [sapp_1] @@ -64,6 +64,6 @@ def testApplyShapeAppearanceCheckDiffuseColor(self): vobj.ShapeAppearance = sapp self.assertEqual( - [m.DiffuseColor[:3] + (m.Transparency, ) for m in vobj.ShapeAppearance], + [m.DiffuseColor[:3] + (1.0 - m.Transparency, ) for m in vobj.ShapeAppearance], vobj.DiffuseColor ) diff --git a/src/Mod/Part/Gui/ViewProviderPartExtPyImp.cpp b/src/Mod/Part/Gui/ViewProviderPartExtPyImp.cpp index adc59b9b980c..d54580160ae8 100644 --- a/src/Mod/Part/Gui/ViewProviderPartExtPyImp.cpp +++ b/src/Mod/Part/Gui/ViewProviderPartExtPyImp.cpp @@ -52,11 +52,10 @@ PyObject* ViewProviderPartExtPy::getCustomAttributes(const char* attr) const // Get the color properties App::PropertyColorList prop; - // v0.21 used the alpha channel to store transparency values std::vector colors = vp->ShapeAppearance.getDiffuseColors(); std::vector transparencies = vp->ShapeAppearance.getTransparencies(); for (int i = 0; i < static_cast(colors.size()); i++) { - colors[i].a = transparencies[i]; + colors[i].setTransparency(transparencies[i]); } prop.setValues(colors); @@ -73,13 +72,12 @@ int ViewProviderPartExtPy::setCustomAttributes(const char* attr, PyObject* obj) App::PropertyColorList prop; prop.setPyObject(obj); - // v0.21 used the alpha channel to store transparency values std::vector colors = prop.getValues(); std::vector transparencies; transparencies.resize(static_cast(colors.size())); for (int i = 0; i < static_cast(colors.size()); i++) { - transparencies[i] = colors[i].a; - colors[i].a = 1.0; + transparencies[i] = colors[i].transparency(); + colors[i].a = 1.0F; } vp->ShapeAppearance.setDiffuseColors(colors); vp->ShapeAppearance.setTransparencies(transparencies); diff --git a/src/Mod/Part/parttests/ColorPerFaceTest.py b/src/Mod/Part/parttests/ColorPerFaceTest.py index ec50bf9c70b7..3086efa73868 100644 --- a/src/Mod/Part/parttests/ColorPerFaceTest.py +++ b/src/Mod/Part/parttests/ColorPerFaceTest.py @@ -24,12 +24,12 @@ def testBox(self): box = self.doc.addObject("Part::Box","Box") self.doc.recompute() - box.ViewObject.DiffuseColor = [(1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,1.,0.,0.), - (1.,1.,0.,0.)] + box.ViewObject.DiffuseColor = [(1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,1.,0.,1.), + (1.,1.,0.,1.)] box.Visibility = False self.doc.recompute() @@ -56,12 +56,12 @@ def testBoxAndLink(self): box = self.doc.addObject("Part::Box","Box") self.doc.recompute() - box.ViewObject.DiffuseColor = [(1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,1.,0.,0.), - (1.,1.,0.,0.)] + box.ViewObject.DiffuseColor = [(1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,1.,0.,1.), + (1.,1.,0.,1.)] link = self.doc.addObject('App::Link','Link') link.setLink(box) @@ -93,12 +93,12 @@ def testTransparency(self): box = self.doc.addObject("Part::Box","Box") self.doc.recompute() - box.ViewObject.DiffuseColor = [(1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,0.,0.,0.), - (1.,1.,0.,0.), - (1.,1.,0.,0.)] + box.ViewObject.DiffuseColor = [(1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,0.,0.,1.), + (1.,1.,0.,1.), + (1.,1.,0.,1.)] box.ViewObject.Transparency = 35 self.assertEqual(box.ViewObject.Transparency, 35) @@ -129,8 +129,8 @@ def testMultiFuse(self): """ box = self.doc.addObject("Part::Box","Box") cyl = self.doc.addObject("Part::Cylinder","Cylinder") - box.ViewObject.ShapeColor = (1.,0.,0.,0.) - cyl.ViewObject.ShapeColor = (1.,0.,0.,0.) + box.ViewObject.ShapeColor = (1.,0.,0.,1.) + cyl.ViewObject.ShapeColor = (1.,0.,0.,1.) self.doc.recompute() bp = BOPFeatures.BOPFeatures(self.doc) @@ -161,13 +161,13 @@ def testMultiFuse(self): self.assertEqual(len(fuse.Shape.Faces), 11) self.assertEqual(len(fuse.ViewObject.DiffuseColor), 11) - self.assertEqual(fuse.ViewObject.DiffuseColor[0], (1.,0.,0.,0.)) + self.assertEqual(fuse.ViewObject.DiffuseColor[0], (1.,0.,0.,1.)) def testMultiFuseSaveRestore(self): box = self.doc.addObject("Part::Box","Box") cyl = self.doc.addObject("Part::Cylinder","Cylinder") - box.ViewObject.ShapeColor = (1.,0.,0.,0.) - cyl.ViewObject.ShapeColor = (1.,0.,0.,0.) + box.ViewObject.ShapeColor = (1.,0.,0.,1.) + cyl.ViewObject.ShapeColor = (1.,0.,0.,1.) self.doc.recompute() bp = BOPFeatures.BOPFeatures(self.doc) @@ -176,7 +176,7 @@ def testMultiFuseSaveRestore(self): fuse.Refine = False self.doc.recompute() - fuse.ViewObject.DiffuseColor = [(1.,0.,0.,0.)] * 11 + fuse.ViewObject.DiffuseColor = [(1.,0.,0.,1.)] * 11 self.doc.saveAs(self.fileName) App.closeDocument(self.doc.Name) @@ -186,7 +186,7 @@ def testMultiFuseSaveRestore(self): fuse = self.doc.ActiveObject self.assertEqual(len(fuse.Shape.Faces), 11) self.assertEqual(len(fuse.ViewObject.DiffuseColor), 11) - self.assertEqual(fuse.ViewObject.DiffuseColor[0], (1.,0.,0.,0.)) + self.assertEqual(fuse.ViewObject.DiffuseColor[0], (1.,0.,0.,1.)) sa = coin.SoSearchAction() sa.setType(coin.SoMaterialBinding.getClassTypeId()) From 93c807b6a6488efba164a402bad6a5b5b7b7ef74 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Fri, 20 Sep 2024 10:40:44 +0200 Subject: [PATCH 084/161] Update Std_Axis.svg as it had poor visibility in dark themes: planes and axis looked both like planes. --- src/Gui/Icons/Std_Axis.svg | 113 +++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 60 deletions(-) diff --git a/src/Gui/Icons/Std_Axis.svg b/src/Gui/Icons/Std_Axis.svg index c894f9ec2a18..805eca3b7040 100644 --- a/src/Gui/Icons/Std_Axis.svg +++ b/src/Gui/Icons/Std_Axis.svg @@ -1,28 +1,38 @@ - - + inkscape:export-ydpi="90" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + @@ -95,6 +105,16 @@ offset="1" id="stop3780" /> + + inkscape:snap-global="false" + objecttolerance="10.0" + gridtolerance="10.0" + guidetolerance="10.0" + inkscape:pagecheckerboard="0"> image/svg+xml - [wmayer] @@ -180,45 +203,15 @@ inkscape:export-ydpi="3.2478156" transform="translate(-2.96179e-7,2.9614273e-6)"> - - - - - + transform="matrix(0.85509196,0.51847636,0,1,0,0)" + rx="0" + ry="0" + y="536.84424" + x="1075.1082" + height="34.667957" + width="435.30161" + id="rect4154" + style="fill:url(#linearGradient1394);fill-opacity:1;stroke:#2d2d2d;stroke-width:15.81178795;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> From a9bc28daa04eb51a12e88c6a5dc792df76b1f549 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Fri, 20 Sep 2024 10:41:21 +0200 Subject: [PATCH 085/161] Add Std_Point.svg icon for datum points --- src/Gui/Icons/Std_Point.svg | 236 ++++++++++++++++++++++++++++++++++++ src/Gui/Icons/resource.qrc | 1 + 2 files changed, 237 insertions(+) create mode 100644 src/Gui/Icons/Std_Point.svg diff --git a/src/Gui/Icons/Std_Point.svg b/src/Gui/Icons/Std_Point.svg new file mode 100644 index 000000000000..29bb4ccecaf0 --- /dev/null +++ b/src/Gui/Icons/Std_Point.svg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + Sketcher_Sketch + 2011-10-10 + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_Sketch.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc index 901e5389a38d..34bd914d37df 100644 --- a/src/Gui/Icons/resource.qrc +++ b/src/Gui/Icons/resource.qrc @@ -261,6 +261,7 @@ Group.svg Geofeaturegroup.svg Geoassembly.svg + Std_Point.svg Std_Axis.svg Std_Plane.svg Link.svg From 7c1a5ebd69f3887cc3ed7c9ac528474ce1ed912b Mon Sep 17 00:00:00 2001 From: bgbsww Date: Thu, 26 Sep 2024 08:35:43 -0400 Subject: [PATCH 086/161] Tweak VSCode debug port to work with current versions --- contrib/.vscode/launch.json | 2 +- contrib/.vscode/scripts/VSCodeAutostartDebug.FCMacro | 6 +++++- contrib/.vscode/scripts/WaitForDebugpy.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contrib/.vscode/launch.json b/contrib/.vscode/launch.json index a10227e4aae5..6d04a9973fd7 100644 --- a/contrib/.vscode/launch.json +++ b/contrib/.vscode/launch.json @@ -66,7 +66,7 @@ "redirectOutput": true, "connect": { "host": "localhost", - "port": 5678 + "port": 5679 }, "pathMappings": [ { diff --git a/contrib/.vscode/scripts/VSCodeAutostartDebug.FCMacro b/contrib/.vscode/scripts/VSCodeAutostartDebug.FCMacro index 8901de6b6206..7765f9682b9a 100644 --- a/contrib/.vscode/scripts/VSCodeAutostartDebug.FCMacro +++ b/contrib/.vscode/scripts/VSCodeAutostartDebug.FCMacro @@ -7,7 +7,11 @@ from freecad.utils import get_python_exe # By default it attempts to use Freecad's PID mistaking it for python. # https://github.com/microsoft/debugpy/issues/262 debugpy.configure(python=get_python_exe()) -debugpy.listen(('localhost', 5678)) +# As of Python 3.12, debugpy runs a forwarding process that listens both on the port specified here for the debugger +# to connect to, but also on an internal port for the underlying pydevd within the python process to connect to. The +# default for that internal port is 5678, so we need to not duplicate it for the external port. Also, on Linux the +# attempt to spawn the forwarding process separately fails, so we force it to be internal to our main process. +debugpy.listen(('localhost', 5679),in_process_debug_adapter=True) # Turns out you cannot probe debugpy to see if it is up: # https://github.com/microsoft/debugpy/issues/974 diff --git a/contrib/.vscode/scripts/WaitForDebugpy.py b/contrib/.vscode/scripts/WaitForDebugpy.py index 4f8f70c899e0..592389259b2f 100644 --- a/contrib/.vscode/scripts/WaitForDebugpy.py +++ b/contrib/.vscode/scripts/WaitForDebugpy.py @@ -13,8 +13,8 @@ def check_socket(host, port): return sock.connect_ex((host, port)) == 0 def main(): - # DO NOT CHECK 5678 or debugpy will break - # Check other port manually opened instead + # DO NOT CHECK the actual port 5678/5879 or debugpy will break + # Check that the other port 39999 used as a flag is manually opened instead attempt_counter = 0 while (not check_socket('localhost', 39999)) and attempt_counter < MAX_ATTEMPTS: time.sleep(RETRY_DELAY_S) From 8945260a7e18466c78faa38f9df0fb2f873e849b Mon Sep 17 00:00:00 2001 From: Benjamin Nauck Date: Thu, 19 Sep 2024 00:15:43 +0200 Subject: [PATCH 087/161] Add two options to disable addons Addons can be disabled in two ways: * by adding a command line argument `--disable-addon ` * and by creating a `ALL_ADDONS_DISABLED` file in the mod root of the addons to disable --- src/App/Application.cpp | 11 +++++++++++ src/App/FreeCADInit.py | 28 ++++++++++++++++++++++++---- src/Gui/FreeCADGuiInit.py | 28 ++++++++++++++++++++++++---- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 9384790627da..bd7bd182c13d 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -2250,6 +2250,7 @@ void parseProgramOptions(int ac, char ** av, const string& exe, variables_map& v ("run-open,r", value()->implicit_value(""),"Run a given test case (use 0 (zero) to run all tests). If no argument is provided then return list of all available tests. Keeps UI open after test(s) complete.") ("module-path,M", value< vector >()->composing(),"Additional module paths") ("python-path,P", value< vector >()->composing(),"Additional python paths") + ("disable-addon", value< vector >()->composing(),"Disable a given addon.") ("single-instance", "Allow to run a single instance of the application") ("safe-mode", "Force enable safe mode") ("pass", value< vector >()->multitoken(), "Ignores the following arguments and pass them through to be used by a script") @@ -2431,6 +2432,16 @@ void processProgramOptions(const variables_map& vm, std::map >(); + string temp; + for (const auto & It : Addons) { + temp += It + ";"; + } + temp.erase(temp.end()-1); + mConfig["DisabledAddons"] = temp; + } + if (vm.count("input-file")) { vector files(vm["input-file"].as< vector >()); int OpenFileCount=0; diff --git a/src/App/FreeCADInit.py b/src/App/FreeCADInit.py index 36e7c2a23a7e..b020f0fd3123 100644 --- a/src/App/FreeCADInit.py +++ b/src/App/FreeCADInit.py @@ -106,6 +106,7 @@ def InitApplications(): MacroMod = os.path.realpath(MacroDir+"/Mod") SystemWideMacroDir = FreeCAD.getHomePath()+'Macro' SystemWideMacroDir = os.path.realpath(SystemWideMacroDir) + DisabledAddons = FreeCAD.ConfigGet("DisabledAddons").split(";") #print FreeCAD.getHomePath() if os.path.isdir(FreeCAD.getHomePath()+'src\\Tools'): @@ -218,11 +219,30 @@ def tryProcessMetadataFile(MetadataFile): except Exception as exc: Err(str(exc)) + def checkIfAddonIsDisabled(Dir): + Name = os.path.basename(Dir) + + if Name in DisabledAddons: + Msg(f'NOTICE: Addon "{Name}" disabled by presence of "--disable-addon {Name}" argument\n') + return True + + stopFileName = "ALL_ADDONS_DISABLED" + stopFile = os.path.join(Dir, os.path.pardir, stopFileName) + if os.path.exists(stopFile): + Msg(f'NOTICE: Addon "{Dir}" disabled by presence of {stopFileName} stopfile\n') + return True + + stopFileName = "ADDON_DISABLED" + stopFile = os.path.join(Dir, stopFileName) + if os.path.exists(stopFile): + Msg(f'NOTICE: Addon "{Dir}" disabled by presence of {stopFileName} stopfile\n') + return True + + return False + for Dir in ModDict.values(): - if ((Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py')): - stopFile = os.path.join(Dir, "ADDON_DISABLED") - if os.path.exists(stopFile): - Msg(f'NOTICE: Addon "{Dir}" disabled by presence of ADDON_DISABLED stopfile\n') + if Dir not in ['', 'CVS', '__init__.py']: + if checkIfAddonIsDisabled(Dir): continue sys.path.insert(0,Dir) PathExtension.append(Dir) diff --git a/src/Gui/FreeCADGuiInit.py b/src/Gui/FreeCADGuiInit.py index 06c5146cbca1..97f4910d4372 100644 --- a/src/Gui/FreeCADGuiInit.py +++ b/src/Gui/FreeCADGuiInit.py @@ -192,11 +192,31 @@ def tryProcessMetadataFile(Dir, MetadataFile): except Exception as exc: Err(str(exc)) + def checkIfAddonIsDisabled(Dir): + DisabledAddons = FreeCAD.ConfigGet("DisabledAddons").split(";") + Name = os.path.basename(Dir) + + if Name in DisabledAddons: + Msg(f'NOTICE: Addon "{Name}" disabled by presence of "--disable-addon {Name}" argument\n') + return True + + stopFileName = "ALL_ADDONS_DISABLED" + stopFile = os.path.join(Dir, os.path.pardir, stopFileName) + if os.path.exists(stopFile): + Msg(f'NOTICE: Addon "{Dir}" disabled by presence of {stopFileName} stopfile\n') + return True + + stopFileName = "ADDON_DISABLED" + stopFile = os.path.join(Dir, stopFileName) + if os.path.exists(stopFile): + Msg(f'NOTICE: Addon "{Dir}" disabled by presence of {stopFileName} stopfile\n') + return True + + return False + for Dir in ModDirs: - if (Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py'): - stopFile = os.path.join(Dir, "ADDON_DISABLED") - if os.path.exists(stopFile): - Msg(f'NOTICE: Addon "{Dir}" disabled by presence of ADDON_DISABLED stopfile\n') + if Dir not in ['', 'CVS', '__init__.py']: + if checkIfAddonIsDisabled(Dir): continue MetadataFile = os.path.join(Dir, "package.xml") if os.path.exists(MetadataFile): From 99b2f232147668f8df4a5e7be0812ef00f24e88a Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 18 Nov 2024 15:11:52 +0100 Subject: [PATCH 088/161] Assembly: Fix joints not being deleted when subassembly is deleted. --- src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 64 +++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index dabbcd7c819a..674fc5dcf517 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -60,6 +60,7 @@ #include #include +#include #include #include #include @@ -1066,36 +1067,63 @@ bool ViewProviderAssembly::onDelete(const std::vector& subNames) return ViewProviderPart::onDelete(subNames); } -bool ViewProviderAssembly::canDelete(App::DocumentObject* obj) const +bool ViewProviderAssembly::canDelete(App::DocumentObject* objBeingDeleted) const { - bool res = ViewProviderPart::canDelete(obj); + bool res = ViewProviderPart::canDelete(objBeingDeleted); if (res) { // If a component is deleted, then we delete the joints as well. auto* assemblyPart = static_cast(getObject()); std::vector objToDel; + std::vector objsBeingDeleted; + objsBeingDeleted.push_back(objBeingDeleted); + + auto addSubComponents = + std::function&)> {}; + addSubComponents = [&](AssemblyLink* asmLink, std::vector& objs) { + std::vector assemblyLinkGroup = asmLink->Group.getValues(); + for (auto* obj : assemblyLinkGroup) { + auto* subAsmLink = dynamic_cast(obj); + auto* link = dynamic_cast(obj); + if (subAsmLink || link) { + if (std::find(objs.begin(), objs.end(), obj) == objs.end()) { + objs.push_back(obj); + if (subAsmLink && !asmLink->isRigid()) { + addSubComponents(subAsmLink, objs); + } + } + } + } + }; - // List its joints - std::vector joints = assemblyPart->getJointsOfObj(obj); - for (auto* joint : joints) { - objToDel.push_back(joint); + auto* asmLink = dynamic_cast(objBeingDeleted); + if (asmLink && !asmLink->isRigid()) { + addSubComponents(asmLink, objsBeingDeleted); } - joints = assemblyPart->getJointsOfPart(obj); - for (auto* joint : joints) { - if (std::find(objToDel.begin(), objToDel.end(), joint) == objToDel.end()) { + + for (auto* obj : objsBeingDeleted) { + // List its joints + std::vector joints = assemblyPart->getJointsOfObj(obj); + for (auto* joint : joints) { objToDel.push_back(joint); } - } - - // List its grounded joints - std::vector inList = obj->getInList(); - for (auto* parent : inList) { - if (!parent) { - continue; + joints = assemblyPart->getJointsOfPart(obj); + for (auto* joint : joints) { + if (std::find(objToDel.begin(), objToDel.end(), joint) == objToDel.end()) { + objToDel.push_back(joint); + } } - if (dynamic_cast(parent->getPropertyByName("ObjectToGround"))) { - objToDel.push_back(parent); + // List its grounded joints + std::vector inList = obj->getInList(); + for (auto* parent : inList) { + if (!parent) { + continue; + } + + if (dynamic_cast(parent->getPropertyByName("ObjectToGround"))) { + objToDel.push_back(parent); + } } } From 9ec977f89dd9790ed26e4a99bfd4e84a3c896297 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Mon, 18 Nov 2024 16:08:11 +0100 Subject: [PATCH 089/161] Draft: Allow selection of subelements for Draft_Fillet Fixes #17505. --- src/Mod/Draft/draftgeoutils/fillets.py | 14 +++++- src/Mod/Draft/draftguitools/gui_fillets.py | 53 +++++++++++----------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/Mod/Draft/draftgeoutils/fillets.py b/src/Mod/Draft/draftgeoutils/fillets.py index 80a1221a3dc7..2ab56ebf31ee 100644 --- a/src/Mod/Draft/draftgeoutils/fillets.py +++ b/src/Mod/Draft/draftgeoutils/fillets.py @@ -79,7 +79,19 @@ def getCurveType(edge, existingCurveType=None): curveType = getCurveType(rndEdges[0]) curveType = getCurveType(rndEdges[1], curveType) - lVertexes = rndEdges[0].Vertexes + [rndEdges[1].Vertexes[-1]] + # Part.__sortEdges__() does not reverse edges. There is no guarantee that + # the endpoint of the 1st edge is the corner point. + edge1_sta, edge1_end = [rndEdges[0].Vertexes[i].Point for i in [0, -1]] + edge2_sta, edge2_end = [rndEdges[1].Vertexes[i].Point for i in [0, -1]] + tol = 1e-7 + if edge1_sta.isEqual(edge2_sta, tol): + lVertexes = [rndEdges[0].Vertexes[-1], rndEdges[0].Vertexes[0], rndEdges[1].Vertexes[-1]] + elif edge1_sta.isEqual(edge2_end, tol): + lVertexes = [rndEdges[0].Vertexes[-1], rndEdges[0].Vertexes[0], rndEdges[1].Vertexes[0]] + elif edge1_end.isEqual(edge2_sta, tol): + lVertexes = [rndEdges[0].Vertexes[0], rndEdges[0].Vertexes[-1], rndEdges[1].Vertexes[-1]] + else: + lVertexes = [rndEdges[0].Vertexes[0], rndEdges[0].Vertexes[-1], rndEdges[1].Vertexes[0]] if len(curveType['Line']) == 2: # Deals with 2-line-edges lists diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py index 145de9ca7268..38c57ffb0abb 100644 --- a/src/Mod/Draft/draftguitools/gui_fillets.py +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -39,11 +39,10 @@ import FreeCADGui as Gui import Draft import Draft_rc -import draftutils.utils as utils -import draftguitools.gui_base_original as gui_base_original -import draftguitools.gui_tool_utils as gui_tool_utils - +from draftguitools import gui_base_original +from draftguitools import gui_tool_utils from draftmake import make_fillet +from draftutils import utils from draftutils.messages import _err, _toolmsg from draftutils.translate import translate @@ -60,10 +59,10 @@ def __init__(self): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Fillet', - 'Accel':'F,I', - 'MenuText': QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Fillet", "Creates a fillet between two selected wires or edges.")} + return {"Pixmap": "Draft_Fillet", + "Accel":"F,I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Fillet", "Creates a fillet between two selected wires or edges.")} def Activated(self, name="Fillet"): """Execute when the command is called.""" @@ -140,33 +139,35 @@ def numericRadius(self, rad): def draw_arc(self, rad, chamfer, delete): """Process the selection and draw the actual object.""" - objs = Gui.Selection.getSelection() + sels = Gui.Selection.getSelectionEx("", 0) + objs = [] + objs_str = [] + doc = "FreeCAD.ActiveDocument." + for sel in sels: + for sub in sel.SubElementNames if sel.SubElementNames else [""]: + objs.append(sel.Object.getSubObject(sub)) + objs_str.append(doc + sel.Object.Name + ".getSubObject('" + sub + "')") + edges = make_fillet._preprocess(objs, rad, chamfer) if edges is None: _err(translate("draft", "Fillet cannot be created")) + self.finish() return - _doc = 'FreeCAD.ActiveDocument.' - - _objs = '[' - _objs += _doc + objs[0].Name + ', ' - _objs += _doc + objs[1].Name - _objs += ']' - Gui.addModule("Draft") - _cmd = 'Draft.make_fillet' - _cmd += '(' - _cmd += _objs + ', ' - _cmd += 'radius=' + str(rad) + _cmd = "Draft.make_fillet" + _cmd += "(" + _cmd += "[" + objs_str[0] + ", " + objs_str[1] + "], " + _cmd += "radius=" + str(rad) if chamfer: - _cmd += ', chamfer=' + str(chamfer) + _cmd += ", chamfer=True" if delete: - _cmd += ', delete=' + str(delete) - _cmd += ')' - _cmd_list = ['arc = ' + _cmd, - 'Draft.autogroup(arc)', - 'FreeCAD.ActiveDocument.recompute()'] + _cmd += ", delete=True" + _cmd += ")" + _cmd_list = ["fillet = " + _cmd, + "Draft.autogroup(fillet)", + "FreeCAD.ActiveDocument.recompute()"] self.commit(translate("draft", "Create fillet"), _cmd_list) self.finish() From eb3ce44b58a38c59a923d9327e442f564e4ada65 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 18 Nov 2024 19:01:00 +0100 Subject: [PATCH 090/161] Core: Do not detach object from document before the call of breakDependency This fixes #17900 --- src/App/Document.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index aef283502bfb..131a18ba855f 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -3989,15 +3989,15 @@ void Document::_removeObject(DocumentObject* pcObject) if (!d->rollback && d->activeUndoTransaction) { // Undo stuff signalTransactionRemove(*pcObject, d->activeUndoTransaction); + breakDependency(pcObject, true); d->activeUndoTransaction->addObjectNew(pcObject); } else { // for a rollback delete the object signalTransactionRemove(*pcObject, 0); + breakDependency(pcObject, true); } - breakDependency(pcObject, true); - // remove from map pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side d->objectIdMap.erase(pcObject->_Id); From fbd7f7090cc4fc0fb9e1dae795f628f43a3331cd Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Wed, 3 Jul 2024 15:24:48 +0200 Subject: [PATCH 091/161] Sketcher: ViewProviderSketch remove unecessary updateColor and applyCursor. --- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 58 ++++----------------- 1 file changed, 11 insertions(+), 47 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index f2cab849155e..d70834bb13d0 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -743,7 +743,9 @@ void ViewProviderSketch::preselectAtPoint(Base::Vector2d point) std::unique_ptr Point(this->getPointOnRay(screencoords, viewer)); - detectAndShowPreselection(Point.get(), screencoords); + if (detectAndShowPreselection(Point.get(), screencoords) && sketchHandler) { + sketchHandler->applyCursor(); + } } } @@ -1082,7 +1084,6 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe } setPreselectPoint(drag.DragPoint); drag.DragPoint = Drag::InvalidPoint; - // updateColor(); } resetPositionText(); Mode = STATUS_NONE; @@ -1155,7 +1156,6 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe } preselection.PreselectCurve = drag.DragCurve; drag.DragCurve = Drag::InvalidCurve; - // updateColor(); } resetPositionText(); Mode = STATUS_NONE; @@ -1500,7 +1500,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor case STATUS_NONE: if (preselectChanged) { editCoinManager->drawConstraintIcons(); - this->updateColor(); + updateColor(); return true; } return false; @@ -1709,7 +1709,8 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor sketchHandler->mouseMove(Base::Vector2d(x, y)); if (preselectChanged) { editCoinManager->drawConstraintIcons(); - this->updateColor(); + sketchHandler->applyCursor(); + updateColor(); } return true; case STATUS_SKETCH_StartRubberBand: { @@ -2087,7 +2088,7 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) selection.SelCurvSet.clear(); selection.SelConstraintSet.clear(); editCoinManager->drawConstraintIcons(); - this->updateColor(); + updateColor(); } } else if (msg.Type == Gui::SelectionChanges::AddSelection) { @@ -2099,38 +2100,32 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) if (shapetype.size() > 4 && shapetype.substr(0, 4) == "Edge") { int GeoId = std::atoi(&shapetype[4]) - 1; selection.SelCurvSet.insert(GeoId); - this->updateColor(); } else if (shapetype.size() > 12 && shapetype.substr(0, 12) == "ExternalEdge") { int GeoId = std::atoi(&shapetype[12]) - 1; GeoId = -GeoId - 3; selection.SelCurvSet.insert(GeoId); - this->updateColor(); } else if (shapetype.size() > 6 && shapetype.substr(0, 6) == "Vertex") { int VtId = std::atoi(&shapetype[6]) - 1; addSelectPoint(VtId); - this->updateColor(); } else if (shapetype == "RootPoint") { addSelectPoint(Selection::RootPoint); - this->updateColor(); } else if (shapetype == "H_Axis") { selection.SelCurvSet.insert(Selection::HorizontalAxis); - this->updateColor(); } else if (shapetype == "V_Axis") { selection.SelCurvSet.insert(Selection::VerticalAxis); - this->updateColor(); } else if (shapetype.size() > 10 && shapetype.substr(0, 10) == "Constraint") { int ConstrId = Sketcher::PropertyConstraintList::getIndexFromConstraintName(shapetype); selection.SelConstraintSet.insert(ConstrId); editCoinManager->drawConstraintIcons(); - this->updateColor(); } + updateColor(); } } } @@ -2146,31 +2141,25 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) if (shapetype.size() > 4 && shapetype.substr(0, 4) == "Edge") { int GeoId = std::atoi(&shapetype[4]) - 1; selection.SelCurvSet.erase(GeoId); - this->updateColor(); } else if (shapetype.size() > 12 && shapetype.substr(0, 12) == "ExternalEdge") { int GeoId = std::atoi(&shapetype[12]) - 1; GeoId = -GeoId - 3; selection.SelCurvSet.erase(GeoId); - this->updateColor(); } else if (shapetype.size() > 6 && shapetype.substr(0, 6) == "Vertex") { int VtId = std::atoi(&shapetype[6]) - 1; removeSelectPoint(VtId); - this->updateColor(); } else if (shapetype == "RootPoint") { removeSelectPoint(Sketcher::GeoEnum::RtPnt); - this->updateColor(); } else if (shapetype == "H_Axis") { selection.SelCurvSet.erase(Sketcher::GeoEnum::HAxis); - this->updateColor(); } else if (shapetype == "V_Axis") { selection.SelCurvSet.erase(Sketcher::GeoEnum::VAxis); - this->updateColor(); } else if (shapetype.size() > 10 && shapetype.substr(0, 10) == "Constraint") { int ConstrId = @@ -2178,8 +2167,8 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) shapetype); selection.SelConstraintSet.erase(ConstrId); editCoinManager->drawConstraintIcons(); - this->updateColor(); } + updateColor(); } } } @@ -2211,37 +2200,22 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) int GeoId = std::atoi(&shapetype[4]) - 1; resetPreselectPoint(); preselection.PreselectCurve = GeoId; - - if (sketchHandler) - sketchHandler->applyCursor(); - this->updateColor(); } else if (shapetype.size() > 12 && shapetype.substr(0, 12) == "ExternalEdge") { int GeoId = std::atoi(&shapetype[12]) - 1; GeoId = -GeoId - 3; resetPreselectPoint(); preselection.PreselectCurve = GeoId; - - if (sketchHandler) - sketchHandler->applyCursor(); - this->updateColor(); } else if (shapetype.size() > 6 && shapetype.substr(0, 6) == "Vertex") { int PtIndex = std::atoi(&shapetype[6]) - 1; setPreselectPoint(PtIndex); - - if (sketchHandler) - sketchHandler->applyCursor(); - this->updateColor(); } } } } else if (msg.Type == Gui::SelectionChanges::RmvPreselect) { resetPreselectPoint(); - if (sketchHandler) - sketchHandler->applyCursor(); - this->updateColor(); } } } @@ -2267,8 +2241,6 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S if (accepted) { setPreselectPoint(result.PointIndex); - if (sketchHandler) - sketchHandler->applyCursor(); return true; } } @@ -2290,8 +2262,6 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S resetPreselectPoint(); preselection.PreselectCurve = result.GeoIndex; - if (sketchHandler) - sketchHandler->applyCursor(); return true; } } @@ -2325,8 +2295,6 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S preselection.PreselectCross = static_cast(static_cast(result.Cross)); - if (sketchHandler) - sketchHandler->applyCursor(); return true; } } @@ -2352,8 +2320,6 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S resetPreselectPoint(); preselection.PreselectConstraintSet = result.ConstrIndices; - if (sketchHandler) - sketchHandler->applyCursor(); return true;// Preselection changed } } @@ -2367,8 +2333,7 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S // we have just left a preselection resetPreselectPoint(); preselection.blockedPreselection = false; - if (sketchHandler) - sketchHandler->applyCursor(); + return true; } Gui::Selection().setPreselectCoord( @@ -2379,8 +2344,7 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point, const S || preselection.blockedPreselection) { resetPreselectPoint(); preselection.blockedPreselection = false; - if (sketchHandler) - sketchHandler->applyCursor(); + return true; } From 5969df37f4bd278798c13e2910acb8b96965a4a2 Mon Sep 17 00:00:00 2001 From: Florian Foinant-Willig Date: Mon, 18 Nov 2024 23:09:20 +0100 Subject: [PATCH 092/161] Sketcher infinite axes --- src/Gui/View3DInventorViewer.cpp | 73 +++++++++++++++++++- src/Gui/View3DInventorViewer.h | 7 ++ src/Mod/Sketcher/Gui/EditModeCoinManager.cpp | 24 +++---- src/Mod/Sketcher/Gui/EditModeCoinManager.h | 8 ++- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 32 ++++++++- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 3 +- 6 files changed, 124 insertions(+), 23 deletions(-) diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 66b68c3abd66..3a4b9cea2fc0 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -2657,8 +2658,76 @@ SbVec2f View3DInventorViewer::getNormalizedPosition(const SbVec2s& pnt) const return {pX, pY}; } -SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, - const Base::Placement& plc) const +Base::BoundBox2d View3DInventorViewer::getViewportOnXYPlaneOfPlacement(Base::Placement plc) const +{ + auto projBBox = Base::BoundBox3d(); + projBBox.SetVoid(); + + SoCamera* pCam = this->getSoRenderManager()->getCamera(); + + if (!pCam) { + // Return empty box. + return Base::BoundBox2d(0, 0, 0, 0); + } + + Base::Vector3d pos = plc.getPosition(); + Base::Rotation rot = plc.getRotation(); + + // Transform the plane LCS into the global one. + Base::Vector3d zAxis(0, 0, 1); + rot.multVec(zAxis, zAxis); + + // Get the position and convert Base::Vector3d to SbVec3f + SbVec3f planeNormal(zAxis.x, zAxis.y, zAxis.z); + SbVec3f planePosition(pos.x, pos.y, pos.z); + SbPlane xyPlane(planeNormal, planePosition); + + const SbViewportRegion& vp = this->getSoRenderManager()->getViewportRegion(); + SbViewVolume vol = pCam->getViewVolume(); + + float fRatio = vp.getViewportAspectRatio(); + float dX, dY; + vp.getViewportSize().getValue(dX, dY); + + // Projects a pair of normalized coordinates on the XY plane. + auto projectPoint = + [&](float x, float y) { + if (fRatio > 1.f) { + x = (x - 0.5f * dX) * fRatio + 0.5f * dX; + } + else if (fRatio < 1.f) { + y = (y - 0.5f * dY) / fRatio + 0.5f * dY; + } + + SbLine line; + vol.projectPointToLine(SbVec2f(x, y), line); + + SbVec3f pt; + // Intersection point on the XY plane. + if (!xyPlane.intersect(line, pt)) { + return; + } + + projBBox.Add(Base::convertTo(pt)); + }; + + // Project the four corners of the viewport plane. + projectPoint(0.f, 0.f); + projectPoint(1.f, 0.f); + projectPoint(0.f, 1.f); + projectPoint(1.f, 1.f); + + if (!projBBox.IsValid()) { + // Return empty box. + return Base::BoundBox2d(0, 0, 0, 0); + } + + plc.invert(); + Base::ViewOrthoProjMatrix proj(plc.toMatrix()); + return projBBox.ProjectBox(&proj); +} + +SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, const Base::Placement& plc) const { SbVec2f pnt2d = getNormalizedPosition(pnt); SoCamera* pCam = this->getSoRenderManager()->getCamera(); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index dfa91ca3de06..1a520e616ca4 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -67,6 +67,10 @@ class SoClipPlane; namespace Quarter = SIM::Coin3D::Quarter; +namespace Base { + class BoundBox2d; +} + namespace Gui { class ViewProvider; @@ -311,6 +315,9 @@ class GuiExport View3DInventorViewer : public Quarter::SoQTQuarterAdaptor, publi /** Returns the 3d point on the XY plane of a placement to the given 2d point. */ SbVec3f getPointOnXYPlaneOfPlacement(const SbVec2s&, const Base::Placement&) const; + /** Returns the bounding box on the XY plane of a placement to the given 2d point. */ + Base::BoundBox2d getViewportOnXYPlaneOfPlacement(Base::Placement plc) const; + /** Returns the 2d coordinates on the viewport to the given 3d point. */ SbVec2s getPointOnViewport(const SbVec3f&) const; diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp index e29026c9dd9c..28660f5b64d8 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp @@ -808,8 +808,6 @@ void EditModeCoinManager::processGeometryConstraintsInformationOverlay( processGeometryInformationOverlay(geolistfacade); - updateAxesLength(); - pEditModeConstraintCoinManager->processConstraints(geolistfacade); } @@ -852,22 +850,18 @@ void EditModeCoinManager::processGeometryInformationOverlay(const GeoListFacade& overlayParameters.visibleInformationChanged = false; // just updated } -void EditModeCoinManager::updateAxesLength() +void EditModeCoinManager::updateAxesLength(const Base::BoundBox2d& bb) { auto zCrossH = ViewProviderSketchCoinAttorney::getViewOrientationFactor(viewProvider) * drawingParameters.zCross; - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 0, - SbVec3f(-analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 1, - SbVec3f(analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 2, - SbVec3f(0.0f, -analysisResults.boundingBoxMagnitudeOrder, zCrossH)); - editModeScenegraphNodes.RootCrossCoordinate->point.set1Value( - 3, - SbVec3f(0.0f, analysisResults.boundingBoxMagnitudeOrder, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(0, + SbVec3f(bb.MinX, 0.0f, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(1, + SbVec3f(bb.MaxX, 0.0f, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(2, + SbVec3f(0.0f, bb.MinY, zCrossH)); + editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(3, + SbVec3f(0.0f, bb.MaxY, zCrossH)); } void EditModeCoinManager::updateColor() diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.h b/src/Mod/Sketcher/Gui/EditModeCoinManager.h index 338d9834521d..2d06a995a6cd 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.h +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.h @@ -44,6 +44,8 @@ class Vector3; class Vector2d; +class BoundBox2d; + class Placement; } // namespace Base @@ -256,6 +258,9 @@ class SketcherGuiExport EditModeCoinManager void setConstraintSelectability(bool enabled = true); //@} + // Updates the Axes extension to span the specified area. + void updateAxesLength(const Base::BoundBox2d& bb); + private: // This function populates the coin nodes with the information of the current geometry void processGeometry(const GeoListFacade& geolistfacade); @@ -265,9 +270,6 @@ class SketcherGuiExport EditModeCoinManager // parallel. void processGeometryInformationOverlay(const GeoListFacade& geolistfacade); - // updates the Axes length to extend beyond the calculated bounding box magnitude - void updateAxesLength(); - // updates the parameters to be used for the Overlay information layer void updateOverlayParameters(); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index d70834bb13d0..55a91adafa71 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -3459,8 +3459,10 @@ void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int Mo viewer->setupEditingRoot(); - cameraSensor.setData(new VPRender {this, viewer->getSoRenderManager()}); - cameraSensor.attach(viewer->getSoRenderManager()->getSceneGraph()); + auto *camSensorData = new VPRender {this, viewer->getSoRenderManager()}; + cameraSensor.setData(camSensorData); + cameraSensor.setDeleteCallback(&ViewProviderSketch::camSensDeleteCB, camSensorData); + cameraSensor.attach(viewer->getCamera()); } void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) @@ -3468,6 +3470,7 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) auto dataPtr = static_cast(cameraSensor.getData()); delete dataPtr; cameraSensor.setData(nullptr); + cameraSensor.setDeleteCallback(nullptr, nullptr); cameraSensor.detach(); viewer->removeGraphicsItem(rubberband.get()); @@ -3475,6 +3478,22 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) viewer->setSelectionEnabled(true); } +void ViewProviderSketch::camSensDeleteCB(void* data, SoSensor *s) +{ + auto *proxyVPrdr = static_cast(data); + if (!proxyVPrdr) + return; + + // The camera object the observer was attached to is gone, try to re-attach the sensor + // to the new camera. + // This happens i.e. when the user switches the camera type from orthographic to + // perspective. + SoCamera *camera = proxyVPrdr->renderMgr->getCamera(); + if (camera) { + static_cast(s)->attach(camera); + } +} + void ViewProviderSketch::camSensCB(void* data, SoSensor*) { VPRender* proxyVPrdr = static_cast(data); @@ -3516,6 +3535,15 @@ void ViewProviderSketch::onCameraChanged(SoCamera* cam) Base::Interpreter().runStringObject(cmdStr.toLatin1()); } + // Stretch the axes to cover the whole viewport. + Gui::View3DInventor* view = qobject_cast(this->getActiveView()); + if (view) { + Base::Placement plc = getEditingPlacement(); + const Base::BoundBox2d vpBBox = view->getViewer() + ->getViewportOnXYPlaneOfPlacement(plc); + editCoinManager->updateAxesLength(vpBBox); + } + drawGrid(true); } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index ae5b27269048..0ceb339efde6 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -717,7 +717,8 @@ class SketcherGuiExport ViewProviderSketch: public PartGui::ViewProvider2DObject void unsetEdit(int ModNum) override; void setEditViewer(Gui::View3DInventorViewer*, int ModNum) override; void unsetEditViewer(Gui::View3DInventorViewer*) override; - static void camSensCB(void* data, SoSensor*); // camera sensor callback + static void camSensCB(void* data, SoSensor*); // camera sensor callback + static void camSensDeleteCB(void* data, SoSensor*); // camera sensor callback void onCameraChanged(SoCamera* cam); //@} From 710542d121c2cabce05561591cfb00ef3b6e745c Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Fri, 25 Oct 2024 19:50:07 +0200 Subject: [PATCH 093/161] Assembly: Refactor get/setDraggerPlacement It seems that Base has very handy helpers for converting between various types. This simplifies code of ViewProviderAssembly::get/setDraggerPlacement a lot. --- src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index 674fc5dcf517..5eeae897761e 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -71,6 +71,8 @@ #include "ViewProviderAssembly.h" #include "ViewProviderAssemblyPy.h" +#include + using namespace Assembly; using namespace AssemblyGui; @@ -1154,27 +1156,14 @@ bool ViewProviderAssembly::getDraggerVisibility() void ViewProviderAssembly::setDraggerPlacement(Base::Placement plc) { - double q0, q1, q2, q3; - plc.getRotation().getValue(q0, q1, q2, q3); - Base::Vector3d pos = plc.getPosition(); - asmDragger->rotation.setValue(q0, q1, q2, q3); - asmDragger->translation.setValue(pos.x, pos.y, pos.z); + asmDragger->rotation.setValue(Base::convertTo(plc.getRotation())); + asmDragger->translation.setValue(Base::convertTo(plc.getPosition())); } Base::Placement ViewProviderAssembly::getDraggerPlacement() { - Base::Placement plc; - SbVec3f pos = asmDragger->translation.getValue(); - plc.setPosition(Base::Vector3d(pos[0], pos[1], pos[2])); - - SbVec3f axis; - float angle; - asmDragger->rotation.getValue(axis, angle); - Base::Vector3d axisV = Base::Vector3d(axis[0], axis[1], axis[2]); - Base::Rotation rot(axisV, angle); - plc.setRotation(rot); - - return plc; + return {Base::convertTo(asmDragger->translation.getValue()), + Base::convertTo(asmDragger->rotation.getValue())}; } Gui::SoFCCSysDragger* ViewProviderAssembly::getDragger() From d365d66413fa2012e8ab10bf68173d8aa7f99e22 Mon Sep 17 00:00:00 2001 From: BMaxV <5713211+BMaxV@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:59:49 +0100 Subject: [PATCH 094/161] Change button text to confirm copy. (#17696) * Change button text to confirm copy. * translation and timer->reset * timer->single shot + text variable --------- Co-authored-by: Chris Hennes --- src/Gui/DlgAbout.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Gui/DlgAbout.cpp b/src/Gui/DlgAbout.cpp index 78044e868a37..8eb2384e3e18 100644 --- a/src/Gui/DlgAbout.cpp +++ b/src/Gui/DlgAbout.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #endif @@ -701,6 +702,13 @@ void AboutDialog::copyToClipboard() } str << "\n"; + + QClipboard* cb = QApplication::clipboard(); + cb->setText(data); + auto copytext = ui->copyButton->text(); + ui->copyButton->setText(tr("Copied!")); + QTimer::singleShot(2000, [this,copytext]() { ui->copyButton->setText(copytext); }); + } } From 7912dc2a62948d4866e2c90c0bb4938760d92da6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 26 Nov 2024 13:35:39 +0100 Subject: [PATCH 095/161] Gui: Fix issues in About dialog --- src/Gui/DlgAbout.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Gui/DlgAbout.cpp b/src/Gui/DlgAbout.cpp index 8eb2384e3e18..9738ca731272 100644 --- a/src/Gui/DlgAbout.cpp +++ b/src/Gui/DlgAbout.cpp @@ -702,18 +702,18 @@ void AboutDialog::copyToClipboard() } str << "\n"; - - QClipboard* cb = QApplication::clipboard(); - cb->setText(data); - auto copytext = ui->copyButton->text(); - ui->copyButton->setText(tr("Copied!")); - QTimer::singleShot(2000, [this,copytext]() { ui->copyButton->setText(copytext); }); - } } QClipboard* cb = QApplication::clipboard(); cb->setText(data); + + auto copytext = ui->copyButton->text(); + ui->copyButton->setText(tr("Copied!")); + const int timeout = 2000; + QTimer::singleShot(timeout, this, [this, copytext]() { + ui->copyButton->setText(copytext); + }); } // ---------------------------------------------------------------------------- From 3070832e54d82f908ca8e59adcca8116c9dc0122 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 26 Nov 2024 14:50:48 +0100 Subject: [PATCH 096/161] Start: Show thumbnail if filename contains a dot Fixes #18109 --- src/Mod/Start/App/DisplayedFilesModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Start/App/DisplayedFilesModel.cpp b/src/Mod/Start/App/DisplayedFilesModel.cpp index 90fb26eeacca..294691af3164 100644 --- a/src/Mod/Start/App/DisplayedFilesModel.cpp +++ b/src/Mod/Start/App/DisplayedFilesModel.cpp @@ -279,7 +279,7 @@ void DisplayedFilesModel::addFile(const QString& filePath) return; } _fileInfoCache.emplace_back(getFileInfo(filePath.toStdString())); - if (qfi.completeSuffix().toLower() == QLatin1String("fcstd")) { + if (qfi.suffix().toLower() == QLatin1String("fcstd")) { auto thumbnail = loadFCStdThumbnail(filePath.toStdString()); if (!thumbnail.isEmpty()) { _imageCache.insert(filePath, thumbnail); From 6b1131dd5ade251a4dd85c555632e29701a1e211 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Tue, 26 Nov 2024 16:47:35 +0100 Subject: [PATCH 097/161] Draft: fix focus behavior of radius input Fixes #16249. The input did receive the focus, but the existing value was not selected. The circle, arc, trim and offset tools had a related issue. The whole radius/distance value, including the unit string, was selected, instead of just the numerical portion. --- src/Mod/Draft/DraftGui.py | 14 +++++--------- src/Mod/Draft/draftguitools/gui_offset.py | 3 +-- src/Mod/Draft/draftguitools/gui_trimex.py | 3 +-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index c9b6c004a8db..369f5a9aa5ba 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -758,8 +758,7 @@ def pointUi(self, title=translate("draft","Point"), cancel=None, extra=None, self.z = 0 self.pointButton.show() if rel: self.isRelative.show() - todo.delay(self.setFocus,None) - self.xValue.selectAll() + todo.delay(self.setFocus, None) def labelUi(self,title=translate("draft","Label"),callback=None): w = QtWidgets.QWidget() @@ -787,8 +786,7 @@ def offsetUi(self): self.labelRadius.setText(translate("draft","Distance")) self.radiusValue.setToolTip(translate("draft", "Offset distance")) self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) - todo.delay(self.radiusValue.setFocus,None) - self.radiusValue.selectAll() + todo.delay(self.setFocus, "radius") def offUi(self): todo.delay(FreeCADGui.Control.closeDialog,None) @@ -805,8 +803,7 @@ def trimUi(self,title=translate("draft","Trimex")): self.labelRadius.setText(translate("draft","Distance")) self.radiusValue.setToolTip(translate("draft", "Offset distance")) self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) - todo.delay(self.radiusValue.setFocus,None) - self.radiusValue.selectAll() + todo.delay(self.setFocus, "radius") def radiusUi(self): self.hideXYZ() @@ -815,8 +812,7 @@ def radiusUi(self): self.labelRadius.show() self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) self.radiusValue.show() - todo.delay(self.radiusValue.setFocus,None) - self.radiusValue.selectAll() + todo.delay(self.setFocus, "radius") def textUi(self): self.hideXYZ() @@ -1466,7 +1462,7 @@ def setRadiusValue(self,val,unit=None): print("Error: setRadiusValue called for number without Dimension") t = display_external(val,None, None) self.radiusValue.setText(t) - self.radiusValue.setFocus() + self.setFocus("radius") def runAutoGroup(self): FreeCADGui.runCommand("Draft_AutoGroup") diff --git a/src/Mod/Draft/draftguitools/gui_offset.py b/src/Mod/Draft/draftguitools/gui_offset.py index cbb93cceb1a7..b4b4c60fe294 100644 --- a/src/Mod/Draft/draftguitools/gui_offset.py +++ b/src/Mod/Draft/draftguitools/gui_offset.py @@ -212,8 +212,7 @@ def action(self, arg): self.constrainSeg = None self.linetrack.off() self.ui.radiusValue.setText("off") - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() + self.ui.setFocus("radius") if self.extendedCopy: if not gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_trimex.py b/src/Mod/Draft/draftguitools/gui_trimex.py index 9c9dffea7bea..3518514868d9 100644 --- a/src/Mod/Draft/draftguitools/gui_trimex.py +++ b/src/Mod/Draft/draftguitools/gui_trimex.py @@ -238,8 +238,7 @@ def action(self, arg): # situation. Setting 0 with no unit will show "0 ??" and not # compute any value self.ui.setRadiusValue(0) - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() + self.ui.setFocus("radius") gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": From 5eb09c8e454ac00d2321a27eaf565dc6ab782e96 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 25 Nov 2024 18:52:30 +0100 Subject: [PATCH 098/161] Core: GetGlobalPlacement: empty subname should not return. --- src/App/GeoFeature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/GeoFeature.cpp b/src/App/GeoFeature.cpp index c434b599e5dd..98e627f7c008 100644 --- a/src/App/GeoFeature.cpp +++ b/src/App/GeoFeature.cpp @@ -304,7 +304,7 @@ Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj, App::DocumentObject* rootObj, const std::string& sub) { - if (!targetObj || !rootObj || sub.empty()) { + if (!targetObj || !rootObj) { return Base::Placement(); } std::vector names = Base::Tools::splitSubName(sub); From ae89309329fa2d42f2b7e0656bf1921d758d41c2 Mon Sep 17 00:00:00 2001 From: Jacob Oursland Date: Sun, 24 Nov 2024 00:35:02 -0800 Subject: [PATCH 099/161] Mesh: move counter declaration to loop-local. --- src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl b/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl index 441d7d7a2142..4b25131d1702 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl +++ b/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl @@ -652,11 +652,11 @@ TRational::TRational (double dValue) // multiply by 2^exponent TRational kMultiplier; TInteger kPower(2); - int i, iDelay = 0; + int iDelay = 0; if (uiExponent & 0x400) { kMultiplier = 2; - for (i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++) + for (int i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++) { if (uiExponent & 1) { @@ -673,7 +673,7 @@ TRational::TRational (double dValue) else { kMultiplier = 1; - for (i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++) + for (int i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++) { if (!(uiExponent & 1)) { From d7e8cc8a547bc83ecc6d01509f1df4b116af9f00 Mon Sep 17 00:00:00 2001 From: Jacob Oursland Date: Sun, 24 Nov 2024 17:50:36 -0800 Subject: [PATCH 100/161] Mesh: Add template type to WM4 TRational variables. --- src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl b/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl index 4b25131d1702..f642c3f2fccf 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl +++ b/src/Mod/Mesh/App/WildMagic4/Wm4TRational.inl @@ -174,7 +174,7 @@ bool TRational::operator> (const TRational& rkR) const template TRational TRational::operator+ (const TRational& rkR) const { - TRational kSum; + TRational kSum; kSum.m_kNumer = m_kNumer*rkR.m_kDenom + m_kDenom*rkR.m_kNumer; kSum.m_kDenom = m_kDenom*rkR.m_kDenom; kSum.EliminatePowersOfTwo(); @@ -184,7 +184,7 @@ TRational TRational::operator+ (const TRational& rkR) const template TRational TRational::operator- (const TRational& rkR) const { - TRational kDiff; + TRational kDiff; kDiff.m_kNumer = m_kNumer*rkR.m_kDenom - m_kDenom*rkR.m_kNumer; kDiff.m_kDenom = m_kDenom*rkR.m_kDenom; kDiff.EliminatePowersOfTwo(); @@ -194,7 +194,7 @@ TRational TRational::operator- (const TRational& rkR) const template TRational TRational::operator* (const TRational& rkR) const { - TRational kProd; + TRational kProd; kProd.m_kNumer = m_kNumer*rkR.m_kNumer; kProd.m_kDenom = m_kDenom*rkR.m_kDenom; kProd.EliminatePowersOfTwo(); @@ -204,7 +204,7 @@ TRational TRational::operator* (const TRational& rkR) const template TRational TRational::operator/ (const TRational& rkR) const { - TRational kQuot; + TRational kQuot; kQuot.m_kNumer = m_kNumer*rkR.m_kDenom; kQuot.m_kDenom = m_kDenom*rkR.m_kNumer; kQuot.EliminatePowersOfTwo(); @@ -214,7 +214,7 @@ TRational TRational::operator/ (const TRational& rkR) const template TRational TRational::operator- () const { - TRational kNeg; + TRational kNeg; kNeg.m_kNumer = -m_kNumer; kNeg.m_kDenom = m_kDenom; return kNeg; @@ -350,7 +350,7 @@ TRational::TRational (float fValue) unsigned int uiMantissa = (0x007FFFFF & uiBits); // create 1.mantissa - TRational kFraction(1,2); + TRational kFraction(1,2); TInteger kTwo(2); m_kNumer = kOne; unsigned int uiMask; @@ -363,7 +363,7 @@ TRational::TRational (float fValue) } // multiply by 2^exponent - TRational kMultiplier; + TRational kMultiplier; TInteger kPower(2); int i, iDelay = 0; if (uiExponent & 0x00000080) @@ -630,7 +630,7 @@ TRational::TRational (double dValue) unsigned int uiMantissaLo = auiBits[0]; // create 1.mantissa - TRational kFraction(1,2); + TRational kFraction(1,2); TInteger kTwo(2); m_kNumer = kOne; unsigned int uiMask; @@ -650,7 +650,7 @@ TRational::TRational (double dValue) } // multiply by 2^exponent - TRational kMultiplier; + TRational kMultiplier; TInteger kPower(2); int iDelay = 0; if (uiExponent & 0x400) From e8e82c4ff6c6b9839a91f0689602c94e76b5cdec Mon Sep 17 00:00:00 2001 From: Jacob Oursland Date: Thu, 7 Nov 2024 22:56:59 -0800 Subject: [PATCH 101/161] App: Reduce BOOST_VERSION workaround to fix boost symbol linker error on Win-Qt5. --- src/App/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index bd7bd182c13d..d84e2724f172 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -3060,7 +3060,7 @@ void Application::LoadParameters() } } -#if defined(_MSC_VER) && BOOST_VERSION < 108300 +#if defined(_MSC_VER) && BOOST_VERSION < 108200 // fix weird error while linking boost (all versions of VC) // VS2010: https://forum.freecad.org/viewtopic.php?f=4&t=1886&p=12553&hilit=boost%3A%3Afilesystem%3A%3Aget#p12553 namespace boost { namespace program_options { std::string arg="arg"; } } From 55d5123b9ada0f37f17a9902f5794ba2b70dc56e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 23 Nov 2024 18:43:50 +0100 Subject: [PATCH 102/161] Start: Implement Thumbnail Managing Standard as specified here: https://specifications.freedesktop.org/thumbnail-spec/0.8.0/ The changes are: * use MD5 as hashing algorithm * write thumbnails to ~/.cache/thumbnails/normal --- src/Mod/Start/App/DisplayedFilesModel.cpp | 29 ++++++++++++++--------- src/Mod/Start/App/PreCompiled.h | 2 ++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Mod/Start/App/DisplayedFilesModel.cpp b/src/Mod/Start/App/DisplayedFilesModel.cpp index 294691af3164..d7607b767273 100644 --- a/src/Mod/Start/App/DisplayedFilesModel.cpp +++ b/src/Mod/Start/App/DisplayedFilesModel.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #endif #include "DisplayedFilesModel.h" @@ -93,12 +95,16 @@ std::string getThumbnailsImage() QString getThumbnailsName() { +#if defined(Q_OS_LINUX) + return QString::fromLatin1("thumbnails/normal"); +#else return QString::fromLatin1("FreeCADStartThumbnails"); +#endif } QDir getThumnailsParentDir() { - return QDir::temp(); + return {QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation)}; } QString getThumbnailsDir() @@ -116,22 +122,23 @@ void createThumbnailsDir() } } -QString getSha1Hash(const std::string& path) +QString getMD5Hash(const std::string& path) { - QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(path.c_str(), static_cast(path.size())); - QByteArray ba1 = hash.result().toHex(); - hash.reset(); - hash.addData(ba1); - QByteArray ba2 = hash.result().toHex(); - return QString::fromLatin1(ba2); + // Use MD5 hash as specified here: + // https://specifications.freedesktop.org/thumbnail-spec/0.8.0/thumbsave.html + QUrl url(QString::fromStdString(path)); + url.setScheme(QString::fromLatin1("file")); + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(url.toEncoded()); + QByteArray ba = hash.result().toHex(); + return QString::fromLatin1(ba); } QString getUniquePNG(const std::string& path) { QDir dir = getThumbnailsDir(); - QString sha1 = getSha1Hash(path) + QLatin1String(".png"); - return dir.absoluteFilePath(sha1); + QString md5 = getMD5Hash(path) + QLatin1String(".png"); + return dir.absoluteFilePath(md5); } bool useCachedPNG(const std::string& image, const std::string& project) diff --git a/src/Mod/Start/App/PreCompiled.h b/src/Mod/Start/App/PreCompiled.h index 7359854941bb..166e8268e15c 100644 --- a/src/Mod/Start/App/PreCompiled.h +++ b/src/Mod/Start/App/PreCompiled.h @@ -52,6 +52,8 @@ #include #include #include +#include +#include #endif // _PreComp_ #endif // START_PRECOMPILED_H From 370c08213c2c7800c3ed97cfebef2eca98e43df9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 22 Nov 2024 14:30:58 +0100 Subject: [PATCH 103/161] Core: Fix unicode path names under Windows --- src/Gui/PreferencePackManager.cpp | 62 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index dfc54240c00c..6fab14694d14 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -60,9 +60,9 @@ PreferencePack::PreferencePack(const fs::path& path, const App::Metadata& metada auto cssPaths = QDir::searchPaths(QString::fromUtf8("css")); auto overlayPaths = QDir::searchPaths(QString::fromUtf8("overlay")); - qssPaths.append(QString::fromStdString(_path.string())); - cssPaths.append(QString::fromStdString(_path.string())); - overlayPaths.append(QString::fromStdString(_path.string() + "/overlay")); + qssPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path))); + cssPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path))); + overlayPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path) + "/overlay")); QDir::setSearchPaths(QString::fromUtf8("qss"), qssPaths); QDir::setSearchPaths(QString::fromUtf8("css"), cssPaths); @@ -80,7 +80,7 @@ bool PreferencePack::apply() const auto preMacroPath = _path / "pre.FCMacro"; if (fs::exists(preMacroPath)) { try { - Base::Interpreter().runFile(preMacroPath.string().c_str(), false); + Base::Interpreter().runFile(Base::FileInfo::pathToString(preMacroPath).c_str(), false); } catch (...) { Base::Console().Message("PreferencePack application aborted by the preferencePack's pre.FCMacro"); @@ -89,13 +89,13 @@ bool PreferencePack::apply() const } // Back up the old config file - auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; auto backupFile = savedPreferencePacksDirectory / "user.cfg.backup"; try { fs::remove(backupFile); } catch (...) {} - App::GetApplication().GetUserParameter().SaveDocument(backupFile.string().c_str()); + App::GetApplication().GetUserParameter().SaveDocument(Base::FileInfo::pathToString(backupFile).c_str()); // Apply the config settings applyConfigChanges(); @@ -104,11 +104,11 @@ bool PreferencePack::apply() const auto postMacroPath = _path / "post.FCMacro"; if (fs::exists(postMacroPath)) { try { - Base::Interpreter().runFile(postMacroPath.string().c_str(), false); + Base::Interpreter().runFile(Base::FileInfo::pathToString(postMacroPath).c_str(), false); } catch (...) { Base::Console().Message("PreferencePack application reverted by the preferencePack's post.FCMacro"); - App::GetApplication().GetUserParameter().LoadDocument(backupFile.string().c_str()); + App::GetApplication().GetUserParameter().LoadDocument(Base::FileInfo::pathToString(backupFile).c_str()); return false; } } @@ -127,7 +127,7 @@ void PreferencePack::applyConfigChanges() const auto configFile = _path / (_metadata.name() + ".cfg"); if (fs::exists(configFile)) { auto newParameters = ParameterManager::Create(); - newParameters->LoadDocument(configFile.string().c_str()); + newParameters->LoadDocument(Base::FileInfo::pathToString(configFile).c_str()); auto baseAppGroup = App::GetApplication().GetUserParameter().GetGroup("BaseApp"); newParameters->GetGroup("BaseApp")->insertTo(baseAppGroup); } @@ -135,9 +135,9 @@ void PreferencePack::applyConfigChanges() const PreferencePackManager::PreferencePackManager() { - auto modPath = fs::path(App::Application::getUserAppDataDir()) / "Mod"; - auto savedPath = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; - auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; + auto modPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; + auto savedPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; _preferencePackPaths.push_back(resourcePath); _preferencePackPaths.push_back(modPath); _preferencePackPaths.push_back(savedPath); @@ -167,7 +167,7 @@ void Gui::PreferencePackManager::AddPackToMetadata(const std::string &packName) { std::lock_guard lock(_mutex); auto savedPreferencePacksDirectory = - fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; fs::path preferencePackDirectory(savedPreferencePacksDirectory / packName); if (fs::exists(preferencePackDirectory) && !fs::is_directory(preferencePackDirectory)) throw std::runtime_error("Cannot create " + savedPreferencePacksDirectory.string() @@ -222,7 +222,7 @@ void Gui::PreferencePackManager::importConfig(const std::string& packName, AddPackToMetadata(packName); auto savedPreferencePacksDirectory = - fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; auto cfgFilename = savedPreferencePacksDirectory / packName / (packName + ".cfg"); #if BOOST_VERSION >= 107400 fs::copy_file(path, cfgFilename, fs::copy_options::overwrite_existing); @@ -243,20 +243,20 @@ void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path &mo catch (...) { // Failed to read the metadata, or to create the preferencePack based on it... auto packageMetadataFile = mod / "package.xml"; - Base::Console().Error("Failed to read %s\n", packageMetadataFile.string().c_str()); + Base::Console().Error("Failed to read %s\n", Base::FileInfo::pathToString(packageMetadataFile).c_str()); } } void PreferencePackManager::TryFindPreferencePacksInPackage(const boost::filesystem::path& mod) { auto packageMetadataFile = mod / "package.xml"; - static const auto modDirectory = fs::path(App::Application::getUserAppDataDir()) / "Mod" / "SavedPreferencePacks"; - static const auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; + static const auto modDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod" / "SavedPreferencePacks"; + static const auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { App::Metadata metadata(packageMetadataFile); auto content = metadata.content(); - auto basename = mod.filename().string(); + auto basename = Base::FileInfo::pathToString(mod.filename()); if (mod == modDirectory) basename = "##USER_SAVED##"; else if (mod == resourcePath) @@ -365,7 +365,7 @@ void Gui::PreferencePackManager::deleteUserPack(const std::string& name) { if (name.empty()) return; - auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; auto savedPath = savedPreferencePacksDirectory / name; std::unique_ptr metadata; if (fs::exists(savedPreferencePacksDirectory / "package.xml")) { @@ -454,13 +454,13 @@ void PreferencePackManager::save(const std::string& name, const std::vectorCreateDocument(); for (const auto& t : templates) { auto templateParameterManager = ParameterManager::Create(); - templateParameterManager->LoadDocument(t.path.string().c_str()); + templateParameterManager->LoadDocument(Base::FileInfo::pathToString(t.path).c_str()); copyTemplateParameters(*templateParameterManager, *outputParameterManager); } auto savedPreferencePacksDirectory = - fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; auto cfgFilename = savedPreferencePacksDirectory / name / (name + ".cfg"); - outputParameterManager->SaveDocument(cfgFilename.string().c_str()); + outputParameterManager->SaveDocument(Base::FileInfo::pathToString(cfgFilename).c_str()); } // Needed until we support only C++20 and above and can use std::string's built-in ends_with() @@ -480,7 +480,7 @@ std::vector scanForTemplateFolders(const std::string& groupName, const templateFolders.push_back(entry); } else { - std::string subgroupName = groupName + "/" + entry.filename().string(); + std::string subgroupName = groupName + "/" + Base::FileInfo::pathToString(entry.filename()); for (const auto& subentry : fs::directory_iterator(entry)) { auto contents = scanForTemplateFolders(subgroupName, subentry); std::copy(contents.begin(), contents.end(), std::back_inserter(templateFolders)); @@ -501,7 +501,7 @@ std::vector scanForTemplateFiles(const std: continue; for (const auto& entry : fs::directory_iterator(templateDir)) { if (entry.path().extension() == ".cfg") { - auto name = entry.path().filename().stem().string(); + auto name = Base::FileInfo::pathToString(entry.path().filename().stem()); std::replace(name.begin(), name.end(), '_', ' '); // Make sure we don't insert the same thing twice... if (std::find_if(templateFiles.begin(), templateFiles.end(), [groupName, name](const auto &rhs)->bool { @@ -527,8 +527,8 @@ std::vector PreferencePackManager::template // * $DATA_DIR/Mod/**/PreferencePackTemplates/(Appearance|Behavior)/* // (alternate spellings are provided for packages using CamelCase and snake_case, and both major English dialects) - auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui"; - auto modPath = fs::path(App::Application::getUserAppDataDir()) / "Mod"; + auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui"; + auto modPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; std::string group = "Built-In"; if (fs::exists(resourcePath) && fs::is_directory(resourcePath)) { @@ -538,7 +538,7 @@ std::vector PreferencePackManager::template if (fs::exists(modPath) && fs::is_directory(modPath)) { for (const auto& mod : fs::directory_iterator(modPath)) { - group = mod.path().filename().string(); + group = Base::FileInfo::pathToString(mod.path().filename()); const auto localFiles = scanForTemplateFiles(group, mod); std::copy(localFiles.begin(), localFiles.end(), std::back_inserter(_templateFiles)); } @@ -549,7 +549,7 @@ std::vector PreferencePackManager::template void Gui::PreferencePackManager::BackupCurrentConfig() const { - auto backupDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; fs::create_directories(backupDirectory); // Create a timestamped filename: @@ -559,14 +559,14 @@ void Gui::PreferencePackManager::BackupCurrentConfig() const auto filename = backupDirectory / timestampStream.str(); // Save the current config: - App::GetApplication().GetUserParameter().SaveDocument(filename.string().c_str()); + App::GetApplication().GetUserParameter().SaveDocument(Base::FileInfo::pathToString(filename).c_str()); } void Gui::PreferencePackManager::DeleteOldBackups() const { constexpr auto oneWeek = 60.0 * 60.0 * 24.0 * 7.0; const auto now = std::time(nullptr); - auto backupDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { if (std::difftime(now, fs::last_write_time(backup)) > oneWeek) { @@ -582,7 +582,7 @@ void Gui::PreferencePackManager::DeleteOldBackups() const std::vector Gui::PreferencePackManager::configBackups() const { std::vector results; - auto backupDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { results.push_back(backup); From 33a83f0ee461823e07a12bea84f218587fb833e7 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Tue, 26 Nov 2024 12:16:22 -0600 Subject: [PATCH 104/161] Update versions in SECURITY.md --- SECURITY.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 6131ab73fe7a..9ef7934974cd 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -17,13 +17,13 @@ hostage in demands for "bounties" will not be entertained. Contact the FPA at fp ## Supported Versions -FreeCAD implements security fixes to the current release series, and to the current development on the master branch. +FreeCAD implements security fixes to the current release series, and to the current development on the main branch. | Version | Supported | |---------| ------------------ | -| 0.22dev | :white_check_mark: | -| 0.21 | :white_check_mark: | -| < 0.21 | :x: | +| 1.1dev | :white_check_mark: | +| 1.0 | :white_check_mark: | +| < 1.0 | :x: | ## Reporting a Vulnerability From fb7ce6405b21566615912b4150f971a596c8464b Mon Sep 17 00:00:00 2001 From: Jacob Oursland Date: Sun, 24 Nov 2024 17:48:47 -0800 Subject: [PATCH 105/161] CMake: Add missing target_link_directories() for OCCT. --- src/Mod/Assembly/Gui/CMakeLists.txt | 1 + tests/src/Mod/Assembly/CMakeLists.txt | 1 + tests/src/Mod/Material/CMakeLists.txt | 1 + tests/src/Mod/Measure/CMakeLists.txt | 1 + tests/src/Mod/Mesh/CMakeLists.txt | 1 + tests/src/Mod/MeshPart/CMakeLists.txt | 1 + tests/src/Mod/Part/CMakeLists.txt | 1 + tests/src/Mod/PartDesign/CMakeLists.txt | 1 + tests/src/Mod/Points/CMakeLists.txt | 1 + tests/src/Mod/Sketcher/CMakeLists.txt | 1 + 10 files changed, 10 insertions(+) diff --git a/src/Mod/Assembly/Gui/CMakeLists.txt b/src/Mod/Assembly/Gui/CMakeLists.txt index 7dda6251f0b8..6924b340d829 100644 --- a/src/Mod/Assembly/Gui/CMakeLists.txt +++ b/src/Mod/Assembly/Gui/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories( ${OCC_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS} ) +link_directories(${OCC_LIBRARY_DIR}) set(AssemblyGui_LIBS Assembly diff --git a/tests/src/Mod/Assembly/CMakeLists.txt b/tests/src/Mod/Assembly/CMakeLists.txt index 0b6aaf602ac8..1b1d32dc85ac 100644 --- a/tests/src/Mod/Assembly/CMakeLists.txt +++ b/tests/src/Mod/Assembly/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Assembly_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Assembly_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Assembly_tests_run gtest_main diff --git a/tests/src/Mod/Material/CMakeLists.txt b/tests/src/Mod/Material/CMakeLists.txt index aab21917da2a..93c4c5da4aab 100644 --- a/tests/src/Mod/Material/CMakeLists.txt +++ b/tests/src/Mod/Material/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Material_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Material_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Material_tests_run gtest_main diff --git a/tests/src/Mod/Measure/CMakeLists.txt b/tests/src/Mod/Measure/CMakeLists.txt index 161ea0c10377..08ab1ff67342 100644 --- a/tests/src/Mod/Measure/CMakeLists.txt +++ b/tests/src/Mod/Measure/CMakeLists.txt @@ -7,6 +7,7 @@ target_include_directories(Measure_tests_run PUBLIC ${VTK_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Measure_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Measure_tests_run gtest_main diff --git a/tests/src/Mod/Mesh/CMakeLists.txt b/tests/src/Mod/Mesh/CMakeLists.txt index 6796225c4593..791993903d80 100644 --- a/tests/src/Mod/Mesh/CMakeLists.txt +++ b/tests/src/Mod/Mesh/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Mesh_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Mesh_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Mesh_tests_run gtest_main diff --git a/tests/src/Mod/MeshPart/CMakeLists.txt b/tests/src/Mod/MeshPart/CMakeLists.txt index 24a4b1272d7b..c93056b4ee40 100644 --- a/tests/src/Mod/MeshPart/CMakeLists.txt +++ b/tests/src/Mod/MeshPart/CMakeLists.txt @@ -7,6 +7,7 @@ target_include_directories(MeshPart_tests_run PUBLIC ${VTK_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(MeshPart_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(MeshPart_tests_run gtest_main diff --git a/tests/src/Mod/Part/CMakeLists.txt b/tests/src/Mod/Part/CMakeLists.txt index 923821fcdccb..57898b0e8d9f 100644 --- a/tests/src/Mod/Part/CMakeLists.txt +++ b/tests/src/Mod/Part/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Part_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Part_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Part_tests_run gtest_main diff --git a/tests/src/Mod/PartDesign/CMakeLists.txt b/tests/src/Mod/PartDesign/CMakeLists.txt index 2077c3f42ef7..a3a03880b4ab 100644 --- a/tests/src/Mod/PartDesign/CMakeLists.txt +++ b/tests/src/Mod/PartDesign/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(PartDesign_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(PartDesign_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(PartDesign_tests_run gtest_main diff --git a/tests/src/Mod/Points/CMakeLists.txt b/tests/src/Mod/Points/CMakeLists.txt index 75b19973945d..ee627574bdb6 100644 --- a/tests/src/Mod/Points/CMakeLists.txt +++ b/tests/src/Mod/Points/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Points_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Points_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Points_tests_run gtest_main diff --git a/tests/src/Mod/Sketcher/CMakeLists.txt b/tests/src/Mod/Sketcher/CMakeLists.txt index 2931eb9c99a7..bfa6bcbe961a 100644 --- a/tests/src/Mod/Sketcher/CMakeLists.txt +++ b/tests/src/Mod/Sketcher/CMakeLists.txt @@ -5,6 +5,7 @@ target_include_directories(Sketcher_tests_run PUBLIC ${Python3_INCLUDE_DIRS} ${XercesC_INCLUDE_DIRS} ) +target_link_directories(Sketcher_tests_run PUBLIC ${OCC_LIBRARY_DIR}) target_link_libraries(Sketcher_tests_run gtest_main From 8e04c0a3dd9435df0c2dec813b17d02f7b723b19 Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Mon, 4 Nov 2024 14:22:22 +0300 Subject: [PATCH 106/161] Gui: take in account module-path argument Use paths passed with `--module-path` argument to search for preference packs Change-Id: If168dbd99a826757290ee6b918f5b712305fe2bb --- src/Gui/DlgPreferencePackManagementImp.cpp | 16 +++++---- src/Gui/PreferencePackManager.cpp | 39 +++++++++++++++++----- src/Gui/PreferencePackManager.h | 5 +++ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/Gui/DlgPreferencePackManagementImp.cpp b/src/Gui/DlgPreferencePackManagementImp.cpp index a1a0dad41a52..50f3982f21e4 100644 --- a/src/Gui/DlgPreferencePackManagementImp.cpp +++ b/src/Gui/DlgPreferencePackManagementImp.cpp @@ -54,7 +54,7 @@ void DlgPreferencePackManagementImp::showEvent(QShowEvent* event) // but can only disable individual installed packs (though we can completely uninstall the pack's // containing Addon by redirecting to the Addon Manager). auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; - auto modDirectory = fs::path(App::Application::getUserAppDataDir()) / "Mod"; + auto modDirectories = Application::Instance->prefPackManager()->modPaths(); auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; // The displayed tree has two levels: at the toplevel is either "User-Saved Packs" or the name @@ -66,12 +66,14 @@ void DlgPreferencePackManagementImp::showEvent(QShowEvent* event) auto builtinPacks = getPacksFromDirectory(resourcePath); std::map> installedPacks; - if (fs::exists(modDirectory) && fs::is_directory(modDirectory)) { - for (const auto& mod : fs::directory_iterator(modDirectory)) { - auto packs = getPacksFromDirectory(mod); - if (!packs.empty()) { - auto modName = mod.path().filename().string(); - installedPacks.emplace(modName, packs); + for (const auto& modDirectory : modDirectories) { + if (fs::exists(modDirectory) && fs::is_directory(modDirectory)) { + for (const auto& mod : fs::directory_iterator(modDirectory)) { + auto packs = getPacksFromDirectory(mod); + if (!packs.empty()) { + auto modName = mod.path().filename().string(); + installedPacks.emplace(modName, packs); + } } } } diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index 6fab14694d14..2328bcb04d81 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -30,6 +30,7 @@ #endif #include +#include #include #include "PreferencePackManager.h" @@ -134,12 +135,11 @@ void PreferencePack::applyConfigChanges() const } PreferencePackManager::PreferencePackManager() + : _preferencePackPaths(modPaths()) { - auto modPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; auto savedPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; - _preferencePackPaths.push_back(resourcePath); - _preferencePackPaths.push_back(modPath); + _preferencePackPaths.insert(_preferencePackPaths.begin(), resourcePath); _preferencePackPaths.push_back(savedPath); rescan(); @@ -232,6 +232,26 @@ void Gui::PreferencePackManager::importConfig(const std::string& packName, rescan(); } +// TODO(Shvedov): Is this suitable place for this method? It is more generic, +// and maybe more suitable place at Application? +std::vector Gui::PreferencePackManager::modPaths() const +{ + auto userModPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; + + auto& config = App::Application::Config(); + auto additionalModules = config.find("AdditionalModulePaths"); + std::vector result; + + if (additionalModules != config.end()) { + boost::split(result, + additionalModules->second, + boost::is_any_of(";"), + boost::token_compress_on); + } + result.emplace_back(userModPath); + return result; +} + void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path &mod) { try { @@ -528,7 +548,6 @@ std::vector PreferencePackManager::template // (alternate spellings are provided for packages using CamelCase and snake_case, and both major English dialects) auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui"; - auto modPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; std::string group = "Built-In"; if (fs::exists(resourcePath) && fs::is_directory(resourcePath)) { @@ -536,11 +555,13 @@ std::vector PreferencePackManager::template std::copy(localFiles.begin(), localFiles.end(), std::back_inserter(_templateFiles)); } - if (fs::exists(modPath) && fs::is_directory(modPath)) { - for (const auto& mod : fs::directory_iterator(modPath)) { - group = Base::FileInfo::pathToString(mod.path().filename()); - const auto localFiles = scanForTemplateFiles(group, mod); - std::copy(localFiles.begin(), localFiles.end(), std::back_inserter(_templateFiles)); + for (const auto& modPath : modPaths()) { + if (fs::exists(modPath) && fs::is_directory(modPath)) { + for (const auto& mod : fs::directory_iterator(modPath)) { + group = Base::FileInfo::pathToString(mod.path().filename()); + const auto localFiles = scanForTemplateFiles(group, mod); + std::copy(localFiles.begin(), localFiles.end(), std::back_inserter(_templateFiles)); + } } } diff --git a/src/Gui/PreferencePackManager.h b/src/Gui/PreferencePackManager.h index 301e160df2fc..e5776e47a02d 100644 --- a/src/Gui/PreferencePackManager.h +++ b/src/Gui/PreferencePackManager.h @@ -191,6 +191,11 @@ namespace Gui { */ void importConfig(const std::string &packName, const boost::filesystem::path &path); + /** + * Get a list of all mod directories. + */ + std::vector modPaths() const; + private: void FindPreferencePacksInPackage(const boost::filesystem::path& mod); From 7c2acdbf093e44bfd22eb981fe7dd8af73113119 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 14 Aug 2024 17:25:39 +0200 Subject: [PATCH 107/161] Gui: propertyeditor: Reformat, fix line endings Instead of fixing whitespaces do a full reformat according to current rules. No other changes. --- src/Gui/propertyeditor/PropertyEditor.h | 343 +- src/Gui/propertyeditor/PropertyItem.cpp | 9608 +++++++++++----------- src/Gui/propertyeditor/PropertyItem.h | 2576 +++--- src/Gui/propertyeditor/PropertyModel.cpp | 1159 +-- 4 files changed, 6907 insertions(+), 6779 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index 73e6e7256338..40fb89482e36 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -1,166 +1,177 @@ -/*************************************************************************** - * Copyright (c) 2004 Werner Mayer * - * * - * 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 PROPERTYEDITOR_H -#define PROPERTYEDITOR_H - -#include - -#include - -#include "PropertyItem.h" -#include "PropertyModel.h" - - -namespace App { -class Property; -class Document; -} - -namespace Gui { - -class PropertyView; - -namespace PropertyEditor { - -class PropertyItemDelegate; -class PropertyModel; -/*! - Put this into the .qss file after Gui--PropertyEditor--PropertyEditor - - Gui--PropertyEditor--PropertyEditor - { - qproperty-groupBackground: gray; - qproperty-groupTextColor: white; - } - - See also: https://man42.net/blog/2011/09/qt-4-7-modify-a-custom-q_property-with-a-qt-style-sheet/ - -*/ - -class PropertyEditor : public QTreeView -{ - Q_OBJECT - - Q_PROPERTY(QBrush groupBackground READ groupBackground WRITE setGroupBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor groupTextColor READ groupTextColor WRITE setGroupTextColor DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QBrush itemBackground READ itemBackground WRITE setItemBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify - -public: - PropertyEditor(QWidget *parent = nullptr); - ~PropertyEditor() override; - - /** Builds up the list view with the properties. */ - void buildUp(PropertyModel::PropertyList &&props = PropertyModel::PropertyList(), bool checkDocument=false); - void updateProperty(const App::Property&); - void removeProperty(const App::Property&); - void setAutomaticExpand(bool); - bool isAutomaticExpand(bool) const; - void setAutomaticDocumentUpdate(bool); - bool isAutomaticDocumentUpdate(bool) const; - /*! Reset the internal state of the view. */ - void reset() override; - - QBrush groupBackground() const; - void setGroupBackground(const QBrush& c); - QColor groupTextColor() const; - void setGroupTextColor(const QColor& c); - QBrush itemBackground() const; - void setItemBackground(const QBrush& c); - - bool isBinding() const { return binding; } - void openEditor(const QModelIndex &index); - void closeEditor(); - -protected Q_SLOTS: - void onItemActivated(const QModelIndex &index); - void onItemExpanded(const QModelIndex &index); - void onItemCollapsed(const QModelIndex &index); - void onRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &dst, int row); - void onRowsRemoved(const QModelIndex &parent, int start, int end); - -protected: - bool eventFilter(QObject* object, QEvent* event) override; - void closeEditor (QWidget * editor, QAbstractItemDelegate::EndEditHint hint) override; - void commitData (QWidget * editor) override; - void editorDestroyed (QObject * editor) override; - void currentChanged (const QModelIndex & current, const QModelIndex & previous) override; - void rowsInserted (const QModelIndex & parent, int start, int end) override; - void rowsAboutToBeRemoved (const QModelIndex & parent, int start, int end) override; - void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override; - void drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const override; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - QStyleOptionViewItem viewOptions() const override; -#else - void initViewItemOption(QStyleOptionViewItem *option) const override; -#endif - void contextMenuEvent(QContextMenuEvent *event) override; - bool event(QEvent*) override; - -private: - void setEditorMode(const QModelIndex & parent, int start, int end); - void closeTransaction(); - void recomputeDocument(App::Document*); - - // check if mouse_pos is around right or bottom side of a cell - // and return the index of that cell if found - QModelIndex indexResizable(QPoint mouse_pos); - -private: - PropertyItemDelegate *delegate; - PropertyModel* propertyModel; - QStringList selectedProperty; - PropertyModel::PropertyList propList; - std::unordered_set propOwners; - bool autoexpand; - bool autoupdate; - bool committing; - bool delaybuild; - bool binding; - bool checkDocument; - bool closingEditor; - bool dragInProgress; - - //max distance between mouse and a cell, small enough to trigger resize - int dragSensibility = 5; // NOLINT - int dragSection = 0; - int dragPreviousPos = 0; - - int transactionID = 0; - - QColor groupColor; - QBrush background; - QBrush _itemBackground; - - QPointer activeEditor; - QPersistentModelIndex editingIndex; - int removingRows = 0; - - friend class Gui::PropertyView; - friend class PropertyItemDelegate; -}; - -} //namespace PropertyEditor -} //namespace Gui - -#endif // PROPERTYEDITOR_H +/*************************************************************************** + * Copyright (c) 2004 Werner Mayer * + * * + * 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 PROPERTYEDITOR_H +#define PROPERTYEDITOR_H + +#include + +#include + +#include "PropertyItem.h" +#include "PropertyModel.h" + + +namespace App +{ +class Property; +class Document; +} // namespace App + +namespace Gui +{ + +class PropertyView; + +namespace PropertyEditor +{ + +class PropertyItemDelegate; +class PropertyModel; +/*! + Put this into the .qss file after Gui--PropertyEditor--PropertyEditor + + Gui--PropertyEditor--PropertyEditor + { + qproperty-groupBackground: gray; + qproperty-groupTextColor: white; + } + + See also: https://man42.net/blog/2011/09/qt-4-7-modify-a-custom-q_property-with-a-qt-style-sheet/ +*/ + +class PropertyEditor: public QTreeView +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(QBrush groupBackground READ groupBackground WRITE setGroupBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor groupTextColor READ groupTextColor WRITE setGroupTextColor DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QBrush itemBackground READ itemBackground WRITE setItemBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify + // clang-format on + +public: + PropertyEditor(QWidget* parent = nullptr); + ~PropertyEditor() override; + + /** Builds up the list view with the properties. */ + void buildUp(PropertyModel::PropertyList&& props = PropertyModel::PropertyList(), + bool checkDocument = false); + void updateProperty(const App::Property&); + void removeProperty(const App::Property&); + void setAutomaticExpand(bool); + bool isAutomaticExpand(bool) const; + void setAutomaticDocumentUpdate(bool); + bool isAutomaticDocumentUpdate(bool) const; + /*! Reset the internal state of the view. */ + void reset() override; + + QBrush groupBackground() const; + void setGroupBackground(const QBrush& c); + QColor groupTextColor() const; + void setGroupTextColor(const QColor& c); + QBrush itemBackground() const; + void setItemBackground(const QBrush& c); + + bool isBinding() const + { + return binding; + } + void openEditor(const QModelIndex& index); + void closeEditor(); + +protected Q_SLOTS: + void onItemActivated(const QModelIndex& index); + void onItemExpanded(const QModelIndex& index); + void onItemCollapsed(const QModelIndex& index); + void + onRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& dst, int row); + void onRowsRemoved(const QModelIndex& parent, int start, int end); + +protected: + bool eventFilter(QObject* object, QEvent* event) override; + void closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint) override; + void commitData(QWidget* editor) override; + void editorDestroyed(QObject* editor) override; + void currentChanged(const QModelIndex& current, const QModelIndex& previous) override; + void rowsInserted(const QModelIndex& parent, int start, int end) override; + void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override; + void + drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; + void drawRow(QPainter* painter, + const QStyleOptionViewItem& options, + const QModelIndex& index) const override; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QStyleOptionViewItem viewOptions() const override; +#else + void initViewItemOption(QStyleOptionViewItem* option) const override; +#endif + void contextMenuEvent(QContextMenuEvent* event) override; + bool event(QEvent*) override; + +private: + void setEditorMode(const QModelIndex& parent, int start, int end); + void closeTransaction(); + void recomputeDocument(App::Document*); + + // check if mouse_pos is around right or bottom side of a cell + // and return the index of that cell if found + QModelIndex indexResizable(QPoint mouse_pos); + +private: + PropertyItemDelegate* delegate; + PropertyModel* propertyModel; + QStringList selectedProperty; + PropertyModel::PropertyList propList; + std::unordered_set propOwners; + bool autoexpand; + bool autoupdate; + bool committing; + bool delaybuild; + bool binding; + bool checkDocument; + bool closingEditor; + bool dragInProgress; + + // max distance between mouse and a cell, small enough to trigger resize + int dragSensibility = 5; // NOLINT + int dragSection = 0; + int dragPreviousPos = 0; + + int transactionID = 0; + + QColor groupColor; + QBrush background; + QBrush _itemBackground; + + QPointer activeEditor; + QPersistentModelIndex editingIndex; + int removingRows = 0; + + friend class Gui::PropertyView; + friend class PropertyItemDelegate; +}; + +} // namespace PropertyEditor +} // namespace Gui + +#endif // PROPERTYEDITOR_H diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index a0da598b0f48..83ec217cca1c 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -1,4782 +1,4826 @@ -/*************************************************************************** - * Copyright (c) 2004 Werner Mayer * - * * - * 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 -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif - -#include "PropertyItem.h" -#include "PropertyView.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// NOLINTBEGIN(cppcoreguidelines-pro-*,cppcoreguidelines-prefer-member-initializer) -using namespace Gui::PropertyEditor; -using namespace Gui::Dialog; - -namespace { -constexpr const int lowPrec = 2; -constexpr const int highPrec = 16; - -int toPercent(float value) -{ - return static_cast(100 * value); // NOLINT -} - -float fromPercent(int value) -{ - return static_cast(value) / 100.0F; // NOLINT -} - -} - -PropertyItemFactory& PropertyItemFactory::instance() -{ - static PropertyItemFactory inst; - return inst; -} - -PropertyItem* PropertyItemFactory::createPropertyItem (const char* sName) const -{ - return static_cast(Produce(sName)); -} - -// ---------------------------------------------------- - -QVariant PropertyItemAttorney::toString(PropertyItem* item, const QVariant& value) -{ - return item->toString(value); -} - -// ---------------------------------------------------- - -Q_DECLARE_METATYPE(Py::Object) // NOLINT - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyItem) - -PropertyItem::PropertyItem() - : parentItem(nullptr) - , readonly(false) - , precision(Base::UnitsApi::getDecimals()) - , linked(false) - , expanded(false) -{ - setAutoApply(true); -} - -PropertyItem::~PropertyItem() -{ - qDeleteAll(childItems); -} - -void PropertyItem::initialize() -{ -} - -void PropertyItem::reset() -{ - qDeleteAll(childItems); - childItems.clear(); -} - -void PropertyItem::onChange() -{ - if (hasExpression()) { - for(auto child : std::as_const(childItems)) { - if(child && child->hasExpression()) { - child->setExpression(std::shared_ptr()); - } - } - for(auto item=parentItem;item;item=item->parentItem) { - if(item->hasExpression()) { - item->setExpression(std::shared_ptr()); - } - } - } -} - -bool PropertyItem::hasAnyExpression() const -{ - if(ExpressionBinding::hasExpression()) { - return true; - } - if(parentItem) { - return parentItem->hasExpression(); - } - return false; -} - -void PropertyItem::setPropertyData(const std::vector& items) -{ - //if we have a single property we can bind it for expression handling - if (items.size() == 1) { - const App::Property& prop = *items.front(); - - try { - // Check for 'DocumentObject' as parent because otherwise 'ObjectIdentifier' raises an exception - auto * docObj = Base::freecad_dynamic_cast(prop.getContainer()); - if (docObj && !docObj->isReadOnly(&prop)) { - App::ObjectIdentifier id(prop); - std::vector paths; - prop.getPaths(paths); - - //there may be no paths available in this property (for example an empty constraint list) - if (id.getProperty() && !paths.empty()) { - bind(id); - } - } - } - //it may happen that setting properties is not possible - catch (...) { - } - } - - propertyItems = items; - updateData(); - this->initialize(); -} - -void PropertyItem::updateData() -{ - bool ro = true; - for (auto it : propertyItems) { - App::PropertyContainer* parent = it->getContainer(); - if (parent) { - ro &= (parent->isReadOnly(it) || it->testStatus(App::Property::ReadOnly)); - } - } - this->setReadOnly(ro); -} - -const std::vector& PropertyItem::getPropertyData() const -{ - return propertyItems; -} - -bool PropertyItem::hasProperty(const App::Property* prop) const -{ - auto it = std::find(propertyItems.begin(), propertyItems.end(), prop); - return (it != propertyItems.end()); -} - -void PropertyItem::assignProperty(const App::Property* prop) -{ - Q_UNUSED(prop) -} - -bool PropertyItem::removeProperty(const App::Property* prop) -{ - auto it = std::find(propertyItems.begin(), propertyItems.end(), prop); - if (it != propertyItems.end()) { - propertyItems.erase(it); - } - - return propertyItems.empty(); -} - -App::Property* PropertyItem::getFirstProperty() -{ - if (propertyItems.empty()) { - return nullptr; - } - return propertyItems.front(); -} - -const App::Property* PropertyItem::getFirstProperty() const -{ - if (propertyItems.empty()) { - return nullptr; - } - return propertyItems.front(); -} - -void PropertyItem::setParent(PropertyItem* parent) -{ - parentItem = parent; -} - -PropertyItem *PropertyItem::parent() const -{ - return parentItem; -} - -void PropertyItem::appendChild(PropertyItem *item) -{ - childItems.append(item); -} - -void PropertyItem::insertChild(int index, PropertyItem *child) -{ - childItems.insert(index, child); -} - -/*! - * \brief PropertyItem::removeChildren - * Deletes the children in the range of [from, to] - */ -void PropertyItem::removeChildren(int from, int to) -{ - int count = to - from + 1; - for (int i=0; isetParent(nullptr); - return child; -} - -PropertyItem *PropertyItem::child(int row) -{ - return childItems.value(row); -} - -int PropertyItem::childCount() const -{ - return childItems.count(); -} - -int PropertyItem::columnCount() const -{ - return 2; -} - -void PropertyItem::setReadOnly(bool ro) -{ - readonly = ro; - for (auto it : std::as_const(childItems)) { - it->setReadOnly(ro); - } -} - -bool PropertyItem::isReadOnly() const -{ - return readonly; -} - -void PropertyItem::setLinked(bool value) -{ - linked = value; - for (auto it : std::as_const(childItems)) { - it->setLinked(value); - } -} - -bool PropertyItem::isLinked() const -{ - return linked; -} - -void PropertyItem::setExpanded(bool enable) -{ - expanded = enable; -} - -bool PropertyItem::isExpanded() const -{ - return expanded; -} - -bool PropertyItem::testStatus(App::Property::Status pos) const -{ - std::vector::const_iterator it; - for (it = propertyItems.begin(); it != propertyItems.end(); ++it) { - if ((*it)->testStatus(pos)) { - return true; - } - } - return false; -} - -void PropertyItem::setDecimals(int prec) -{ - precision = prec; -} - -int PropertyItem::decimals() const -{ - return precision; -} - -QVariant PropertyItem::displayName() const -{ - return {displayText}; -} - -QVariant PropertyItem::toolTip(const App::Property* prop) const -{ - QString str = QApplication::translate("App::Property", - prop->getDocumentation()); - return {str}; -} - -QVariant PropertyItem::decoration(const QVariant& value) const -{ - Q_UNUSED(value) - return {}; -} - -QString PropertyItem::asNone(const Py::Object& pyobj) const -{ - Q_UNUSED(pyobj) - return QString::fromUtf8(""); -} - -QString PropertyItem::asString(const Py::Object& pyobj) const -{ - return QString::fromStdString(pyobj.as_string()); -} - -QString PropertyItem::asSequence(const Py::Object& pyobj) const -{ - std::ostringstream ss; - ss << '['; - Py::Sequence seq(pyobj); - bool first = true; - Py_ssize_t i = 0; - for (i=0; i < 2 && i < seq.size(); ++i) { - if (first) { - first = false; - } - else { - ss << ", "; - } - ss << Py::Object(seq[i]).as_string(); - } - - if (i < seq.size()) { - ss << "..."; - } - ss << ']'; - return QString::fromUtf8(ss.str().c_str()); -} - -QString PropertyItem::asMapping(const Py::Object& pyobj) const -{ - std::ostringstream ss; - ss << '{'; - Py::Mapping map(pyobj); - bool first = true; - auto it = map.begin(); - for (int i = 0; i < 2 && it != map.end(); ++it, ++i) { - if (first) { - first = false; - } - else { - ss << ", "; - } - const auto &v = *it; - ss << Py::Object(v.first).as_string() << ':' << Py::Object(v.second).as_string(); - } - - if (it != map.end()) { - ss << "..."; - } - ss << '}'; - return QString::fromUtf8(ss.str().c_str()); -} - -QString PropertyItem::toString(const Py::Object& pyobj) const -{ - if (pyobj.isNone()) { - return asNone(pyobj); - } - if (pyobj.isSequence()) { - return asSequence(pyobj); - } - if (pyobj.isMapping()) { - return asMapping(pyobj); - } - - return asString(pyobj); -} - -QVariant PropertyItem::toString(const QVariant& prop) const -{ - if (prop != QVariant() || propertyItems.size()!=1) { - return prop; - } - - std::ostringstream ss; - Base::PyGILStateLocker lock; - try { - Py::Object pyobj(propertyItems[0]->getPyObject(), true); - return toString(pyobj); - } - catch (Py::Exception &) { - Base::PyException e; - ss.str(""); - ss << "ERR: " << e.what(); - } - catch (Base::Exception &e) { - ss.str(""); - ss << "ERR: " << e.what(); - } - catch (std::exception &e) { - ss.str(""); - ss << "ERR: " << e.what(); - } - catch (...) { - ss.str(""); - ss << "ERR!"; - } - - return {QString::fromUtf8(ss.str().c_str())}; -} - -QVariant PropertyItem::value(const App::Property* /*prop*/) const -{ - return {}; -} - -void PropertyItem::setValue(const QVariant& /*value*/) -{ -} - -QWidget* PropertyItem::createEditor(QWidget* /*parent*/, const std::function& /*method*/) const -{ - return nullptr; -} - -void PropertyItem::setEditorData(QWidget * /*editor*/, const QVariant& /*data*/) const -{ -} - -QVariant PropertyItem::editorData(QWidget * /*editor*/) const -{ - return {}; -} - -QWidget* PropertyItem::createExpressionEditor(QWidget* parent, const std::function& method) const -{ - if(!isBound()) { - return nullptr; - } - auto le = new ExpLineEdit(parent,true); - le->setFrame(false); - le->setReadOnly(true); - QObject::connect(le, &ExpLineEdit::textChanged, method); - le->bind(getPath()); - le->setAutoApply(autoApply()); - return le; -} - -void PropertyItem::setExpressionEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - if (le) { - le->setText(data.toString()); - } -} - -QVariant PropertyItem::expressionEditorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - if(le) { - return {le->text()}; - } - return {}; -} - -PropertyEditorWidget* PropertyItem::createPropertyEditorWidget(QWidget* parent) const -{ - auto editor = new PropertyEditorWidget(parent); - connect(editor, &PropertyEditorWidget::buttonClick, this, [this]() { - const auto &props = this->getPropertyData(); - if (!props.empty() - && props[0]->getName() - && props[0]->testStatus(App::Property::UserEdit) - && props[0]->getContainer()) { - props[0]->getContainer()->editProperty(props[0]->getName()); - } - }); - return editor; -} - -QString PropertyItem::propertyName() const -{ - if (propName.isEmpty()) { - return QLatin1String(QT_TRANSLATE_NOOP("App::Property", "")); - } - return propName; -} - -void PropertyItem::setPropertyName(const QString& name, const QString& realName) -{ - if (realName.size()) { - propName = realName; - } - else { - propName = name; - } - - setObjectName(propName); - - QString display; - bool upper = false; - for (auto && i : name) { - if (i.isUpper() && !display.isEmpty()) { - // if there is a sequence of capital letters do not insert spaces - if (!upper) { - QChar last = display.at(display.length()-1); - if (!last.isSpace()) { - display += QLatin1String(" "); - } - } - } - upper = i.isUpper(); - display += i; - } - - propName = display; - - QString str = QApplication::translate("App::Property", propName.toUtf8()); - displayText = str; -} - -void PropertyItem::setPropertyValue(const QString& value) -{ - // Construct command for property assignment in one go, in case of any - // intermediate changes caused by property change that may potentially - // invalidate the current property array. - std::ostringstream ss; - for (auto prop : propertyItems) { - App::PropertyContainer* parent = prop->getContainer(); - if (!parent || parent->isReadOnly(prop) || prop->testStatus(App::Property::ReadOnly)) { - continue; - } - - if (parent->isDerivedFrom(App::Document::getClassTypeId())) { - auto doc = static_cast(parent); - ss << "FreeCAD.getDocument('" << doc->getName() << "')."; - } - else if (parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) { - auto obj = static_cast(parent); - App::Document* doc = obj->getDocument(); - ss << "FreeCAD.getDocument('" << doc->getName() << "').getObject('" - << obj->getNameInDocument() << "')."; - } - else if (parent->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { - App::DocumentObject* obj = static_cast(parent)->getObject(); - App::Document* doc = obj->getDocument(); - ss << "FreeCADGui.getDocument('" << doc->getName() << "').getObject('" - << obj->getNameInDocument() << "')."; - } - else { - continue; - } - - ss << parent->getPropertyPrefix() << prop->getName() - << " = " << value.toUtf8().constData() << '\n'; - } - - std::string cmd = ss.str(); - if (cmd.empty()) { - return; - } - - try { - Gui::Command::runCommand(Gui::Command::App, cmd.c_str()); - } - catch (Base::PyException &e) { - e.ReportException(); - Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str()); - } - catch (Base::Exception &e) { - e.ReportException(); - } - catch (...) { - Base::Console().Error("Unknown C++ exception in PropertyItem::setPropertyValue thrown\n"); - } -} - -QVariant PropertyItem::dataProperty(int role) const -{ - if (role == Qt::ForegroundRole && linked) { - return QVariant::fromValue(QColor(0x20, 0xaa, 0x20)); // NOLINT - } - - if (role == Qt::BackgroundRole || role == Qt::ForegroundRole) { - if (PropertyView::showAll() - && propertyItems.size() == 1 - && propertyItems.front()->testStatus(App::Property::PropDynamic) - && !propertyItems.front()->testStatus(App::Property::LockDynamic)) { - return role == Qt::BackgroundRole - ? QVariant::fromValue(QColor(0xFF, 0xFF, 0x99)) // NOLINT - : QVariant::fromValue(QColor(0, 0, 0)); - } - return {}; - } - if (role == Qt::DisplayRole) { - return displayName(); - } - // no properties set - if (propertyItems.empty()) { - return {}; - } - if (role == Qt::ToolTipRole) { - QString type = QString::fromLatin1("Type: %1\nName: %2").arg( - QString::fromLatin1(propertyItems[0]->getTypeId().getName()), objectName()); - - QString doc = PropertyItem::toolTip(propertyItems[0]).toString(); - if (doc.isEmpty()) { - doc = toolTip(propertyItems[0]).toString(); - } - if (doc.size()) { - return type + QLatin1String("\n\n") + doc; - } - return type; - } - - return {}; -} - -QVariant PropertyItem::dataValue(int role) const -{ - // no properties set - if (propertyItems.empty()) { - PropertyItem* parent = this->parent(); - if (!parent || !parent->parent()) { - return {}; - } - if (role == Qt::EditRole) { - return parent->property(qPrintable(objectName())); - } - if (role == Qt::DecorationRole) { - QVariant val = parent->property(qPrintable(objectName())); - return decoration(val); - } - if (role == Qt::DisplayRole) { - QVariant val = parent->property(qPrintable(objectName())); - return toString(val); - } - if (role == Qt::ForegroundRole) { - if (hasExpression()) { - return QVariant::fromValue(QApplication::palette().color(QPalette::Link)); - } - return {}; - } - - return {}; - } - if (role == Qt::EditRole) { - return value(propertyItems[0]); - } - if (role == Qt::DecorationRole) { - return decoration(value(propertyItems[0])); - } - if (role == Qt::DisplayRole) { - return toString(value(propertyItems[0])); - } - if (role == Qt::ToolTipRole) { - return toolTip(propertyItems[0]); - } - if (role == Qt::ForegroundRole) { - if (hasExpression()) { - return QVariant::fromValue(QApplication::palette().color(QPalette::Link)); - } - return {}; - } - - return {}; -} - -QVariant PropertyItem::data(int column, int role) const -{ - // property name - if (column == 0) { - return dataProperty(role); - } - - return dataValue(role); -} - -bool PropertyItem::setData (const QVariant& value) -{ - // This is the basic mechanism to set the value to - // a property and if no property is set for this item - // it delegates it to its parent which sets then the - // property or delegates again to its parent... - if (propertyItems.empty()) { - PropertyItem* parent = this->parent(); - if (!parent || !parent->parent() || hasAnyExpression()) { - return false; - } - - parent->setProperty(qPrintable(objectName()),value); - return true; - } - - setValue(value); - return true; -} - -Qt::ItemFlags PropertyItem::flags(int column) const -{ - Qt::ItemFlags basicFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - if (column == 1 && !isReadOnly()) { - return basicFlags | Qt::ItemIsEditable; - } - - return basicFlags; -} - -int PropertyItem::row() const -{ - if (parentItem) { - return parentItem->childItems.indexOf(const_cast(this)); // NOLINT - } - - return 0; -} - -void PropertyItem::bind(const App::ObjectIdentifier& _path) -{ - Gui::ExpressionBinding::bind(_path); - propertyBound(); -} - -void PropertyItem::bind(const App::Property& prop) -{ - Gui::ExpressionBinding::bind(prop); - propertyBound(); -} - -QString PropertyItem::expressionAsString() const -{ - if (hasExpression()) { - try { - std::unique_ptr result(getExpression()->eval()); - return QString::fromStdString(result->toString()); - } - catch (const Base::Exception& e) { - e.ReportException(); - } - } - - return {}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringItem) - -PropertyStringItem::PropertyStringItem() = default; - -QVariant PropertyStringItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - std::string value = static_cast(prop)->getValue(); - return {QString::fromUtf8(value.c_str())}; -} - -void PropertyStringItem::setValue(const QVariant& value) -{ - if(!hasExpression()) { - if (!value.canConvert()) { - return; - } - QString val = value.toString(); - val = QString::fromUtf8(Base::InterpreterSingleton::strToPython(val.toUtf8()).c_str()); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); - } -} - -QWidget* PropertyStringItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto le = new ExpLineEdit(parent); - le->setFrame(false); - le->setReadOnly(isReadOnly()); - QObject::connect(le, &ExpLineEdit::textChanged, method); - if(isBound()) { - le->bind(getPath()); - le->setAutoApply(autoApply()); - } - - return le; -} - -void PropertyStringItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - le->setText(data.toString()); -} - -QVariant PropertyStringItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - return {le->text()}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFontItem) - -PropertyFontItem::PropertyFontItem() = default; - -QVariant PropertyFontItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - std::string value = static_cast(prop)->getValue(); - return {QString::fromUtf8(value.c_str())}; -} - -void PropertyFontItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); -} - -QWidget* PropertyFontItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto cb = new QComboBox(parent); - cb->setFrame(false); - cb->setDisabled(isReadOnly()); -#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - QObject::connect(cb, qOverload(&QComboBox::activated), method); -#else - QObject::connect(cb, &QComboBox::textActivated, method); -#endif - return cb; -} - -void PropertyFontItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto cb = qobject_cast(editor); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - QStringList familyNames = QFontDatabase().families(QFontDatabase::Any); -#else - QStringList familyNames = QFontDatabase::families(QFontDatabase::Any); -#endif - cb->addItems(familyNames); - int index = familyNames.indexOf(data.toString()); - cb->setCurrentIndex(index); -} - -QVariant PropertyFontItem::editorData(QWidget *editor) const -{ - auto cb = qobject_cast(editor); - return {cb->currentText()}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertySeparatorItem) - -QWidget* PropertySeparatorItem::createEditor(QWidget* parent, const std::function& method) const -{ - Q_UNUSED(parent); - Q_UNUSED(method); - return nullptr; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerItem) - -PropertyIntegerItem::PropertyIntegerItem() = default; - -QVariant PropertyIntegerItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - int value = (int)static_cast(prop)->getValue(); - return {value}; -} - -void PropertyIntegerItem::setValue(const QVariant& value) -{ - //if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - int val = value.toInt(); - QString data = QString::fromLatin1("%1").arg(val); - setPropertyValue(data); - } -} - -QWidget* PropertyIntegerItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto sb = new Gui::IntSpinBox(parent); - sb->setFrame(false); - sb->setReadOnly(isReadOnly()); - QObject::connect(sb, qOverload(&Gui::IntSpinBox::valueChanged), method); - - if (isBound()) { - sb->bind(getPath()); - sb->setAutoApply(autoApply()); - } - - return sb; -} - -void PropertyIntegerItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto sb = qobject_cast(editor); - sb->setRange(INT_MIN, INT_MAX); - sb->setValue(data.toInt()); -} - -QVariant PropertyIntegerItem::editorData(QWidget *editor) const -{ - auto sb = qobject_cast(editor); - return {sb->value()}; -} - -QVariant PropertyIntegerItem::toString(const QVariant& v) const -{ - QString string(PropertyItem::toString(v).toString()); - - if (hasExpression()) { - string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - - return {string}; -} - - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerConstraintItem) - -PropertyIntegerConstraintItem::PropertyIntegerConstraintItem() = default; - -QVariant PropertyIntegerConstraintItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - int value = (int)static_cast(prop)->getValue(); - return {value}; -} - -void PropertyIntegerConstraintItem::setValue(const QVariant& value) -{ - //if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - int val = value.toInt(); - QString data = QString::fromLatin1("%1").arg(val); - setPropertyValue(data); - } -} - -QWidget* PropertyIntegerConstraintItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto sb = new Gui::IntSpinBox(parent); - sb->setFrame(false); - sb->setReadOnly(isReadOnly()); - QObject::connect(sb, qOverload(&Gui::IntSpinBox::valueChanged), method); - - if (isBound()) { - sb->bind(getPath()); - sb->setAutoApply(autoApply()); - } - - return sb; -} - -void PropertyIntegerConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - const auto prop = static_cast - (getFirstProperty()); - - const App::PropertyIntegerConstraint::Constraints* c = nullptr; - if (prop) { - c = prop->getConstraints(); - } - - auto sb = qobject_cast(editor); - if (c) { - sb->setMinimum(int(c->LowerBound)); - sb->setMaximum(int(c->UpperBound)); - sb->setSingleStep(int(c->StepSize)); - } - else { - sb->setMinimum(min); - sb->setMaximum(max); - sb->setSingleStep(steps); - } - - sb->setValue(data.toInt()); -} - -QVariant PropertyIntegerConstraintItem::editorData(QWidget *editor) const -{ - auto sb = qobject_cast(editor); - return {sb->value()}; -} - -QVariant PropertyIntegerConstraintItem::toString(const QVariant& v) const -{ - QString string(PropertyItem::toString(v).toString()); - - if (hasExpression()) { - string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - - return {string}; -} - - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatItem) - -PropertyFloatItem::PropertyFloatItem() = default; - -QVariant PropertyFloatItem::toString(const QVariant& prop) const -{ - double value = prop.toDouble(); - QString data = QLocale().toString(value, 'f', decimals()); - - if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - - return {data}; -} - -QVariant PropertyFloatItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - double value = static_cast(prop)->getValue(); - return {value}; -} - -void PropertyFloatItem::setValue(const QVariant& value) -{ - //if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - double val = value.toDouble(); - QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); - setPropertyValue(data); - } -} - -QWidget* PropertyFloatItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto sb = new Gui::DoubleSpinBox(parent); - sb->setFrame(false); - sb->setDecimals(decimals()); - sb->setReadOnly(isReadOnly()); - QObject::connect(sb, qOverload(&Gui::DoubleSpinBox::valueChanged), method); - - if (isBound()) { - sb->bind(getPath()); - sb->setAutoApply(autoApply()); - } - - return sb; -} - -void PropertyFloatItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto sb = qobject_cast(editor); - sb->setRange((double)INT_MIN, (double)INT_MAX); - sb->setValue(data.toDouble()); -} - -QVariant PropertyFloatItem::editorData(QWidget *editor) const -{ - auto sb = qobject_cast(editor); - return {sb->value()}; -} - -// -------------------------------------------------------------------- - - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitItem) - -PropertyUnitItem::PropertyUnitItem() = default; - -QVariant PropertyUnitItem::toString(const QVariant& prop) const -{ - const Base::Quantity& unit = prop.value(); - QString string = unit.getUserString(); - if (hasExpression()) { - string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - - return {string}; -} - -QVariant PropertyUnitItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - Base::Quantity value = static_cast(prop)->getQuantityValue(); - return QVariant::fromValue(value); -} - -void PropertyUnitItem::setValue(const QVariant& value) -{ - //if the item has an expression it handles the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - const Base::Quantity& val = value.value(); - - Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); - QString unit = Base::UnitsApi::toString(val, format); - setPropertyValue(unit); - } -} - -QWidget* PropertyUnitItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto infield = new Gui::QuantitySpinBox(parent); - infield->setFrame(false); - infield->setMinimumHeight(0); - infield->setReadOnly(isReadOnly()); - - //if we are bound to an expression we need to bind it to the input field - if (isBound()) { - infield->bind(getPath()); - infield->setAutoApply(autoApply()); - } - - - QObject::connect(infield, qOverload(&Gui::QuantitySpinBox::valueChanged), method); - return infield; -} - -void PropertyUnitItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - const Base::Quantity& value = data.value(); - - auto infield = qobject_cast(editor); - infield->setValue(value); - infield->selectAll(); -} - -QVariant PropertyUnitItem::editorData(QWidget *editor) const -{ - auto infield = qobject_cast(editor); - Base::Quantity value = infield->value(); - return QVariant::fromValue(value); -} - -// -------------------------------------------------------------------- - - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitConstraintItem) - -PropertyUnitConstraintItem::PropertyUnitConstraintItem() = default; - -void PropertyUnitConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - const Base::Quantity& value = data.value(); - - auto infield = qobject_cast(editor); - infield->setValue(value); - infield->selectAll(); - - const auto prop = static_cast - (getFirstProperty()); - - const App::PropertyQuantityConstraint::Constraints* c = nullptr; - if (prop) { - c = prop->getConstraints(); - } - - if (c) { - infield->setMinimum(c->LowerBound); - infield->setMaximum(c->UpperBound); - infield->setSingleStep(c->StepSize); - } - else { - infield->setMinimum(min); - infield->setMaximum(max); - infield->setSingleStep(steps); - } -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatConstraintItem) - -PropertyFloatConstraintItem::PropertyFloatConstraintItem() = default; - -QVariant PropertyFloatConstraintItem::toString(const QVariant& prop) const -{ - double value = prop.toDouble(); - QString data = QLocale().toString(value, 'f', decimals()); - return {data}; -} - -QVariant PropertyFloatConstraintItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - double value = static_cast(prop)->getValue(); - return {value}; -} - -void PropertyFloatConstraintItem::setValue(const QVariant& value) -{ - //if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - double val = value.toDouble(); - QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); - setPropertyValue(data); - } -} - -QWidget* PropertyFloatConstraintItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto sb = new Gui::DoubleSpinBox(parent); - sb->setDecimals(decimals()); - sb->setFrame(false); - sb->setReadOnly(isReadOnly()); - QObject::connect(sb, qOverload(&Gui::DoubleSpinBox::valueChanged), method); - - if (isBound()) { - sb->bind(getPath()); - sb->setAutoApply(autoApply()); - } - - return sb; -} - -void PropertyFloatConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - const auto prop = static_cast - (getFirstProperty()); - - const App::PropertyFloatConstraint::Constraints* c = nullptr; - if (prop) { - c = prop->getConstraints(); - } - - auto sb = qobject_cast(editor); - if (c) { - sb->setMinimum(c->LowerBound); - sb->setMaximum(c->UpperBound); - sb->setSingleStep(c->StepSize); - } - else { - sb->setMinimum(min); - sb->setMaximum(max); - sb->setSingleStep(steps); - } - - sb->setValue(data.toDouble()); -} - -QVariant PropertyFloatConstraintItem::editorData(QWidget *editor) const -{ - auto sb = qobject_cast(editor); - return {sb->value()}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPrecisionItem) - -PropertyPrecisionItem::PropertyPrecisionItem() -{ - setDecimals(highPrec); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyAngleItem) - -PropertyAngleItem::PropertyAngleItem() = default; - -void PropertyAngleItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - PropertyUnitConstraintItem::setEditorData(editor, data); -} - -QVariant PropertyAngleItem::toString(const QVariant& prop) const -{ - return PropertyUnitConstraintItem::toString(prop); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyBoolItem) - -PropertyBoolItem::PropertyBoolItem() = default; - -QVariant PropertyBoolItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - bool value = static_cast(prop)->getValue(); - return {value}; -} - -void PropertyBoolItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - bool val = value.toBool(); - QString data = (val ? QLatin1String("True") : QLatin1String("False")); - setPropertyValue(data); -} - -QWidget* PropertyBoolItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto cb = new QComboBox(parent); - cb->setFrame(false); - cb->addItem(QLatin1String("false")); - cb->addItem(QLatin1String("true")); - cb->setDisabled(isReadOnly()); - QObject::connect(cb, qOverload(&QComboBox::activated), method); - return cb; -} - -void PropertyBoolItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto cb = qobject_cast(editor); - cb->setCurrentIndex(cb->findText(data.toString())); -} - -QVariant PropertyBoolItem::editorData(QWidget *editor) const -{ - auto cb = qobject_cast(editor); - return {cb->currentText()}; -} - -// --------------------------------------------------------------- - -namespace Gui::PropertyEditor { -class VectorLineEdit : public Gui::ExpLineEdit -{ - int decimals; -public: - explicit VectorLineEdit (int decimals, QWidget * parent=nullptr, bool expressionOnly=false) - : Gui::ExpLineEdit(parent, expressionOnly) - , decimals(decimals) - { - } - - bool apply(const std::string &propName) override { - // NOLINTNEXTLINE - if (!ExpressionBinding::apply(propName)) { // clazy:exclude=skipped-base-method - QVariant data = property("coords"); - if (data.canConvert()) { - const Base::Vector3d& value = data.value(); - - QString str = QString::fromLatin1("(%1, %2, %3)") - .arg(value.x, 0, 'f', decimals) - .arg(value.y, 0, 'f', decimals) - .arg(value.z, 0, 'f', decimals); - - Gui::Command::doCommand(Gui::Command::Doc, "%s = %s", propName.c_str(), str.toLatin1().constData()); - return true; - } - } - - return false; - } -}; -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorItem) - -PropertyVectorItem::PropertyVectorItem() -{ - m_x = static_cast(PropertyFloatItem::create()); - m_x->setParent(this); - m_x->setPropertyName(QLatin1String("x")); - this->appendChild(m_x); - m_y = static_cast(PropertyFloatItem::create()); - m_y->setParent(this); - m_y->setPropertyName(QLatin1String("y")); - this->appendChild(m_y); - m_z = static_cast(PropertyFloatItem::create()); - m_z->setParent(this); - m_z->setPropertyName(QLatin1String("z")); - this->appendChild(m_z); -} - -QVariant PropertyVectorItem::toString(const QVariant& prop) const -{ - QLocale loc; - const Base::Vector3d& value = prop.value(); - QString data = QString::fromLatin1("[%1 %2 %3]") - .arg(loc.toString(value.x, 'f', lowPrec), - loc.toString(value.y, 'f', lowPrec), - loc.toString(value.z, 'f', lowPrec)); - if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - return {data}; -} - -QVariant PropertyVectorItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Vector3d& value = static_cast(prop)->getValue(); - return QVariant::fromValue(value); -} - -void PropertyVectorItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - const Base::Vector3d& val = value.value(); - QString data = QString::fromLatin1("(%1, %2, %3)") - .arg(val.x, 0, 'g', highPrec) - .arg(val.y, 0, 'g', highPrec) - .arg(val.z, 0, 'g', highPrec); - setPropertyValue(data); -} - -QWidget* PropertyVectorItem::createEditor(QWidget* parent, const std::function& /*method*/) const -{ - auto le = new VectorLineEdit(decimals(), parent); - le->setFrame(false); - le->setReadOnly(true); - - if (isBound()) { - le->bind(getPath()); - le->setAutoApply(autoApply()); - } - - return le; -} - -void PropertyVectorItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - QLocale loc; - auto le = qobject_cast(editor); - const Base::Vector3d& value = data.value(); - QString text = QString::fromLatin1("[%1 %2 %3]") - .arg(loc.toString(value.x, 'f', lowPrec), - loc.toString(value.y, 'f', lowPrec), - loc.toString(value.z, 'f', lowPrec)); - le->setProperty("coords", data); - le->setText(text); -} - -QVariant PropertyVectorItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - return {le->text()}; -} - -double PropertyVectorItem::x() const -{ - return data(1,Qt::EditRole).value().x; -} - -void PropertyVectorItem::setX(double x) -{ - setData(QVariant::fromValue(Base::Vector3d(x, y(), z()))); -} - -double PropertyVectorItem::y() const -{ - return data(1,Qt::EditRole).value().y; -} - -void PropertyVectorItem::setY(double y) -{ - setData(QVariant::fromValue(Base::Vector3d(x(), y, z()))); -} - -double PropertyVectorItem::z() const -{ - return data(1,Qt::EditRole).value().z; -} - -void PropertyVectorItem::setZ(double z) -{ - setData(QVariant::fromValue(Base::Vector3d(x(), y(), z))); -} - -void PropertyVectorItem::propertyBound() -{ - m_x->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<setContentsMargins(0, 0, 0, 0); - layout->setSpacing(2); - - lineEdit = new QLineEdit(this); - lineEdit->setReadOnly(true); - layout->addWidget(lineEdit); - - button = new QPushButton(QLatin1String("..."), this); -#if defined (Q_OS_MACOS) - button->setAttribute(Qt::WA_LayoutUsesWidgetRect); // layout size from QMacStyle was not correct -#endif - layout->addWidget(button); - - connect(button, &QPushButton::clicked, this, &PropertyEditorWidget::buttonClick); - - // QAbstractItemView will call selectAll() if a QLineEdit is the focus - // proxy. Since the QLineEdit here is read-only and not meant for editing, - // do not set it as focus proxy. Otherwise, the text won't even shown for - // most stylesheets (which contain a trick to hide the content of a selected - // read-only/disabled editor widgets). - // - // setFocusProxy(lineEdit); -} - -PropertyEditorWidget::~PropertyEditorWidget() = default; - -void PropertyEditorWidget::resizeEvent(QResizeEvent* e) -{ - button->setFixedWidth(e->size().height()); - button->setFixedHeight(e->size().height()); -} - -void PropertyEditorWidget::showValue(const QVariant &d) -{ - lineEdit->setText(d.toString()); -} - -QVariant PropertyEditorWidget::value() const -{ - return variant; -} - -void PropertyEditorWidget::setValue(const QVariant& val) -{ - variant = val; - showValue(variant); - Q_EMIT valueChanged(variant); -} - -// --------------------------------------------------------------- - -VectorListWidget::VectorListWidget(int decimals, QWidget *parent) - : PropertyEditorWidget(parent) - , decimals(decimals) -{ - connect(button, &QPushButton::clicked, this, &VectorListWidget::buttonClicked); -} - -void VectorListWidget::buttonClicked() -{ - auto dlg = new VectorListEditor(decimals, this); - dlg->setAttribute(Qt::WA_DeleteOnClose); - dlg->setValues(value().value>()); - QPoint p(0, 0); - p = this->mapToGlobal(p); - dlg->move(p); - connect(dlg, &VectorListEditor::accepted, this, [this, dlg] { - QVariant data = QVariant::fromValue>(dlg->getValues()); - setValue(data); - }); - - dlg->exec(); -} - -void VectorListWidget::showValue(const QVariant& d) -{ - QLocale loc; - QString data; - const QList& value = d.value>(); - if (value.isEmpty()) { - data = QString::fromLatin1("[]"); - } - else { - data = QString::fromLatin1("[%1 %2 %3], ...") - .arg(loc.toString(value[0].x, 'f', lowPrec), - loc.toString(value[0].y, 'f', lowPrec), - loc.toString(value[0].z, 'f', lowPrec)); - } - lineEdit->setText(data); -} -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorListItem) - -PropertyVectorListItem::PropertyVectorListItem() = default; - -QVariant PropertyVectorListItem::toString(const QVariant& prop) const -{ - QLocale loc; - QString data; - const QList& value = prop.value>(); - if (value.isEmpty()) { - data = QString::fromLatin1("[]"); - } - else { - data = QString::fromLatin1("[%1 %2 %3], ...") - .arg(loc.toString(value[0].x, 'f', lowPrec), - loc.toString(value[0].y, 'f', lowPrec), - loc.toString(value[0].z, 'f', lowPrec)); - } - - if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - return {data}; -} - -QVariant PropertyVectorListItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const std::vector& value = static_cast(prop)->getValue(); - QList list; - std::copy(value.begin(), value.end(), std::back_inserter(list)); - return QVariant::fromValue>(list); -} - -void PropertyVectorListItem::setValue(const QVariant& value) -{ - if (!value.canConvert>()) { - return; - } - const QList& val = value.value>(); - QString data; - QTextStream str(&data); - str << "["; - for (const auto& it : val) { - str << QString::fromLatin1("(%1, %2, %3), ") - .arg(it.x, 0, 'g', highPrec) - .arg(it.y, 0, 'g', highPrec) - .arg(it.z, 0, 'g', highPrec); - } - str << "]"; - setPropertyValue(data); -} - -QWidget* PropertyVectorListItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto pe = new VectorListWidget(decimals(), parent); - QObject::connect(pe, &VectorListWidget::valueChanged, method); - pe->setDisabled(isReadOnly()); - return pe; -} - -void PropertyVectorListItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto pe = qobject_cast(editor); - pe->setValue(data); -} - -QVariant PropertyVectorListItem::editorData(QWidget *editor) const -{ - auto pe = qobject_cast(editor); - return pe->value(); -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorDistanceItem) - -PropertyVectorDistanceItem::PropertyVectorDistanceItem() -{ - m_x = static_cast(PropertyUnitItem::create()); - m_x->setParent(this); - m_x->setPropertyName(QLatin1String("x")); - this->appendChild(m_x); - m_y = static_cast(PropertyUnitItem::create()); - m_y->setParent(this); - m_y->setPropertyName(QLatin1String("y")); - this->appendChild(m_y); - m_z = static_cast(PropertyUnitItem::create()); - m_z->setParent(this); - m_z->setPropertyName(QLatin1String("z")); - this->appendChild(m_z); -} - -QVariant PropertyVectorDistanceItem::toString(const QVariant& prop) const -{ - const Base::Vector3d& value = prop.value(); - QString data = QString::fromLatin1("[") + - Base::Quantity(value.x, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + - Base::Quantity(value.y, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + - Base::Quantity(value.z, Base::Unit::Length).getUserString() + QString::fromLatin1("]"); - if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); - } - return {data}; -} - - -QVariant PropertyVectorDistanceItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Vector3d& value = static_cast(prop)->getValue(); - return QVariant::fromValue(value); -} - -void PropertyVectorDistanceItem::setValue(const QVariant& variant) -{ - if (hasExpression() || !variant.canConvert()) { - return; - } - const Base::Vector3d& value = variant.value(); - - Base::Quantity x = Base::Quantity(value.x, Base::Unit::Length); - Base::Quantity y = Base::Quantity(value.y, Base::Unit::Length); - Base::Quantity z = Base::Quantity(value.z, Base::Unit::Length); - - Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); - QString data = QString::fromLatin1("(%1, %2, %3)") - .arg(Base::UnitsApi::toNumber(x, format), - Base::UnitsApi::toNumber(y, format), - Base::UnitsApi::toNumber(z, format)); - setPropertyValue(data); -} - -void PropertyVectorDistanceItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - le->setProperty("coords", data); - le->setText(toString(data).toString()); -} - -QWidget* PropertyVectorDistanceItem::createEditor(QWidget* parent, const std::function& /*method*/) const -{ - auto le = new VectorLineEdit(decimals(), parent); - le->setFrame(false); - le->setReadOnly(true); - - if (isBound()) { - le->bind(getPath()); - le->setAutoApply(autoApply()); - } - - return le; -} - -QVariant PropertyVectorDistanceItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - return {le->text()}; -} - -Base::Quantity PropertyVectorDistanceItem::x() const -{ - return Base::Quantity(data(1,Qt::EditRole).value().x, Base::Unit::Length); -} - -void PropertyVectorDistanceItem::setX(Base::Quantity x) -{ - setData(QVariant::fromValue(Base::Vector3d(x.getValue(), y().getValue(), z().getValue()))); -} - -Base::Quantity PropertyVectorDistanceItem::y() const -{ - return Base::Quantity(data(1,Qt::EditRole).value().y, Base::Unit::Length); -} - -void PropertyVectorDistanceItem::setY(Base::Quantity y) -{ - setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y.getValue(), z().getValue()))); -} - -Base::Quantity PropertyVectorDistanceItem::z() const -{ - return Base::Quantity(data(1,Qt::EditRole).value().z, Base::Unit::Length); -} - -void PropertyVectorDistanceItem::setZ(Base::Quantity z) -{ - setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y().getValue(), z.getValue()))); -} - -void PropertyVectorDistanceItem::propertyBound() -{ - if (isBound()) { - m_x->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<(PropertyFloatItem::create()); - m_a11->setParent(this); - m_a11->setPropertyName(QLatin1String("A11")); - m_a11->setDecimals(decimals); - this->appendChild(m_a11); - m_a12 = static_cast(PropertyFloatItem::create()); - m_a12->setParent(this); - m_a12->setPropertyName(QLatin1String("A12")); - m_a12->setDecimals(decimals); - this->appendChild(m_a12); - m_a13 = static_cast(PropertyFloatItem::create()); - m_a13->setParent(this); - m_a13->setPropertyName(QLatin1String("A13")); - m_a13->setDecimals(decimals); - this->appendChild(m_a13); - m_a14 = static_cast(PropertyFloatItem::create()); - m_a14->setParent(this); - m_a14->setPropertyName(QLatin1String("A14")); - m_a14->setDecimals(decimals); - this->appendChild(m_a14); - m_a21 = static_cast(PropertyFloatItem::create()); - m_a21->setParent(this); - m_a21->setPropertyName(QLatin1String("A21")); - m_a21->setDecimals(decimals); - this->appendChild(m_a21); - m_a22 = static_cast(PropertyFloatItem::create()); - m_a22->setParent(this); - m_a22->setPropertyName(QLatin1String("A22")); - m_a22->setDecimals(decimals); - this->appendChild(m_a22); - m_a23 = static_cast(PropertyFloatItem::create()); - m_a23->setParent(this); - m_a23->setPropertyName(QLatin1String("A23")); - m_a23->setDecimals(decimals); - this->appendChild(m_a23); - m_a24 = static_cast(PropertyFloatItem::create()); - m_a24->setParent(this); - m_a24->setPropertyName(QLatin1String("A24")); - m_a24->setDecimals(decimals); - this->appendChild(m_a24); - m_a31 = static_cast(PropertyFloatItem::create()); - m_a31->setParent(this); - m_a31->setPropertyName(QLatin1String("A31")); - m_a31->setDecimals(decimals); - this->appendChild(m_a31); - m_a32 = static_cast(PropertyFloatItem::create()); - m_a32->setParent(this); - m_a32->setPropertyName(QLatin1String("A32")); - m_a32->setDecimals(decimals); - this->appendChild(m_a32); - m_a33 = static_cast(PropertyFloatItem::create()); - m_a33->setParent(this); - m_a33->setPropertyName(QLatin1String("A33")); - m_a33->setDecimals(decimals); - this->appendChild(m_a33); - m_a34 = static_cast(PropertyFloatItem::create()); - m_a34->setParent(this); - m_a34->setPropertyName(QLatin1String("A34")); - m_a34->setDecimals(decimals); - this->appendChild(m_a34); - m_a41 = static_cast(PropertyFloatItem::create()); - m_a41->setParent(this); - m_a41->setPropertyName(QLatin1String("A41")); - m_a41->setDecimals(decimals); - this->appendChild(m_a41); - m_a42 = static_cast(PropertyFloatItem::create()); - m_a42->setParent(this); - m_a42->setPropertyName(QLatin1String("A42")); - m_a42->setDecimals(decimals); - this->appendChild(m_a42); - m_a43 = static_cast(PropertyFloatItem::create()); - m_a43->setParent(this); - m_a43->setPropertyName(QLatin1String("A43")); - m_a43->setDecimals(decimals); - this->appendChild(m_a43); - m_a44 = static_cast(PropertyFloatItem::create()); - m_a44->setParent(this); - m_a44->setPropertyName(QLatin1String("A44")); - m_a44->setDecimals(decimals); - this->appendChild(m_a44); -} - -QVariant PropertyMatrixItem::toString(const QVariant& prop) const -{ - QLocale loc; - const Base::Matrix4D& value = prop.value(); - // NOLINTBEGIN - QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") - .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) - loc.toString(value[0][1], 'f', lowPrec), - loc.toString(value[0][2], 'f', lowPrec), - loc.toString(value[0][3], 'f', lowPrec), - loc.toString(value[1][0], 'f', lowPrec), - loc.toString(value[1][1], 'f', lowPrec), - loc.toString(value[1][2], 'f', lowPrec), - loc.toString(value[1][3], 'f', lowPrec), - loc.toString(value[2][0], 'f', lowPrec)) - .arg(loc.toString(value[2][1], 'f', lowPrec), - loc.toString(value[2][2], 'f', lowPrec), - loc.toString(value[2][3], 'f', lowPrec), - loc.toString(value[3][0], 'f', lowPrec), - loc.toString(value[3][1], 'f', lowPrec), - loc.toString(value[3][2], 'f', lowPrec), - loc.toString(value[3][3], 'f', lowPrec)); - // NOLINTEND - return {text}; -} - -QVariant PropertyMatrixItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Matrix4D& value = static_cast(prop)->getValue(); - return QVariant::fromValue(value); -} - -QVariant PropertyMatrixItem::toolTip(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Matrix4D& value = static_cast(prop)->getValue(); - return {QString::fromStdString(value.analyse())}; -} - -void PropertyMatrixItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - const Base::Matrix4D& val = value.value(); - // NOLINTBEGIN - QString data = QString::fromLatin1("FreeCAD.Matrix(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)") - .arg(val[0][0],0, 'g', highPrec) - .arg(val[0][1],0, 'g', highPrec) - .arg(val[0][2],0, 'g', highPrec) - .arg(val[0][3],0, 'g', highPrec) - .arg(val[1][0],0, 'g', highPrec) - .arg(val[1][1],0, 'g', highPrec) - .arg(val[1][2],0, 'g', highPrec) - .arg(val[1][3],0, 'g', highPrec) - .arg(val[2][0],0, 'g', highPrec) - .arg(val[2][1],0, 'g', highPrec) - .arg(val[2][2],0, 'g', highPrec) - .arg(val[2][3],0, 'g', highPrec) - .arg(val[3][0],0, 'g', highPrec) - .arg(val[3][1],0, 'g', highPrec) - .arg(val[3][2],0, 'g', highPrec) - .arg(val[3][3],0, 'g', highPrec); - // NOLINTEND - setPropertyValue(data); -} - -QWidget* PropertyMatrixItem::createEditor(QWidget* parent, const std::function& /*method*/) const -{ - auto le = new QLineEdit(parent); - le->setFrame(false); - le->setReadOnly(true); - return le; -} - -void PropertyMatrixItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - QLocale loc; - auto le = qobject_cast(editor); - const Base::Matrix4D& value = data.value(); - // NOLINTBEGIN - QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") - .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) - loc.toString(value[0][1], 'f', lowPrec), - loc.toString(value[0][2], 'f', lowPrec), - loc.toString(value[0][3], 'f', lowPrec), - loc.toString(value[1][0], 'f', lowPrec), - loc.toString(value[1][1], 'f', lowPrec), - loc.toString(value[1][2], 'f', lowPrec), - loc.toString(value[1][3], 'f', lowPrec), - loc.toString(value[2][0], 'f', lowPrec)) - .arg(loc.toString(value[2][1], 'f', lowPrec), - loc.toString(value[2][2], 'f', lowPrec), - loc.toString(value[2][3], 'f', lowPrec), - loc.toString(value[3][0], 'f', lowPrec), - loc.toString(value[3][1], 'f', lowPrec), - loc.toString(value[3][2], 'f', lowPrec), - loc.toString(value[3][3], 'f', lowPrec)); - // NOLINTEND - le->setText(text); -} - -QVariant PropertyMatrixItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - return {le->text()}; -} - -// clang-format off -double PropertyMatrixItem::getA11() const -{ - return data(1, Qt::EditRole).value()[0][0]; -} - -void PropertyMatrixItem::setA11(double A11) -{ - setData(QVariant::fromValue(Base::Matrix4D(A11, getA12(), getA13(),getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA12() const -{ - return data(1, Qt::EditRole).value()[0][1]; -} - -void PropertyMatrixItem::setA12(double A12) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), A12, getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA13() const -{ - return data(1, Qt::EditRole).value()[0][2]; -} - -void PropertyMatrixItem::setA13(double A13) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), A13, getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA14() const -{ - return data(1, Qt::EditRole).value()[0][3]; -} - -void PropertyMatrixItem::setA14(double A14) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), A14, - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA21() const -{ - return data(1, Qt::EditRole).value()[1][0]; -} - -void PropertyMatrixItem::setA21(double A21) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - A21, getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA22() const -{ - return data(1, Qt::EditRole).value()[1][1]; -} - -void PropertyMatrixItem::setA22(double A22) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), A22, getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA23() const -{ - return data(1, Qt::EditRole).value()[1][2]; -} - -void PropertyMatrixItem::setA23(double A23) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), A23, getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA24() const -{ - return data(1, Qt::EditRole).value()[1][3]; -} - -void PropertyMatrixItem::setA24(double A24) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), A24, - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA31() const -{ - return data(1, Qt::EditRole).value()[2][0]; -} - -void PropertyMatrixItem::setA31(double A31) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - A31, getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA32() const -{ - return data(1, Qt::EditRole).value()[2][1]; -} - -void PropertyMatrixItem::setA32(double A32) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), A32, getA33(), getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA33() const -{ - return data(1, Qt::EditRole).value()[2][2]; -} - -void PropertyMatrixItem::setA33(double A33) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), A33, getA34(), - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA34() const -{ - return data(1, Qt::EditRole).value()[2][3]; -} - -void PropertyMatrixItem::setA34(double A34) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), A34, - getA41(), getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA41() const -{ - return data(1, Qt::EditRole).value()[3][0]; -} - -void PropertyMatrixItem::setA41(double A41) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - A41, getA42(), getA43(), getA44()))); -} - -double PropertyMatrixItem::getA42() const -{ - return data(1, Qt::EditRole).value()[3][1]; -} - -void PropertyMatrixItem::setA42(double A42) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), A42, getA43(), getA44()))); -} - -double PropertyMatrixItem::getA43() const -{ - return data(1, Qt::EditRole).value()[3][2]; -} - -void PropertyMatrixItem::setA43(double A43) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), A43, getA44()))); -} - -double PropertyMatrixItem::getA44() const -{ - return data(1, Qt::EditRole).value()[3][3]; -} - -void PropertyMatrixItem::setA44(double A44) -{ - setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), - getA21(), getA22(), getA23(), getA24(), - getA31(), getA32(), getA33(), getA34(), - getA41(), getA42(), getA43(), A44))); -} -// clang-format on - -// --------------------------------------------------------------- - -RotationHelper::RotationHelper() - : init_axis(false) - , changed_value(false) - , rot_angle(0) - , rot_axis(0,0,1) -{ -} - -void RotationHelper::setChanged(bool value) -{ - changed_value = value; -} - -bool RotationHelper::hasChangedAndReset() -{ - if (!changed_value) { - return false; - } - - changed_value = false; - return true; -} - -bool RotationHelper::isAxisInitialized() const -{ - return init_axis; -} - -void RotationHelper::setValue(const Base::Vector3d& axis, double angle) -{ - rot_axis = axis; - rot_angle = angle; - init_axis = true; -} - -void RotationHelper::getValue(Base::Vector3d& axis, double& angle) const -{ - axis = rot_axis; - angle = rot_angle; -} - -double RotationHelper::getAngle(const Base::Rotation& val) const -{ - double angle {}; - Base::Vector3d dir; - val.getRawValue(dir, angle); - if (dir * this->rot_axis < 0.0) { - angle = -angle; - } - return angle; -} - -Base::Rotation RotationHelper::setAngle(double angle) -{ - Base::Rotation rot; - rot.setValue(this->rot_axis, Base::toRadians(angle)); - changed_value = true; - rot_angle = angle; - return rot; -} - -Base::Vector3d RotationHelper::getAxis() const -{ - // We must store the rotation axis in a member because - // if we read the value from the property we would always - // get a normalized vector which makes it quite unhandy - // to work with - return this->rot_axis; -} - -Base::Rotation RotationHelper::setAxis(const Base::Rotation& value, const Base::Vector3d& axis) -{ - this->rot_axis = axis; - Base::Rotation rot = value; - Base::Vector3d dummy; - double angle {}; - rot.getValue(dummy, angle); - if (dummy * axis < 0.0) { - angle = -angle; - } - rot.setValue(axis, angle); - changed_value = true; - return rot; -} - -void RotationHelper::assignProperty(const Base::Rotation& value, double eps) -{ - double angle {}; - Base::Vector3d dir; - value.getRawValue(dir, angle); - Base::Vector3d cross = this->rot_axis.Cross(dir); - double len2 = cross.Sqr(); - if (angle != 0) { - // vectors are not parallel - if (len2 > eps) { - this->rot_axis = dir; - } - // vectors point into opposite directions - else if (this->rot_axis.Dot(dir) < 0) { - this->rot_axis = -this->rot_axis; - } - } - this->rot_angle = Base::toDegrees(angle); -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyRotationItem) - -PropertyRotationItem::PropertyRotationItem() -{ - m_a = static_cast(PropertyUnitItem::create()); - m_a->setParent(this); - m_a->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Angle"))); - this->appendChild(m_a); - m_d = static_cast(PropertyVectorItem::create()); - m_d->setParent(this); - m_d->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Axis"))); - m_d->setReadOnly(true); - this->appendChild(m_d); -} - -PropertyRotationItem::~PropertyRotationItem() = default; - -Base::Quantity PropertyRotationItem::getAngle() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return Base::Quantity(0.0); - } - - const Base::Rotation& val = value.value(); - double angle = h.getAngle(val); - return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); -} - -void PropertyRotationItem::setAngle(Base::Quantity angle) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - Base::Rotation rot = h.setAngle(angle.getValue()); - setValue(QVariant::fromValue(rot)); -} - -Base::Vector3d PropertyRotationItem::getAxis() const -{ - return h.getAxis(); -} - -void PropertyRotationItem::setAxis(const Base::Vector3d& axis) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto rot = value.value(); - rot = h.setAxis(rot, axis); - setValue(QVariant::fromValue(rot)); -} - -void PropertyRotationItem::assignProperty(const App::Property* prop) -{ - // Choose an adaptive epsilon to avoid changing the axis when they are considered to - // be equal. See https://forum.freecad.org/viewtopic.php?f=10&t=24662&start=10 - double eps = std::pow(10.0, -2 * (decimals() + 1)); // NOLINT - if (prop->isDerivedFrom()) { - const Base::Rotation& value = static_cast(prop)->getValue(); - h.assignProperty(value, eps); - } -} - -QVariant PropertyRotationItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Rotation& value = static_cast(prop)->getValue(); - double angle {}; - Base::Vector3d dir; - value.getRawValue(dir, angle); - if (!h.isAxisInitialized()) { - if (m_a->hasExpression()) { - QString str = m_a->expressionAsString(); - angle = str.toDouble(); - } - else { - angle = Base::toDegrees(angle); - } - - PropertyItem* x = m_d->child(0); - PropertyItem* y = m_d->child(1); - PropertyItem* z = m_d->child(2); - if (x->hasExpression()) { - QString str = x->expressionAsString(); - dir.x = str.toDouble(); - } - if (y->hasExpression()) { - QString str = y->expressionAsString(); - dir.y = str.toDouble(); - } - if (z->hasExpression()) { - QString str = z->expressionAsString(); - dir.z = str.toDouble(); - } - h.setValue(dir, angle); - } - return QVariant::fromValue(value); -} - -QVariant PropertyRotationItem::toolTip(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Rotation& p = static_cast(prop)->getValue(); - double angle {}; - Base::Vector3d dir; - p.getRawValue(dir, angle); - angle = Base::toDegrees(angle); - - QLocale loc; - QString data = QString::fromUtf8("Axis: (%1 %2 %3)\n" - "Angle: %4") - .arg(loc.toString(dir.x, 'f', decimals()), - loc.toString(dir.y, 'f', decimals()), - loc.toString(dir.z, 'f', decimals()), - Base::Quantity(angle, Base::Unit::Angle).getUserString()); - return {data}; -} - -QVariant PropertyRotationItem::toString(const QVariant& prop) const -{ - const Base::Rotation& p = prop.value(); - double angle {}; - Base::Vector3d dir; - p.getRawValue(dir, angle); - angle = Base::toDegrees(angle); - - QLocale loc; - QString data = QString::fromUtf8("[(%1 %2 %3); %4]") - .arg(loc.toString(dir.x, 'f', lowPrec), - loc.toString(dir.y, 'f', lowPrec), - loc.toString(dir.z, 'f', lowPrec), - Base::Quantity(angle, Base::Unit::Angle).getUserString()); - return {data}; -} - -void PropertyRotationItem::setValue(const QVariant& value) -{ - if (!value.canConvert()) { - return; - } - // Accept this only if the user changed the axis, angle or position but - // not if >this< item loses focus - if (!h.hasChangedAndReset()) { - return; - } - - Base::Vector3d axis; - double angle {}; - h.getValue(axis, angle); - Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); - QString data = QString::fromLatin1("App.Rotation(App.Vector(%1,%2,%3),%4)") - .arg(Base::UnitsApi::toNumber(axis.x, format), - Base::UnitsApi::toNumber(axis.y, format), - Base::UnitsApi::toNumber(axis.z, format), - Base::UnitsApi::toNumber(angle, format)); - setPropertyValue(data); -} - -QWidget* PropertyRotationItem::createEditor(QWidget* parent, const std::function& method) const -{ - Q_UNUSED(parent) - Q_UNUSED(method) - return nullptr; -} - -void PropertyRotationItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - Q_UNUSED(editor) - Q_UNUSED(data) -} - -QVariant PropertyRotationItem::editorData(QWidget *editor) const -{ - Q_UNUSED(editor) - return {}; -} - -void PropertyRotationItem::propertyBound() -{ - if (isBound()) { - m_a->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Angle")); - - m_d->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Axis")); - } -} - -// -------------------------------------------------------------------- - -PlacementEditor::PlacementEditor(QString name, QWidget * parent) - : LabelButton(parent) - , _task(nullptr) - , propertyname{std::move(name)} -{ - propertyname.replace(QLatin1String(" "), QLatin1String("")); -} - -PlacementEditor::~PlacementEditor() = default; - -void PlacementEditor::browse() -{ - Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); - Gui::Dialog::TaskPlacement* task {}; - task = qobject_cast(dlg); - if (dlg && !task) { - // there is already another task dialog which must be closed first - Gui::Control().showDialog(dlg); - return; - } - if (!task) { - task = new Gui::Dialog::TaskPlacement(); - } - if (!_task) { - _task = task; - connect(task, &TaskPlacement::placementChanged, - this, &PlacementEditor::updateValue); - } - task->setPlacement(value().value()); - task->setPropertyName(propertyname); - task->setSelection(Gui::Selection().getSelectionEx()); - task->bindObject(); - Gui::Control().showDialog(task); -} - -void PlacementEditor::showValue(const QVariant& d) -{ - const Base::Placement& p = d.value(); - double angle {}; - Base::Vector3d dir; - Base::Vector3d pos; - p.getRotation().getRawValue(dir, angle); - angle = Base::toDegrees(angle); - pos = p.getPosition(); - - QLocale loc; - QString data = QString::fromUtf8("[(%1 %2 %3);%4 \xc2\xb0;(%5 %6 %7)]") - .arg(loc.toString(dir.x, 'f', lowPrec), - loc.toString(dir.y, 'f', lowPrec), - loc.toString(dir.z, 'f', lowPrec), - loc.toString(angle, 'f', lowPrec), - loc.toString(pos.x, 'f', lowPrec), - loc.toString(pos.y, 'f', lowPrec), - loc.toString(pos.z, 'f', lowPrec)); - getLabel()->setText(data); -} - -void PlacementEditor::updateValue(const QVariant& v, bool incr, bool data) -{ - if (data) { - if (incr) { - QVariant u = value(); - const Base::Placement& plm = u.value(); - const Base::Placement& rel = v.value(); - Base::Placement newp = rel * plm; - setValue(QVariant::fromValue(newp)); - } - else { - setValue(v); - } - } -} - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPlacementItem) - -PropertyPlacementItem::PropertyPlacementItem() -{ - m_a = static_cast(PropertyUnitItem::create()); - m_a->setParent(this); - m_a->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Angle"))); - this->appendChild(m_a); - m_d = static_cast(PropertyVectorItem::create()); - m_d->setParent(this); - m_d->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Axis"))); - m_d->setReadOnly(true); - this->appendChild(m_d); - m_p = static_cast(PropertyVectorDistanceItem::create()); - m_p->setParent(this); - m_p->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Position"))); - m_p->setReadOnly(true); - this->appendChild(m_p); -} - -PropertyPlacementItem::~PropertyPlacementItem() = default; - -Base::Quantity PropertyPlacementItem::getAngle() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return Base::Quantity(0.0); - } - - const Base::Placement& val = value.value(); - double angle = h.getAngle(val.getRotation()); - return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); -} - -void PropertyPlacementItem::setAngle(Base::Quantity angle) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto val = value.value(); - Base::Rotation rot = h.setAngle(angle.getValue()); - val.setRotation(rot); - setValue(QVariant::fromValue(val)); -} - -Base::Vector3d PropertyPlacementItem::getAxis() const -{ - return h.getAxis(); -} - -void PropertyPlacementItem::setAxis(const Base::Vector3d& axis) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto val = value.value(); - Base::Rotation rot = val.getRotation(); - rot = h.setAxis(rot, axis); - val.setRotation(rot); - setValue(QVariant::fromValue(val)); -} - -Base::Vector3d PropertyPlacementItem::getPosition() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return Base::Vector3d(0,0,0); - } - const Base::Placement& val = value.value(); - return val.getPosition(); -} - -void PropertyPlacementItem::setPosition(const Base::Vector3d& pos) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto val = value.value(); - val.setPosition(pos); - h.setChanged(true); - setValue(QVariant::fromValue(val)); -} - -void PropertyPlacementItem::assignProperty(const App::Property* prop) -{ - // Choose an adaptive epsilon to avoid changing the axis when they are considered to - // be equal. See https://forum.freecad.org/viewtopic.php?f=10&t=24662&start=10 - double eps = std::pow(10.0, -2 * (decimals() + 1)); // NOLINT - if (prop->isDerivedFrom()) { - const Base::Placement& value = static_cast(prop)->getValue(); - h.assignProperty(value.getRotation(), eps); - } -} - -QVariant PropertyPlacementItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Placement& value = static_cast(prop)->getValue(); - double angle {}; - Base::Vector3d dir; - value.getRotation().getRawValue(dir, angle); - if (!h.isAxisInitialized()) { - if (m_a->hasExpression()) { - QString str = m_a->expressionAsString(); - angle = str.toDouble(); - } - else { - angle = Base::toDegrees(angle); - } - - PropertyItem* x = m_d->child(0); - PropertyItem* y = m_d->child(1); - PropertyItem* z = m_d->child(2); - if (x->hasExpression()) { - QString str = x->expressionAsString(); - dir.x = str.toDouble(); - } - if (y->hasExpression()) { - QString str = y->expressionAsString(); - dir.y = str.toDouble(); - } - if (z->hasExpression()) { - QString str = z->expressionAsString(); - dir.z = str.toDouble(); - } - h.setValue(dir, angle); - } - return QVariant::fromValue(value); -} - -QVariant PropertyPlacementItem::toolTip(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const Base::Placement& p = static_cast(prop)->getValue(); - double angle {}; - Base::Vector3d dir; - Base::Vector3d pos; - p.getRotation().getRawValue(dir, angle); - angle = Base::toDegrees(angle); - pos = p.getPosition(); - - QLocale loc; - QString data = QString::fromUtf8("Axis: (%1 %2 %3)\n" - "Angle: %4\n" - "Position: (%5 %6 %7)") - .arg(loc.toString(dir.x, 'f', decimals()), - loc.toString(dir.y, 'f', decimals()), - loc.toString(dir.z, 'f', decimals()), - Base::Quantity(angle, Base::Unit::Angle).getUserString(), - Base::Quantity(pos.x, Base::Unit::Length).getUserString(), - Base::Quantity(pos.y, Base::Unit::Length).getUserString(), - Base::Quantity(pos.z, Base::Unit::Length).getUserString()); - return {data}; -} - -QVariant PropertyPlacementItem::toString(const QVariant& prop) const -{ - const Base::Placement& p = prop.value(); - double angle {}; - Base::Vector3d dir; - Base::Vector3d pos; - p.getRotation().getRawValue(dir, angle); - angle = Base::toDegrees(angle); - pos = p.getPosition(); - - QLocale loc; - QString data = QString::fromUtf8("[(%1 %2 %3); %4; (%5 %6 %7)]") - .arg(loc.toString(dir.x, 'f', lowPrec), - loc.toString(dir.y, 'f', lowPrec), - loc.toString(dir.z, 'f', lowPrec), - Base::Quantity(angle, Base::Unit::Angle).getUserString(), - Base::Quantity(pos.x, Base::Unit::Length).getUserString(), - Base::Quantity(pos.y, Base::Unit::Length).getUserString(), - Base::Quantity(pos.z, Base::Unit::Length).getUserString()); - return {data}; -} - -void PropertyPlacementItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - // Accept this only if the user changed the axis, angle or position but - // not if >this< item loses focus - if (!h.hasChangedAndReset()) { - return; - } - - const Base::Placement& val = value.value(); - Base::Vector3d pos = val.getPosition(); - - Base::Vector3d axis; - double angle {}; - h.getValue(axis, angle); - - Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); - QString data = QString::fromLatin1("App.Placement(" - "App.Vector(%1,%2,%3)," - "App.Rotation(App.Vector(%4,%5,%6),%7))") - .arg(Base::UnitsApi::toNumber(pos.x, format), - Base::UnitsApi::toNumber(pos.y, format), - Base::UnitsApi::toNumber(pos.z, format), - Base::UnitsApi::toNumber(axis.x, format), - Base::UnitsApi::toNumber(axis.y, format), - Base::UnitsApi::toNumber(axis.z, format), - Base::UnitsApi::toNumber(angle, format)); - setPropertyValue(data); -} - -QWidget* PropertyPlacementItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto pe = new PlacementEditor(this->propertyName(), parent); - QObject::connect(pe, &PlacementEditor::valueChanged, method); - - // The Placement dialog only works if property is part of a DocumentObject - bool readonly = isReadOnly(); - if (auto prop = getFirstProperty()) { - readonly |= (!prop->getContainer()->isDerivedFrom()); - } - pe->setDisabled(readonly); - return pe; -} - -void PropertyPlacementItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto pe = qobject_cast(editor); - pe->setValue(data); -} - -QVariant PropertyPlacementItem::editorData(QWidget *editor) const -{ - auto pe = qobject_cast(editor); - return pe->value(); -} - -void PropertyPlacementItem::propertyBound() -{ - if (isBound()) { - m_a->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<(PropertyStringListItem::create()); - m_enum->setParent(this); - m_enum->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Enum"))); - this->appendChild(m_enum); - } -} - -void PropertyEnumItem::propertyBound() -{ - if (m_enum && isBound()) { - m_enum->bind(App::ObjectIdentifier(getPath())<isDerivedFrom()) { - const auto prop_enum = static_cast(prop); - std::vector enums = prop_enum->getEnumVector(); - for (const auto& it : enums) { - res.push_back(QString::fromStdString(it)); - } - } - return res; -} - -QVariant PropertyEnumItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const auto prop_enum = static_cast(prop); - if(!prop_enum->isValid()) { - return {QString()}; - } - return {QString::fromUtf8(prop_enum->getValueAsString())}; -} - -void PropertyEnumItem::setValue(const QVariant& value) -{ - if (hasExpression()) { - return; - } - - QString data; - - if (value.userType() == QMetaType::QStringList) { - QStringList values = value.toStringList(); - QTextStream str(&data); - str << "["; - for (const auto & it : values) { - QString text(it); - text.replace(QString::fromUtf8("'"),QString::fromUtf8("\\'")); - - std::string pystr = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); - pystr = Base::InterpreterSingleton::strToPython(pystr.c_str()); - str << "u\"" << pystr.c_str() << "\", "; - } - str << "]"; - setPropertyValue(data); - } - else if (value.canConvert()) { - QByteArray val = value.toString().toUtf8(); - std::string str = Base::Tools::escapedUnicodeFromUtf8(val); - data = QString::fromLatin1("u\"%1\"").arg(QString::fromStdString(str)); - setPropertyValue(data); - } -} - -namespace { - -class EnumItems; - -struct EnumItem { - QString text; - QString fullText; - std::shared_ptr children; - explicit EnumItem(QString t = QString(), QString f = QString()) - : text(std::move(t)) - , fullText(std::move(f)) - {} - void populate(QMenu *menu); -}; - -class EnumItems : public std::vector -{ -}; - -void EnumItem::populate(QMenu *menu) -{ - if (!children || children->empty()) { - auto action = menu->addAction(text); - action->setData(fullText); - return; - } - auto subMenu = menu->addMenu(text); - for (auto &item : *children) { - item.populate(subMenu); - } -} - -std::shared_ptr getEnumItems(const QStringList& commonModes) // NOLINT -{ - int index = -1; - std::shared_ptr enumItems; - for (auto &mode : commonModes) { - ++index; - auto fields = mode.split(QStringLiteral("|")); - if (!enumItems && fields.size() <= 1) { - continue; - } - if (!enumItems) { - enumItems = std::make_shared(); - for (int i=0; iemplace_back(commonModes[i], mode); - } - } - auto children = enumItems; - int j = -1; - for (auto &field : fields) { - ++j; - field = field.trimmed(); - auto it = children->end(); - if (field.isEmpty()) { - if (!children->empty()) { - --it; - } - else { - continue; - } - } - else { - it = std::find_if(children->begin(), children->end(), - [&field](const EnumItem &item) { - return item.text == field; - }); - if (it == children->end()) { - it = children->emplace(children->end(), field, mode); - } - } - if (j + 1 == (int)fields.size()) { - break; - } - if (!it->children) { - it->children = std::make_shared(); - } - children = it->children; - } - } - - return enumItems; -} - -} // anonymous namespace - -QStringList PropertyEnumItem::getCommonModes() const -{ - const std::vector& items = getPropertyData(); - - QStringList commonModes; - QStringList modes; - for (auto it = items.begin(); it != items.end(); ++it) { - if ((*it)->is()) { - auto prop = static_cast(*it); - if (!prop->hasEnums()) { - commonModes.clear(); - return {}; - } - const std::vector& value = prop->getEnumVector(); - if (it == items.begin()) { - for (const auto & jt : value) { - commonModes << QString::fromUtf8(jt.c_str()); - } - } - else { - for (const auto & jt : value) { - if (commonModes.contains(QString::fromUtf8(jt.c_str()))) { - modes << QString::fromUtf8(jt.c_str()); - } - } - - commonModes = modes; - modes.clear(); - } - } - } - - return commonModes; -} - -QWidget* PropertyEnumItem::createEditor(QWidget* parent, const std::function& method) const -{ - QStringList commonModes = getCommonModes(); - if (commonModes.isEmpty()) { - return nullptr; - } - - std::shared_ptr enumItems = getEnumItems(commonModes); - - if (!enumItems) { - auto cb = new QComboBox(parent); - cb->setFrame(false); - cb->setDisabled(isReadOnly()); - cb->addItems(commonModes); - QObject::connect(cb, qOverload(&QComboBox::activated), method); - return cb; - } - - auto button = new PropertyEnumButton(parent); - button->setDisabled(isReadOnly()); - auto menu = new QMenu(button); - for (auto &item : *enumItems) { - item.populate(menu); - } - button->setMenu(menu); - QObject::connect(menu, &QMenu::aboutToShow, this, [=]() { - menu->setMinimumWidth(button->width()); - }); - QObject::connect(menu, &QMenu::triggered, this, [=](QAction *action) { - button->setText(action->data().toString()); - Q_EMIT button->picked(); - }); - QObject::connect(button, &PropertyEnumButton::picked, method); - return button; -} - -void PropertyEnumItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - if (auto cb = qobject_cast(editor)) { - cb->setEditable(false); - cb->setCurrentIndex(cb->findText(data.toString())); - } - else if (auto btn = qobject_cast(editor)) { - btn->setText(data.toString()); - } -} - -QVariant PropertyEnumItem::editorData(QWidget *editor) const -{ - if (auto cb = qobject_cast(editor)) { - return {cb->currentText()}; - } - if (auto btn = qobject_cast(editor)) { - return btn->text(); - } - return {}; -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringListItem) - -PropertyStringListItem::PropertyStringListItem() = default; - -QWidget* PropertyStringListItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto le = new Gui::LabelEditor(parent); - le->setAutoFillBackground(true); - le->setDisabled(isReadOnly()); - QObject::connect(le, &Gui::LabelEditor::textChanged, method); - return le; -} - -void PropertyStringListItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - QStringList list = data.toStringList(); - le->setText(list.join(QChar::fromLatin1('\n'))); -} - -QVariant PropertyStringListItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - QString complete = le->text(); - QStringList list = complete.split(QChar::fromLatin1('\n')); - return {list}; -} - -QVariant PropertyStringListItem::toString(const QVariant& prop) const -{ - QStringList list = prop.toStringList(); - const int size = 10; - if (list.size() > size) { - list = list.mid(0, size); - list.append(QLatin1String("...")); - } - - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); - - return {text}; -} - -QVariant PropertyStringListItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - QStringList list; - const std::vector& value = (static_cast(prop))->getValues(); - for (const auto & jt : value) { - list << QString::fromUtf8(jt.c_str()); - } - - return {list}; -} - -void PropertyStringListItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - QStringList values = value.toStringList(); - QString data; - QTextStream str(&data); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - str.setCodec("UTF-8"); -#endif - - str << "["; - for (const auto & it : values) { - QString text(it); - std::string pystr = Base::InterpreterSingleton::strToPython(text.toUtf8().constData()); - str << "\"" << QString::fromUtf8(pystr.c_str()) << "\", "; - } - str << "]"; - - setPropertyValue(data); -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatListItem) - -PropertyFloatListItem::PropertyFloatListItem() = default; - -QWidget* PropertyFloatListItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto le = new Gui::LabelEditor(parent); - le->setAutoFillBackground(true); - le->setInputType(Gui::LabelEditor::Float); - le->setDisabled(isReadOnly()); - QObject::connect(le, &Gui::LabelEditor::textChanged, method); - return le; -} - -void PropertyFloatListItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - QStringList list = data.toStringList(); - le->setText(list.join(QChar::fromLatin1('\n'))); -} - -QVariant PropertyFloatListItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - QString complete = le->text(); - QStringList list = complete.split(QChar::fromLatin1('\n')); - return {list}; -} - -QVariant PropertyFloatListItem::toString(const QVariant& prop) const -{ - QStringList list = prop.toStringList(); - const int size = 10; - if (list.size() > size) { - list = list.mid(0, size); - list.append(QLatin1String("...")); - } - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); - return {text}; -} - -QVariant PropertyFloatListItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - QStringList list; - const std::vector& value = static_cast(prop)->getValues(); - for (double jt : value) { - list << QString::number(jt, 'f', decimals()); - } - - return {list}; -} - -void PropertyFloatListItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - QStringList values = value.toStringList(); - QString data; - QTextStream str(&data); - str << "["; - for (const auto & it : values) { - str << it << ","; - } - str << "]"; - if (data == QString::fromUtf8("[,]")) { - data = QString::fromUtf8("[]"); - } - setPropertyValue(data); -} - -// --------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerListItem) - -PropertyIntegerListItem::PropertyIntegerListItem() = default; - -QWidget* PropertyIntegerListItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto le = new Gui::LabelEditor(parent); - le->setAutoFillBackground(true); - le->setInputType(Gui::LabelEditor::Integer); - le->setDisabled(isReadOnly()); - QObject::connect(le, &Gui::LabelEditor::textChanged, method); - return le; -} - -void PropertyIntegerListItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto le = qobject_cast(editor); - QStringList list = data.toStringList(); - le->setText(list.join(QChar::fromLatin1('\n'))); -} - -QVariant PropertyIntegerListItem::editorData(QWidget *editor) const -{ - auto le = qobject_cast(editor); - QString complete = le->text(); - QStringList list = complete.split(QChar::fromLatin1('\n')); - return {list}; -} - -QVariant PropertyIntegerListItem::toString(const QVariant& prop) const -{ - QStringList list = prop.toStringList(); - const int size = 10; - if (list.size() > size) { - list = list.mid(0, size); - list.append(QLatin1String("...")); - } - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); - - return {text}; -} - -QVariant PropertyIntegerListItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - QStringList list; - const std::vector& value = static_cast(prop)->getValues(); - for (long jt : value) { - list << QString::number(jt); - } - - return {list}; -} - -void PropertyIntegerListItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - QStringList values = value.toStringList(); - QString data; - QTextStream str(&data); - str << "["; - for (const auto & value : values) { - str << value << ","; - } - str << "]"; - if (data == QString::fromUtf8("[,]")) { - data = QString::fromUtf8("[]"); - } - setPropertyValue(data); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyColorItem) - -PropertyColorItem::PropertyColorItem() = default; - -QVariant PropertyColorItem::decoration(const QVariant& value) const -{ - auto color = value.value(); - - int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); - QPixmap p(size, size); - p.fill(color); - - return QVariant(p); -} - -QVariant PropertyColorItem::toString(const QVariant& prop) const -{ - auto value = prop.value(); - QString color = QString::fromLatin1("[%1, %2, %3]") - .arg(value.red()).arg(value.green()).arg(value.blue()); - return {color}; -} - -QVariant PropertyColorItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - App::Color value = static_cast(prop)->getValue(); - return QVariant(value.asValue()); -} - -void PropertyColorItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - auto col = value.value(); - QString data = QString::fromLatin1("(%1,%2,%3)") - .arg(col.red()) - .arg(col.green()) - .arg(col.blue()); - setPropertyValue(data); -} - -QWidget* PropertyColorItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto cb = new Gui::ColorButton( parent ); - cb->setDisabled(isReadOnly()); - QObject::connect(cb, &Gui::ColorButton::changed, method); - return cb; -} - -void PropertyColorItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto cb = qobject_cast(editor); - auto color = data.value(); - cb->setColor(color); -} - -QVariant PropertyColorItem::editorData(QWidget *editor) const -{ - auto cb = qobject_cast(editor); - QVariant var; - var.setValue(cb->color()); - return var; -} - -// -------------------------------------------------------------------- - -namespace Gui::PropertyEditor { - class Material - { - public: - QColor diffuseColor; - QColor ambientColor; - QColor specularColor; - QColor emissiveColor; - float shininess {}; - float transparency {}; - }; -} - -Q_DECLARE_METATYPE(Gui::PropertyEditor::Material) // NOLINT - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialItem) - -PropertyMaterialItem::PropertyMaterialItem() -{ - const int min = 0; - const int max = 100; - const int steps = 5; - diffuse = static_cast(PropertyColorItem::create()); - diffuse->setParent(this); - diffuse->setPropertyName(QLatin1String("DiffuseColor")); - this->appendChild(diffuse); - - ambient = static_cast(PropertyColorItem::create()); - ambient->setParent(this); - ambient->setPropertyName(QLatin1String("AmbientColor")); - this->appendChild(ambient); - - specular = static_cast(PropertyColorItem::create()); - specular->setParent(this); - specular->setPropertyName(QLatin1String("SpecularColor")); - this->appendChild(specular); - - emissive = static_cast(PropertyColorItem::create()); - emissive->setParent(this); - emissive->setPropertyName(QLatin1String("EmissiveColor")); - this->appendChild(emissive); - - shininess = static_cast(PropertyIntegerConstraintItem::create()); - shininess->setRange(min, max); - shininess->setStepSize(steps); - shininess->setParent(this); - shininess->setPropertyName(QLatin1String("Shininess")); - this->appendChild(shininess); - - transparency = static_cast(PropertyIntegerConstraintItem::create()); - transparency->setRange(min, max); - transparency->setStepSize(steps); - transparency->setParent(this); - transparency->setPropertyName(QLatin1String("Transparency")); - this->appendChild(transparency); -} - -PropertyMaterialItem::~PropertyMaterialItem() = default; - -void PropertyMaterialItem::propertyBound() -{ -} - -QColor PropertyMaterialItem::getDiffuseColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - auto val = value.value(); - return val.diffuseColor; -} - -void PropertyMaterialItem::setDiffuseColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.diffuseColor = color; - setValue(QVariant::fromValue(mat)); -} - -QColor PropertyMaterialItem::getAmbientColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - auto val = value.value(); - return val.ambientColor; -} - -void PropertyMaterialItem::setAmbientColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.ambientColor = color; - setValue(QVariant::fromValue(mat)); -} - -QColor PropertyMaterialItem::getSpecularColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - auto val = value.value(); - return val.specularColor; -} - -void PropertyMaterialItem::setSpecularColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.specularColor = color; - setValue(QVariant::fromValue(mat)); -} - -QColor PropertyMaterialItem::getEmissiveColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - auto val = value.value(); - return val.emissiveColor; -} - -void PropertyMaterialItem::setEmissiveColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.emissiveColor = color; - setValue(QVariant::fromValue(mat)); -} - -int PropertyMaterialItem::getShininess() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return 0; - } - - auto val = value.value(); - return toPercent(val.shininess); -} - -void PropertyMaterialItem::setShininess(int s) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.shininess = fromPercent(s); - setValue(QVariant::fromValue(mat)); -} - -int PropertyMaterialItem::getTransparency() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return 0; - } - - auto val = value.value(); - return toPercent(val.transparency); -} - -void PropertyMaterialItem::setTransparency(int t) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - auto mat = value.value(); - mat.transparency = fromPercent(t); - setValue(QVariant::fromValue(mat)); -} - -QVariant PropertyMaterialItem::decoration(const QVariant& value) const -{ - // use the diffuse color - auto val = value.value(); - QColor color = val.diffuseColor; - - int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); - QPixmap p(size, size); - p.fill(color); - - return QVariant(p); -} - -QVariant PropertyMaterialItem::toString(const QVariant& prop) const -{ - // use the diffuse color - auto val = prop.value(); - QColor value = val.diffuseColor; - QString color = QString::fromLatin1("[%1, %2, %3]") - .arg(value.red()).arg(value.green()).arg(value.blue()); - return {color}; -} - -QVariant PropertyMaterialItem::toolTip(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const App::Material& value = static_cast(prop)->getValue(); - auto dc = value.diffuseColor.asValue(); - auto ac = value.ambientColor.asValue(); - auto sc = value.specularColor.asValue(); - auto ec = value.emissiveColor.asValue(); - - QString data = QString::fromUtf8( - "Diffuse color: [%1, %2, %3]\n" - "Ambient color: [%4, %5, %6]\n" - "Specular color: [%7, %8, %9]\n" - "Emissive color: [%10, %11, %12]\n" - "Shininess: %13\n" - "Transparency: %14" - ) - .arg(dc.red()).arg(dc.green()).arg(dc.blue()) - .arg(ac.red()).arg(ac.green()).arg(ac.blue()) - .arg(sc.red()).arg(sc.green()).arg(sc.blue()) - .arg(ec.red()).arg(ec.green()).arg(ec.blue()) - .arg(toPercent(value.shininess)) - .arg(toPercent(value.transparency)) - ; - - return {data}; -} - -QVariant PropertyMaterialItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const App::Material& value = static_cast(prop)->getValue(); - Material mat; - - mat.diffuseColor = value.diffuseColor.asValue(); - mat.ambientColor = value.ambientColor.asValue(); - mat.specularColor = value.specularColor.asValue(); - mat.emissiveColor = value.emissiveColor.asValue(); - mat.shininess = value.shininess; - mat.transparency = value.transparency; - - return QVariant::fromValue(mat); -} - -void PropertyMaterialItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - - auto mat = value.value(); - App::Color dc; dc.setValue(mat.diffuseColor); - App::Color ac; ac.setValue(mat.ambientColor); - App::Color sc; sc.setValue(mat.specularColor); - App::Color ec; ec.setValue(mat.emissiveColor); - float s = mat.shininess; - float t = mat.transparency; - - QString data = QString::fromLatin1( - "App.Material(" - "DiffuseColor=(%1,%2,%3)," - "AmbientColor=(%4,%5,%6)," - "SpecularColor=(%7,%8,%9)," - "EmissiveColor=(%10,%11,%12)," - "Shininess=(%13)," - "Transparency=(%14)," - ")" - ) - .arg(dc.r, 0, 'f', decimals()) - .arg(dc.g, 0, 'f', decimals()) - .arg(dc.b, 0, 'f', decimals()) - .arg(ac.r, 0, 'f', decimals()) - .arg(ac.g, 0, 'f', decimals()) - .arg(ac.b, 0, 'f', decimals()) - .arg(sc.r, 0, 'f', decimals()) - .arg(sc.g, 0, 'f', decimals()) - .arg(sc.b, 0, 'f', decimals()) - .arg(ec.r, 0, 'f', decimals()) - .arg(ec.g, 0, 'f', decimals()) - .arg(ec.b, 0, 'f', decimals()) - .arg(s, 0, 'f', decimals()) - .arg(t, 0, 'f', decimals()) - ; - - setPropertyValue(data); -} - -QWidget* PropertyMaterialItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto cb = new Gui::ColorButton(parent); - cb->setDisabled(isReadOnly()); - QObject::connect(cb, &Gui::ColorButton::changed, method); - return cb; -} - -void PropertyMaterialItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - if (!data.canConvert()) { - return; - } - - auto val = data.value(); - auto cb = qobject_cast(editor); - cb->setColor(val.diffuseColor); -} - -QVariant PropertyMaterialItem::editorData(QWidget *editor) const -{ - auto cb = qobject_cast(editor); - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - auto val = value.value(); - val.diffuseColor = cb->color(); - return QVariant::fromValue(val); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialListItem) - -PropertyMaterialListItem::PropertyMaterialListItem() -{ - const int min = 0; - const int max = 100; - const int steps = 5; - - // This editor gets a list of materials but it only edits the first item. - diffuse = static_cast(PropertyColorItem::create()); - diffuse->setParent(this); - diffuse->setPropertyName(QLatin1String("DiffuseColor")); - this->appendChild(diffuse); - - ambient = static_cast(PropertyColorItem::create()); - ambient->setParent(this); - ambient->setPropertyName(QLatin1String("AmbientColor")); - this->appendChild(ambient); - - specular = static_cast(PropertyColorItem::create()); - specular->setParent(this); - specular->setPropertyName(QLatin1String("SpecularColor")); - this->appendChild(specular); - - emissive = static_cast(PropertyColorItem::create()); - emissive->setParent(this); - emissive->setPropertyName(QLatin1String("EmissiveColor")); - this->appendChild(emissive); - - shininess = static_cast(PropertyIntegerConstraintItem::create()); - shininess->setRange(min, max); - shininess->setStepSize(steps); - shininess->setParent(this); - shininess->setPropertyName(QLatin1String("Shininess")); - this->appendChild(shininess); - - transparency = static_cast(PropertyIntegerConstraintItem::create()); - transparency->setRange(min, max); - transparency->setStepSize(steps); - transparency->setParent(this); - transparency->setPropertyName(QLatin1String("Transparency")); - this->appendChild(transparency); -} - -PropertyMaterialListItem::~PropertyMaterialListItem() = default; - -void PropertyMaterialListItem::propertyBound() -{ -} - -QColor PropertyMaterialListItem::getDiffuseColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - auto mat = list[0].value(); - return mat.diffuseColor; -} - -void PropertyMaterialListItem::setDiffuseColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.diffuseColor = color; - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -QColor PropertyMaterialListItem::getAmbientColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - auto mat = list[0].value(); - return mat.ambientColor; -} - -void PropertyMaterialListItem::setAmbientColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.ambientColor = color; - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -QColor PropertyMaterialListItem::getSpecularColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - auto mat = list[0].value(); - return mat.specularColor; -} - -void PropertyMaterialListItem::setSpecularColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.specularColor = color; - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -QColor PropertyMaterialListItem::getEmissiveColor() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - auto mat = list[0].value(); - return mat.emissiveColor; -} - -void PropertyMaterialListItem::setEmissiveColor(const QColor& color) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.emissiveColor = color; - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -int PropertyMaterialListItem::getShininess() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return 0; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return 0; - } - - if (!list[0].canConvert()) { - return 0; - } - - auto mat = list[0].value(); - return toPercent(mat.shininess); -} - -void PropertyMaterialListItem::setShininess(int s) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.shininess = fromPercent(s); - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -int PropertyMaterialListItem::getTransparency() const -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return 0; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return 0; - } - - if (!list[0].canConvert()) { - return 0; - } - - auto mat = list[0].value(); - return toPercent(mat.transparency); -} - -void PropertyMaterialListItem::setTransparency(int t) -{ - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - auto mat = list[0].value(); - mat.transparency = fromPercent(t); - list[0] = QVariant::fromValue(mat); - setValue(list); -} - -QVariant PropertyMaterialListItem::decoration(const QVariant& value) const -{ - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - // use the diffuse color - auto mat = list[0].value(); - QColor color = mat.diffuseColor; - - int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); - QPixmap p(size, size); - p.fill(color); - - return QVariant(p); -} - -QVariant PropertyMaterialListItem::toString(const QVariant& prop) const -{ - if (!prop.canConvert()) { - return {}; - } - - QVariantList list = prop.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - // use the diffuse color - auto mat = list[0].value(); - QColor value = mat.diffuseColor; - QString color = QString::fromLatin1("[%1, %2, %3]") - .arg(value.red()).arg(value.green()).arg(value.blue()); - return {color}; -} - -QVariant PropertyMaterialListItem::toolTip(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const std::vector& values = static_cast(prop)->getValues(); - if (values.empty()) { - return {}; - } - - App::Material value = values.front(); - auto dc = value.diffuseColor.asValue(); - auto ac = value.ambientColor.asValue(); - auto sc = value.specularColor.asValue(); - auto ec = value.emissiveColor.asValue(); - - QString data = QString::fromUtf8( - "Diffuse color: [%1, %2, %3]\n" - "Ambient color: [%4, %5, %6]\n" - "Specular color: [%7, %8, %9]\n" - "Emissive color: [%10, %11, %12]\n" - "Shininess: %13\n" - "Transparency: %14" - ) - .arg(dc.red()).arg(dc.green()).arg(dc.blue()) - .arg(ac.red()).arg(ac.green()).arg(ac.blue()) - .arg(sc.red()).arg(sc.green()).arg(sc.blue()) - .arg(ec.red()).arg(ec.green()).arg(ec.blue()) - .arg(toPercent(value.shininess)) - .arg(toPercent(value.transparency)) - ; - - return {data}; -} - -QVariant PropertyMaterialListItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - const std::vector& value = static_cast(prop)->getValues(); - QVariantList variantList; - - for (const auto & it : value) { - Material mat; - mat.diffuseColor = it.diffuseColor.asValue(); - mat.ambientColor = it.ambientColor.asValue(); - mat.specularColor = it.specularColor.asValue(); - mat.emissiveColor = it.emissiveColor.asValue(); - mat.shininess = it.shininess; - mat.transparency = it.transparency; - - variantList << QVariant::fromValue(mat); - } - - return variantList; -} - -void PropertyMaterialListItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return; - } - - // Setting an appearance using the property editor resets the - // per-face appearance - list = list.mid(0, 1); - - QString data; - QTextStream str(&data); - str << "("; - - auto mat = list[0].value(); - App::Color dc; dc.setValue(mat.diffuseColor); - App::Color ac; ac.setValue(mat.ambientColor); - App::Color sc; sc.setValue(mat.specularColor); - App::Color ec; ec.setValue(mat.emissiveColor); - float s = mat.shininess; - float t = mat.transparency; - - QString item = QString::fromLatin1( - "App.Material(" - "DiffuseColor=(%1,%2,%3)," - "AmbientColor=(%4,%5,%6)," - "SpecularColor=(%7,%8,%9)," - "EmissiveColor=(%10,%11,%12)," - "Shininess=(%13)," - "Transparency=(%14)," - ")" - ) - .arg(dc.r, 0, 'f', decimals()) - .arg(dc.g, 0, 'f', decimals()) - .arg(dc.b, 0, 'f', decimals()) - .arg(ac.r, 0, 'f', decimals()) - .arg(ac.g, 0, 'f', decimals()) - .arg(ac.b, 0, 'f', decimals()) - .arg(sc.r, 0, 'f', decimals()) - .arg(sc.g, 0, 'f', decimals()) - .arg(sc.b, 0, 'f', decimals()) - .arg(ec.r, 0, 'f', decimals()) - .arg(ec.g, 0, 'f', decimals()) - .arg(ec.b, 0, 'f', decimals()) - .arg(s, 0, 'f', decimals()) - .arg(t, 0, 'f', decimals()) - ; - str << item << ")"; - - setPropertyValue(data); -} - -QWidget* PropertyMaterialListItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto cb = new Gui::ColorButton(parent); - cb->setDisabled(isReadOnly()); - QObject::connect(cb, &Gui::ColorButton::changed, method); - return cb; -} - -void PropertyMaterialListItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - if (!data.canConvert()) { - return; - } - - QVariantList list = data.toList(); - if (list.isEmpty()) { - return; - } - - if (!list[0].canConvert()) { - return; - } - - // use the diffuse color - auto mat = list[0].value(); - QColor color = mat.diffuseColor; - - auto cb = qobject_cast(editor); - cb->setColor(color); -} - -QVariant PropertyMaterialListItem::editorData(QWidget *editor) const -{ - auto cb = qobject_cast(editor); - QVariant value = data(1, Qt::EditRole); - if (!value.canConvert()) { - return {}; - } - - QVariantList list = value.toList(); - if (list.isEmpty()) { - return {}; - } - - if (!list[0].canConvert()) { - return {}; - } - - // use the diffuse color - auto mat = list[0].value(); - mat.diffuseColor = cb->color(); - list[0] = QVariant::fromValue(mat); - - return list; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFileItem) - -PropertyFileItem::PropertyFileItem() = default; - -QVariant PropertyFileItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - std::string value = static_cast(prop)->getValue(); - return {QString::fromUtf8(value.c_str())}; -} - -void PropertyFileItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); -} - -QVariant PropertyFileItem::toolTip(const App::Property* prop) const -{ - return value(prop); -} - -QWidget* PropertyFileItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto fc = new Gui::FileChooser(parent); - fc->setAutoFillBackground(true); - fc->setDisabled(isReadOnly()); - QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); - return fc; -} - -void PropertyFileItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - const App::Property* prop = getFirstProperty(); - if (const auto propFile = dynamic_cast(prop)) { - std::string filter = propFile->getFilter(); - auto fc = qobject_cast(editor); - if (!filter.empty()) { - fc->setFilter(Base::Tools::fromStdString(filter)); - } - fc->setFileName(data.toString()); - } -} - -QVariant PropertyFileItem::editorData(QWidget *editor) const -{ - auto fc = qobject_cast(editor); - return {fc->fileName()}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPathItem) - -PropertyPathItem::PropertyPathItem() = default; - -QVariant PropertyPathItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - std::string value = static_cast(prop)->getValue().string(); - return {QString::fromUtf8(value.c_str())}; -} - -void PropertyPathItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); -} - -QVariant PropertyPathItem::toolTip(const App::Property* prop) const -{ - return value(prop); -} - -QWidget* PropertyPathItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto fc = new Gui::FileChooser(parent); - fc->setMode(FileChooser::Directory); - fc->setAutoFillBackground(true); - fc->setDisabled(isReadOnly()); - QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); - return fc; -} - -void PropertyPathItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto fc = qobject_cast(editor); - fc->setFileName(data.toString()); -} - -QVariant PropertyPathItem::editorData(QWidget *editor) const -{ - auto fc = qobject_cast(editor); - return {fc->fileName()}; -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyTransientFileItem) - -PropertyTransientFileItem::PropertyTransientFileItem() = default; - -QVariant PropertyTransientFileItem::value(const App::Property* prop) const -{ - assert(prop && prop->isDerivedFrom()); - - std::string value = static_cast(prop)->getValue(); - return {QString::fromUtf8(value.c_str())}; -} - -void PropertyTransientFileItem::setValue(const QVariant& value) -{ - if (hasExpression() || !value.canConvert()) { - return; - } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); -} - -QVariant PropertyTransientFileItem::toolTip(const App::Property* prop) const -{ - return value(prop); -} - -QWidget* PropertyTransientFileItem::createEditor(QWidget* parent, const std::function& method) const -{ - auto fc = new Gui::FileChooser(parent); - fc->setAutoFillBackground(true); - fc->setDisabled(isReadOnly()); - QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); - return fc; -} - -void PropertyTransientFileItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - auto fc = qobject_cast(editor); - fc->setFileName(data.toString()); - - const auto prop = dynamic_cast - (getFirstProperty()); - - if (prop) { - std::string filter = prop->getFilter(); - if (!filter.empty()) { - fc->setFilter(QString::fromStdString(filter)); - } - } -} - -QVariant PropertyTransientFileItem::editorData(QWidget *editor) const -{ - auto fc = qobject_cast(editor); - return {fc->fileName()}; -} - -// --------------------------------------------------------------- - -LinkSelection::LinkSelection(App::SubObjectT link) - : link(std::move(link)) -{ -} - -LinkSelection::~LinkSelection() = default; - -void LinkSelection::select() -{ - auto sobj = link.getSubObject(); - if(!sobj) { - QMessageBox::critical(getMainWindow(), tr("Error"), tr("Object not found")); - return; - } - Gui::Selection().selStackPush(); - Gui::Selection().clearSelection(); - Gui::Selection().addSelection(link.getDocumentName().c_str(), - link.getObjectName().c_str(), - link.getSubName().c_str()); - this->deleteLater(); -} - -// --------------------------------------------------------------- - -LinkLabel::LinkLabel (QWidget * parent, const App::Property *prop) - : QWidget(parent), objProp(prop), dlg(nullptr) -{ - auto layout = new QHBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(1); - - label = new QLabel(this); - label->setAutoFillBackground(true); - label->setTextFormat(Qt::RichText); - // Below is necessary for the hytperlink to be clickable without losing focus - label->setTextInteractionFlags(Qt::TextBrowserInteraction); - layout->addWidget(label); - - editButton = new QPushButton(QLatin1String("..."), this); -#if defined (Q_OS_MACOS) - editButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // layout size from QMacStyle was not correct -#endif - editButton->setToolTip(tr("Change the linked object")); - layout->addWidget(editButton); - - this->setFocusPolicy(Qt::StrongFocus); - this->setFocusProxy(label); - - // setLayout(layout); - - connect(label, &QLabel::linkActivated, - this, &LinkLabel::onLinkActivated); - connect(editButton, &QPushButton::clicked, - this, &LinkLabel::onEditClicked); -} - -LinkLabel::~LinkLabel() = default; - -void LinkLabel::updatePropertyLink() -{ - QString text; - auto owner = objProp.getObject(); - auto prop = Base::freecad_dynamic_cast(objProp.getProperty()); - - link = QVariant(); - - if(owner && prop) { - auto links = DlgPropertyLink::getLinksFromProperty(prop); - if(links.size() == 1) { - auto &sobj = links.front(); - link = QVariant::fromValue(sobj); - QString linkcolor = QApplication::palette().color(QPalette::Link).name(); - text = QString::fromLatin1( - "" - "

" - "%5" - "

" - ) - .arg(QLatin1String(sobj.getDocumentName().c_str()), - QLatin1String(sobj.getObjectName().c_str()), - QString::fromUtf8(sobj.getSubName().c_str()), - linkcolor, - DlgPropertyLink::formatObject( - owner->getDocument(), sobj.getObject(), sobj.getSubName().c_str())); - } else if (!links.empty()) { - text = DlgPropertyLink::formatLinks(owner->getDocument(), links); - } - } - label->setText(text); -} - -QVariant LinkLabel::propertyLink() const -{ - return link; -} - -void LinkLabel::onLinkActivated (const QString& s) -{ - Q_UNUSED(s); - auto select = new LinkSelection(qvariant_cast(link)); - QTimer::singleShot(50, select, &LinkSelection::select); // NOLINT -} - -void LinkLabel::onEditClicked () -{ - if (!dlg) { - dlg = new DlgPropertyLink(this); - dlg->init(objProp,true); - connect(dlg, &DlgPropertyLink::accepted, this, &LinkLabel::onLinkChanged); - } - else { - dlg->init(objProp,false); - } - - dlg->show(); -} - -void LinkLabel::onLinkChanged() { - if(dlg) { - auto links = dlg->currentLinks(); - if(links != dlg->originalLinks()) { - link = QVariant::fromValue(links); - Q_EMIT linkChanged(link); - updatePropertyLink(); - } - } -} - -void LinkLabel::resizeEvent(QResizeEvent* e) -{ - editButton->setFixedWidth(e->size().height()); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkItem) - -PropertyLinkItem::PropertyLinkItem() = default; - -QVariant PropertyLinkItem::toString(const QVariant& prop) const -{ - QString res; - if(!propertyItems.empty()) { - App::DocumentObjectT owner(propertyItems[0]); - res = DlgPropertyLink::formatLinks(owner.getDocument(), - qvariant_cast >(prop)); - } - return res; -} - -QVariant PropertyLinkItem::data(int column, int role) const { - if(!propertyItems.empty() && column == 1 - && (role == Qt::ForegroundRole || role == Qt::ToolTipRole)) - { - if (auto propLink = dynamic_cast(propertyItems[0])) { - if (role==Qt::ForegroundRole && propLink->checkRestore() > 1) { - return QVariant::fromValue(QColor(0xff, 0, 0)); // NOLINT - } - if (role == Qt::ToolTipRole) { - if (auto xlink = dynamic_cast(propertyItems[0])) { - const char *filePath = xlink->getFilePath(); - if (filePath && filePath[0]) { - return QVariant::fromValue(QString::fromUtf8(filePath)); - } - } - } - } - } - - return PropertyItem::data(column,role); -} - -QVariant PropertyLinkItem::value(const App::Property* prop) const -{ - auto propLink = Base::freecad_dynamic_cast(prop); - if (!propLink) { - return {}; - } - - auto links = DlgPropertyLink::getLinksFromProperty(propLink); - if (links.empty()) { - return {}; - } - - return QVariant::fromValue(links); -} - -void PropertyLinkItem::setValue(const QVariant& value) -{ - auto links = qvariant_cast >(value); - setPropertyValue(DlgPropertyLink::linksToPython(links)); -} - -QWidget* PropertyLinkItem::createEditor(QWidget* parent, const std::function& method) const -{ - if (propertyItems.empty()) { - return nullptr; - } - auto ll = new LinkLabel(parent, propertyItems.front()); - ll->setAutoFillBackground(true); - ll->setDisabled(isReadOnly()); - QObject::connect(ll, &LinkLabel::linkChanged, method); - return ll; -} - -void PropertyLinkItem::setEditorData(QWidget *editor, const QVariant& data) const -{ - (void)data; - auto ll = dynamic_cast(editor); - return ll->updatePropertyLink(); -} - -QVariant PropertyLinkItem::editorData(QWidget *editor) const -{ - auto ll = dynamic_cast(editor); - return ll->propertyLink(); -} - -// -------------------------------------------------------------------- - -PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkListItem) - -PropertyLinkListItem::PropertyLinkListItem() = default; - -PropertyItemEditorFactory::PropertyItemEditorFactory() = default; - -PropertyItemEditorFactory::~PropertyItemEditorFactory() = default; - -QWidget * PropertyItemEditorFactory::createEditor (int /*type*/, QWidget * /*parent*/) const -{ - // do not allow to create any editor widgets because we do that in subclasses of PropertyItem - return nullptr; -} - -QByteArray PropertyItemEditorFactory::valuePropertyName (int /*type*/) const -{ - // do not allow to set properties because we do that in subclasses of PropertyItem - return ""; -} -// NOLINTEND(cppcoreguidelines-pro-*,cppcoreguidelines-prefer-member-initializer) - -#include "moc_PropertyItem.cpp" - +/*************************************************************************** + * Copyright (c) 2004 Werner Mayer * + * * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "PropertyItem.h" +#include "PropertyView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NOLINTBEGIN(cppcoreguidelines-pro-*,cppcoreguidelines-prefer-member-initializer) +using namespace Gui::PropertyEditor; +using namespace Gui::Dialog; + +namespace +{ +constexpr const int lowPrec = 2; +constexpr const int highPrec = 16; + +int toPercent(float value) +{ + return static_cast(100 * value); // NOLINT +} + +float fromPercent(int value) +{ + return static_cast(value) / 100.0F; // NOLINT +} + +} // namespace + +PropertyItemFactory& PropertyItemFactory::instance() +{ + static PropertyItemFactory inst; + return inst; +} + +PropertyItem* PropertyItemFactory::createPropertyItem(const char* sName) const +{ + return static_cast(Produce(sName)); +} + +// ---------------------------------------------------- + +QVariant PropertyItemAttorney::toString(PropertyItem* item, const QVariant& value) +{ + return item->toString(value); +} + +// ---------------------------------------------------- + +Q_DECLARE_METATYPE(Py::Object) // NOLINT + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyItem) + +PropertyItem::PropertyItem() + : parentItem(nullptr) + , readonly(false) + , precision(Base::UnitsApi::getDecimals()) + , linked(false) + , expanded(false) +{ + setAutoApply(true); +} + +PropertyItem::~PropertyItem() +{ + qDeleteAll(childItems); +} + +void PropertyItem::initialize() +{} + +void PropertyItem::reset() +{ + qDeleteAll(childItems); + childItems.clear(); +} + +void PropertyItem::onChange() +{ + if (hasExpression()) { + for (auto child : std::as_const(childItems)) { + if (child && child->hasExpression()) { + child->setExpression(std::shared_ptr()); + } + } + for (auto item = parentItem; item; item = item->parentItem) { + if (item->hasExpression()) { + item->setExpression(std::shared_ptr()); + } + } + } +} + +bool PropertyItem::hasAnyExpression() const +{ + if (ExpressionBinding::hasExpression()) { + return true; + } + if (parentItem) { + return parentItem->hasExpression(); + } + return false; +} + +void PropertyItem::setPropertyData(const std::vector& items) +{ + // if we have a single property we can bind it for expression handling + if (items.size() == 1) { + const App::Property& prop = *items.front(); + + try { + // Check for 'DocumentObject' as parent because otherwise 'ObjectIdentifier' raises an + // exception + auto* docObj = Base::freecad_dynamic_cast(prop.getContainer()); + if (docObj && !docObj->isReadOnly(&prop)) { + App::ObjectIdentifier id(prop); + std::vector paths; + prop.getPaths(paths); + + // there may be no paths available in this property (for example an empty constraint + // list) + if (id.getProperty() && !paths.empty()) { + bind(id); + } + } + } + // it may happen that setting properties is not possible + catch (...) { + } + } + + propertyItems = items; + updateData(); + this->initialize(); +} + +void PropertyItem::updateData() +{ + bool ro = true; + for (auto it : propertyItems) { + App::PropertyContainer* parent = it->getContainer(); + if (parent) { + ro &= (parent->isReadOnly(it) || it->testStatus(App::Property::ReadOnly)); + } + } + this->setReadOnly(ro); +} + +const std::vector& PropertyItem::getPropertyData() const +{ + return propertyItems; +} + +bool PropertyItem::hasProperty(const App::Property* prop) const +{ + auto it = std::find(propertyItems.begin(), propertyItems.end(), prop); + return (it != propertyItems.end()); +} + +void PropertyItem::assignProperty(const App::Property* prop) +{ + Q_UNUSED(prop) +} + +bool PropertyItem::removeProperty(const App::Property* prop) +{ + auto it = std::find(propertyItems.begin(), propertyItems.end(), prop); + if (it != propertyItems.end()) { + propertyItems.erase(it); + } + + return propertyItems.empty(); +} + +App::Property* PropertyItem::getFirstProperty() +{ + if (propertyItems.empty()) { + return nullptr; + } + return propertyItems.front(); +} + +const App::Property* PropertyItem::getFirstProperty() const +{ + if (propertyItems.empty()) { + return nullptr; + } + return propertyItems.front(); +} + +void PropertyItem::setParent(PropertyItem* parent) +{ + parentItem = parent; +} + +PropertyItem* PropertyItem::parent() const +{ + return parentItem; +} + +void PropertyItem::appendChild(PropertyItem* item) +{ + childItems.append(item); +} + +void PropertyItem::insertChild(int index, PropertyItem* child) +{ + childItems.insert(index, child); +} + +/*! + * \brief PropertyItem::removeChildren + * Deletes the children in the range of [from, to] + */ +void PropertyItem::removeChildren(int from, int to) +{ + int count = to - from + 1; + for (int i = 0; i < count; i++) { + PropertyItem* child = childItems.takeAt(from); + delete child; + } +} + +void PropertyItem::moveChild(int from, int to) +{ + childItems.move(from, to); +} + +/*! + * \brief PropertyItem::takeChild + * Removes the child at index row but doesn't delete it + */ +PropertyItem* PropertyItem::takeChild(int row) +{ + PropertyItem* child = childItems.takeAt(row); + child->setParent(nullptr); + return child; +} + +PropertyItem* PropertyItem::child(int row) +{ + return childItems.value(row); +} + +int PropertyItem::childCount() const +{ + return childItems.count(); +} + +int PropertyItem::columnCount() const +{ + return 2; +} + +void PropertyItem::setReadOnly(bool ro) +{ + readonly = ro; + for (auto it : std::as_const(childItems)) { + it->setReadOnly(ro); + } +} + +bool PropertyItem::isReadOnly() const +{ + return readonly; +} + +void PropertyItem::setLinked(bool value) +{ + linked = value; + for (auto it : std::as_const(childItems)) { + it->setLinked(value); + } +} + +bool PropertyItem::isLinked() const +{ + return linked; +} + +void PropertyItem::setExpanded(bool enable) +{ + expanded = enable; +} + +bool PropertyItem::isExpanded() const +{ + return expanded; +} + +bool PropertyItem::testStatus(App::Property::Status pos) const +{ + std::vector::const_iterator it; + for (it = propertyItems.begin(); it != propertyItems.end(); ++it) { + if ((*it)->testStatus(pos)) { + return true; + } + } + return false; +} + +void PropertyItem::setDecimals(int prec) +{ + precision = prec; +} + +int PropertyItem::decimals() const +{ + return precision; +} + +QVariant PropertyItem::displayName() const +{ + return {displayText}; +} + +QVariant PropertyItem::toolTip(const App::Property* prop) const +{ + QString str = QApplication::translate("App::Property", prop->getDocumentation()); + return {str}; +} + +QVariant PropertyItem::decoration(const QVariant& value) const +{ + Q_UNUSED(value) + return {}; +} + +QString PropertyItem::asNone(const Py::Object& pyobj) const +{ + Q_UNUSED(pyobj) + return QString::fromUtf8(""); +} + +QString PropertyItem::asString(const Py::Object& pyobj) const +{ + return QString::fromStdString(pyobj.as_string()); +} + +QString PropertyItem::asSequence(const Py::Object& pyobj) const +{ + std::ostringstream ss; + ss << '['; + Py::Sequence seq(pyobj); + bool first = true; + Py_ssize_t i = 0; + for (i = 0; i < 2 && i < seq.size(); ++i) { + if (first) { + first = false; + } + else { + ss << ", "; + } + ss << Py::Object(seq[i]).as_string(); + } + + if (i < seq.size()) { + ss << "..."; + } + ss << ']'; + return QString::fromUtf8(ss.str().c_str()); +} + +QString PropertyItem::asMapping(const Py::Object& pyobj) const +{ + std::ostringstream ss; + ss << '{'; + Py::Mapping map(pyobj); + bool first = true; + auto it = map.begin(); + for (int i = 0; i < 2 && it != map.end(); ++it, ++i) { + if (first) { + first = false; + } + else { + ss << ", "; + } + const auto& v = *it; + ss << Py::Object(v.first).as_string() << ':' << Py::Object(v.second).as_string(); + } + + if (it != map.end()) { + ss << "..."; + } + ss << '}'; + return QString::fromUtf8(ss.str().c_str()); +} + +QString PropertyItem::toString(const Py::Object& pyobj) const +{ + if (pyobj.isNone()) { + return asNone(pyobj); + } + if (pyobj.isSequence()) { + return asSequence(pyobj); + } + if (pyobj.isMapping()) { + return asMapping(pyobj); + } + + return asString(pyobj); +} + +QVariant PropertyItem::toString(const QVariant& prop) const +{ + if (prop != QVariant() || propertyItems.size() != 1) { + return prop; + } + + std::ostringstream ss; + Base::PyGILStateLocker lock; + try { + Py::Object pyobj(propertyItems[0]->getPyObject(), true); + return toString(pyobj); + } + catch (Py::Exception&) { + Base::PyException e; + ss.str(""); + ss << "ERR: " << e.what(); + } + catch (Base::Exception& e) { + ss.str(""); + ss << "ERR: " << e.what(); + } + catch (std::exception& e) { + ss.str(""); + ss << "ERR: " << e.what(); + } + catch (...) { + ss.str(""); + ss << "ERR!"; + } + + return {QString::fromUtf8(ss.str().c_str())}; +} + +QVariant PropertyItem::value(const App::Property* /*prop*/) const +{ + return {}; +} + +void PropertyItem::setValue(const QVariant& /*value*/) +{} + +QWidget* PropertyItem::createEditor(QWidget* /*parent*/, + const std::function& /*method*/) const +{ + return nullptr; +} + +void PropertyItem::setEditorData(QWidget* /*editor*/, const QVariant& /*data*/) const +{} + +QVariant PropertyItem::editorData(QWidget* /*editor*/) const +{ + return {}; +} + +QWidget* PropertyItem::createExpressionEditor(QWidget* parent, + const std::function& method) const +{ + if (!isBound()) { + return nullptr; + } + auto le = new ExpLineEdit(parent, true); + le->setFrame(false); + le->setReadOnly(true); + QObject::connect(le, &ExpLineEdit::textChanged, method); + le->bind(getPath()); + le->setAutoApply(autoApply()); + return le; +} + +void PropertyItem::setExpressionEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + if (le) { + le->setText(data.toString()); + } +} + +QVariant PropertyItem::expressionEditorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + if (le) { + return {le->text()}; + } + return {}; +} + +PropertyEditorWidget* PropertyItem::createPropertyEditorWidget(QWidget* parent) const +{ + auto editor = new PropertyEditorWidget(parent); + connect(editor, &PropertyEditorWidget::buttonClick, this, [this]() { + const auto& props = this->getPropertyData(); + if (!props.empty() && props[0]->getName() && props[0]->testStatus(App::Property::UserEdit) + && props[0]->getContainer()) { + props[0]->getContainer()->editProperty(props[0]->getName()); + } + }); + return editor; +} + +QString PropertyItem::propertyName() const +{ + if (propName.isEmpty()) { + return QLatin1String(QT_TRANSLATE_NOOP("App::Property", "")); + } + return propName; +} + +void PropertyItem::setPropertyName(const QString& name, const QString& realName) +{ + if (realName.size()) { + propName = realName; + } + else { + propName = name; + } + + setObjectName(propName); + + QString display; + bool upper = false; + for (auto&& i : name) { + if (i.isUpper() && !display.isEmpty()) { + // if there is a sequence of capital letters do not insert spaces + if (!upper) { + QChar last = display.at(display.length() - 1); + if (!last.isSpace()) { + display += QLatin1String(" "); + } + } + } + upper = i.isUpper(); + display += i; + } + + propName = display; + + QString str = QApplication::translate("App::Property", propName.toUtf8()); + displayText = str; +} + +void PropertyItem::setPropertyValue(const QString& value) +{ + // Construct command for property assignment in one go, in case of any + // intermediate changes caused by property change that may potentially + // invalidate the current property array. + std::ostringstream ss; + for (auto prop : propertyItems) { + App::PropertyContainer* parent = prop->getContainer(); + if (!parent || parent->isReadOnly(prop) || prop->testStatus(App::Property::ReadOnly)) { + continue; + } + + if (parent->isDerivedFrom(App::Document::getClassTypeId())) { + auto doc = static_cast(parent); + ss << "FreeCAD.getDocument('" << doc->getName() << "')."; + } + else if (parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + auto obj = static_cast(parent); + App::Document* doc = obj->getDocument(); + ss << "FreeCAD.getDocument('" << doc->getName() << "').getObject('" + << obj->getNameInDocument() << "')."; + } + else if (parent->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + App::DocumentObject* obj = + static_cast(parent)->getObject(); + App::Document* doc = obj->getDocument(); + ss << "FreeCADGui.getDocument('" << doc->getName() << "').getObject('" + << obj->getNameInDocument() << "')."; + } + else { + continue; + } + + ss << parent->getPropertyPrefix() << prop->getName() << " = " << value.toUtf8().constData() + << '\n'; + } + + std::string cmd = ss.str(); + if (cmd.empty()) { + return; + } + + try { + Gui::Command::runCommand(Gui::Command::App, cmd.c_str()); + } + catch (Base::PyException& e) { + e.ReportException(); + Base::Console().Error("Stack Trace: %s\n", e.getStackTrace().c_str()); + } + catch (Base::Exception& e) { + e.ReportException(); + } + catch (...) { + Base::Console().Error("Unknown C++ exception in PropertyItem::setPropertyValue thrown\n"); + } +} + +QVariant PropertyItem::dataProperty(int role) const +{ + if (role == Qt::ForegroundRole && linked) { + return QVariant::fromValue(QColor(0x20, 0xaa, 0x20)); // NOLINT + } + + if (role == Qt::BackgroundRole || role == Qt::ForegroundRole) { + if (PropertyView::showAll() && propertyItems.size() == 1 + && propertyItems.front()->testStatus(App::Property::PropDynamic) + && !propertyItems.front()->testStatus(App::Property::LockDynamic)) { + return role == Qt::BackgroundRole + ? QVariant::fromValue(QColor(0xFF, 0xFF, 0x99)) // NOLINT + : QVariant::fromValue(QColor(0, 0, 0)); + } + return {}; + } + if (role == Qt::DisplayRole) { + return displayName(); + } + // no properties set + if (propertyItems.empty()) { + return {}; + } + if (role == Qt::ToolTipRole) { + QString type = + QString::fromLatin1("Type: %1\nName: %2") + .arg(QString::fromLatin1(propertyItems[0]->getTypeId().getName()), objectName()); + + QString doc = PropertyItem::toolTip(propertyItems[0]).toString(); + if (doc.isEmpty()) { + doc = toolTip(propertyItems[0]).toString(); + } + if (doc.size()) { + return type + QLatin1String("\n\n") + doc; + } + return type; + } + + return {}; +} + +QVariant PropertyItem::dataValue(int role) const +{ + // no properties set + if (propertyItems.empty()) { + PropertyItem* parent = this->parent(); + if (!parent || !parent->parent()) { + return {}; + } + if (role == Qt::EditRole) { + return parent->property(qPrintable(objectName())); + } + if (role == Qt::DecorationRole) { + QVariant val = parent->property(qPrintable(objectName())); + return decoration(val); + } + if (role == Qt::DisplayRole) { + QVariant val = parent->property(qPrintable(objectName())); + return toString(val); + } + if (role == Qt::ForegroundRole) { + if (hasExpression()) { + return QVariant::fromValue(QApplication::palette().color(QPalette::Link)); + } + return {}; + } + + return {}; + } + if (role == Qt::EditRole) { + return value(propertyItems[0]); + } + if (role == Qt::DecorationRole) { + return decoration(value(propertyItems[0])); + } + if (role == Qt::DisplayRole) { + return toString(value(propertyItems[0])); + } + if (role == Qt::ToolTipRole) { + return toolTip(propertyItems[0]); + } + if (role == Qt::ForegroundRole) { + if (hasExpression()) { + return QVariant::fromValue(QApplication::palette().color(QPalette::Link)); + } + return {}; + } + + return {}; +} + +QVariant PropertyItem::data(int column, int role) const +{ + // property name + if (column == 0) { + return dataProperty(role); + } + + return dataValue(role); +} + +bool PropertyItem::setData(const QVariant& value) +{ + // This is the basic mechanism to set the value to + // a property and if no property is set for this item + // it delegates it to its parent which sets then the + // property or delegates again to its parent... + if (propertyItems.empty()) { + PropertyItem* parent = this->parent(); + if (!parent || !parent->parent() || hasAnyExpression()) { + return false; + } + + parent->setProperty(qPrintable(objectName()), value); + return true; + } + + setValue(value); + return true; +} + +Qt::ItemFlags PropertyItem::flags(int column) const +{ + Qt::ItemFlags basicFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + if (column == 1 && !isReadOnly()) { + return basicFlags | Qt::ItemIsEditable; + } + + return basicFlags; +} + +int PropertyItem::row() const +{ + if (parentItem) { + return parentItem->childItems.indexOf(const_cast(this)); // NOLINT + } + + return 0; +} + +void PropertyItem::bind(const App::ObjectIdentifier& _path) +{ + Gui::ExpressionBinding::bind(_path); + propertyBound(); +} + +void PropertyItem::bind(const App::Property& prop) +{ + Gui::ExpressionBinding::bind(prop); + propertyBound(); +} + +QString PropertyItem::expressionAsString() const +{ + if (hasExpression()) { + try { + std::unique_ptr result(getExpression()->eval()); + return QString::fromStdString(result->toString()); + } + catch (const Base::Exception& e) { + e.ReportException(); + } + } + + return {}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringItem) + +PropertyStringItem::PropertyStringItem() = default; + +QVariant PropertyStringItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + std::string value = static_cast(prop)->getValue(); + return {QString::fromUtf8(value.c_str())}; +} + +void PropertyStringItem::setValue(const QVariant& value) +{ + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + QString val = value.toString(); + val = QString::fromUtf8(Base::InterpreterSingleton::strToPython(val.toUtf8()).c_str()); + QString data = QString::fromLatin1("\"%1\"").arg(val); + setPropertyValue(data); + } +} + +QWidget* PropertyStringItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto le = new ExpLineEdit(parent); + le->setFrame(false); + le->setReadOnly(isReadOnly()); + QObject::connect(le, &ExpLineEdit::textChanged, method); + if (isBound()) { + le->bind(getPath()); + le->setAutoApply(autoApply()); + } + + return le; +} + +void PropertyStringItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + le->setText(data.toString()); +} + +QVariant PropertyStringItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + return {le->text()}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFontItem) + +PropertyFontItem::PropertyFontItem() = default; + +QVariant PropertyFontItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + std::string value = static_cast(prop)->getValue(); + return {QString::fromUtf8(value.c_str())}; +} + +void PropertyFontItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + + QString val = value.toString(); + QString data = QString::fromLatin1("\"%1\"").arg(val); + setPropertyValue(data); +} + +QWidget* PropertyFontItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto cb = new QComboBox(parent); + cb->setFrame(false); + cb->setDisabled(isReadOnly()); +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QObject::connect(cb, qOverload(&QComboBox::activated), method); +#else + QObject::connect(cb, &QComboBox::textActivated, method); +#endif + return cb; +} + +void PropertyFontItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto cb = qobject_cast(editor); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QStringList familyNames = QFontDatabase().families(QFontDatabase::Any); +#else + QStringList familyNames = QFontDatabase::families(QFontDatabase::Any); +#endif + cb->addItems(familyNames); + int index = familyNames.indexOf(data.toString()); + cb->setCurrentIndex(index); +} + +QVariant PropertyFontItem::editorData(QWidget* editor) const +{ + auto cb = qobject_cast(editor); + return {cb->currentText()}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertySeparatorItem) + +QWidget* PropertySeparatorItem::createEditor(QWidget* parent, + const std::function& method) const +{ + Q_UNUSED(parent); + Q_UNUSED(method); + return nullptr; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerItem) + +PropertyIntegerItem::PropertyIntegerItem() = default; + +QVariant PropertyIntegerItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + int value = (int)static_cast(prop)->getValue(); + return {value}; +} + +void PropertyIntegerItem::setValue(const QVariant& value) +{ + // if the item has an expression it issues the python code + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + int val = value.toInt(); + QString data = QString::fromLatin1("%1").arg(val); + setPropertyValue(data); + } +} + +QWidget* PropertyIntegerItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto sb = new Gui::IntSpinBox(parent); + sb->setFrame(false); + sb->setReadOnly(isReadOnly()); + QObject::connect(sb, qOverload(&Gui::IntSpinBox::valueChanged), method); + + if (isBound()) { + sb->bind(getPath()); + sb->setAutoApply(autoApply()); + } + + return sb; +} + +void PropertyIntegerItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto sb = qobject_cast(editor); + sb->setRange(INT_MIN, INT_MAX); + sb->setValue(data.toInt()); +} + +QVariant PropertyIntegerItem::editorData(QWidget* editor) const +{ + auto sb = qobject_cast(editor); + return {sb->value()}; +} + +QVariant PropertyIntegerItem::toString(const QVariant& v) const +{ + QString string(PropertyItem::toString(v).toString()); + + if (hasExpression()) { + string += + QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + + return {string}; +} + + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerConstraintItem) + +PropertyIntegerConstraintItem::PropertyIntegerConstraintItem() = default; + +QVariant PropertyIntegerConstraintItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + int value = (int)static_cast(prop)->getValue(); + return {value}; +} + +void PropertyIntegerConstraintItem::setValue(const QVariant& value) +{ + // if the item has an expression it issues the python code + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + int val = value.toInt(); + QString data = QString::fromLatin1("%1").arg(val); + setPropertyValue(data); + } +} + +QWidget* PropertyIntegerConstraintItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto sb = new Gui::IntSpinBox(parent); + sb->setFrame(false); + sb->setReadOnly(isReadOnly()); + QObject::connect(sb, qOverload(&Gui::IntSpinBox::valueChanged), method); + + if (isBound()) { + sb->bind(getPath()); + sb->setAutoApply(autoApply()); + } + + return sb; +} + +void PropertyIntegerConstraintItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + const auto prop = static_cast(getFirstProperty()); + + const App::PropertyIntegerConstraint::Constraints* c = nullptr; + if (prop) { + c = prop->getConstraints(); + } + + auto sb = qobject_cast(editor); + if (c) { + sb->setMinimum(int(c->LowerBound)); + sb->setMaximum(int(c->UpperBound)); + sb->setSingleStep(int(c->StepSize)); + } + else { + sb->setMinimum(min); + sb->setMaximum(max); + sb->setSingleStep(steps); + } + + sb->setValue(data.toInt()); +} + +QVariant PropertyIntegerConstraintItem::editorData(QWidget* editor) const +{ + auto sb = qobject_cast(editor); + return {sb->value()}; +} + +QVariant PropertyIntegerConstraintItem::toString(const QVariant& v) const +{ + QString string(PropertyItem::toString(v).toString()); + + if (hasExpression()) { + string += + QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + + return {string}; +} + + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatItem) + +PropertyFloatItem::PropertyFloatItem() = default; + +QVariant PropertyFloatItem::toString(const QVariant& prop) const +{ + double value = prop.toDouble(); + QString data = QLocale().toString(value, 'f', decimals()); + + if (hasExpression()) { + data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + + return {data}; +} + +QVariant PropertyFloatItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + double value = static_cast(prop)->getValue(); + return {value}; +} + +void PropertyFloatItem::setValue(const QVariant& value) +{ + // if the item has an expression it issues the python code + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + double val = value.toDouble(); + QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); + setPropertyValue(data); + } +} + +QWidget* PropertyFloatItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto sb = new Gui::DoubleSpinBox(parent); + sb->setFrame(false); + sb->setDecimals(decimals()); + sb->setReadOnly(isReadOnly()); + QObject::connect(sb, qOverload(&Gui::DoubleSpinBox::valueChanged), method); + + if (isBound()) { + sb->bind(getPath()); + sb->setAutoApply(autoApply()); + } + + return sb; +} + +void PropertyFloatItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto sb = qobject_cast(editor); + sb->setRange((double)INT_MIN, (double)INT_MAX); + sb->setValue(data.toDouble()); +} + +QVariant PropertyFloatItem::editorData(QWidget* editor) const +{ + auto sb = qobject_cast(editor); + return {sb->value()}; +} + +// -------------------------------------------------------------------- + + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitItem) + +PropertyUnitItem::PropertyUnitItem() = default; + +QVariant PropertyUnitItem::toString(const QVariant& prop) const +{ + const Base::Quantity& unit = prop.value(); + QString string = unit.getUserString(); + if (hasExpression()) { + string += + QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + + return {string}; +} + +QVariant PropertyUnitItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + Base::Quantity value = static_cast(prop)->getQuantityValue(); + return QVariant::fromValue(value); +} + +void PropertyUnitItem::setValue(const QVariant& value) +{ + // if the item has an expression it handles the python code + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + const Base::Quantity& val = value.value(); + + Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); + QString unit = Base::UnitsApi::toString(val, format); + setPropertyValue(unit); + } +} + +QWidget* PropertyUnitItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto infield = new Gui::QuantitySpinBox(parent); + infield->setFrame(false); + infield->setMinimumHeight(0); + infield->setReadOnly(isReadOnly()); + + // if we are bound to an expression we need to bind it to the input field + if (isBound()) { + infield->bind(getPath()); + infield->setAutoApply(autoApply()); + } + + QObject::connect(infield, qOverload(&Gui::QuantitySpinBox::valueChanged), method); + return infield; +} + +void PropertyUnitItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + const Base::Quantity& value = data.value(); + + auto infield = qobject_cast(editor); + infield->setValue(value); + infield->selectAll(); +} + +QVariant PropertyUnitItem::editorData(QWidget* editor) const +{ + auto infield = qobject_cast(editor); + Base::Quantity value = infield->value(); + return QVariant::fromValue(value); +} + +// -------------------------------------------------------------------- + + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitConstraintItem) + +PropertyUnitConstraintItem::PropertyUnitConstraintItem() = default; + +void PropertyUnitConstraintItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + const Base::Quantity& value = data.value(); + + auto infield = qobject_cast(editor); + infield->setValue(value); + infield->selectAll(); + + const auto prop = static_cast(getFirstProperty()); + + const App::PropertyQuantityConstraint::Constraints* c = nullptr; + if (prop) { + c = prop->getConstraints(); + } + + if (c) { + infield->setMinimum(c->LowerBound); + infield->setMaximum(c->UpperBound); + infield->setSingleStep(c->StepSize); + } + else { + infield->setMinimum(min); + infield->setMaximum(max); + infield->setSingleStep(steps); + } +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatConstraintItem) + +PropertyFloatConstraintItem::PropertyFloatConstraintItem() = default; + +QVariant PropertyFloatConstraintItem::toString(const QVariant& prop) const +{ + double value = prop.toDouble(); + QString data = QLocale().toString(value, 'f', decimals()); + return {data}; +} + +QVariant PropertyFloatConstraintItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + double value = static_cast(prop)->getValue(); + return {value}; +} + +void PropertyFloatConstraintItem::setValue(const QVariant& value) +{ + // if the item has an expression it issues the python code + if (!hasExpression()) { + if (!value.canConvert()) { + return; + } + double val = value.toDouble(); + QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); + setPropertyValue(data); + } +} + +QWidget* PropertyFloatConstraintItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto sb = new Gui::DoubleSpinBox(parent); + sb->setDecimals(decimals()); + sb->setFrame(false); + sb->setReadOnly(isReadOnly()); + QObject::connect(sb, qOverload(&Gui::DoubleSpinBox::valueChanged), method); + + if (isBound()) { + sb->bind(getPath()); + sb->setAutoApply(autoApply()); + } + + return sb; +} + +void PropertyFloatConstraintItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + const auto prop = static_cast(getFirstProperty()); + + const App::PropertyFloatConstraint::Constraints* c = nullptr; + if (prop) { + c = prop->getConstraints(); + } + + auto sb = qobject_cast(editor); + if (c) { + sb->setMinimum(c->LowerBound); + sb->setMaximum(c->UpperBound); + sb->setSingleStep(c->StepSize); + } + else { + sb->setMinimum(min); + sb->setMaximum(max); + sb->setSingleStep(steps); + } + + sb->setValue(data.toDouble()); +} + +QVariant PropertyFloatConstraintItem::editorData(QWidget* editor) const +{ + auto sb = qobject_cast(editor); + return {sb->value()}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPrecisionItem) + +PropertyPrecisionItem::PropertyPrecisionItem() +{ + setDecimals(highPrec); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyAngleItem) + +PropertyAngleItem::PropertyAngleItem() = default; + +void PropertyAngleItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + PropertyUnitConstraintItem::setEditorData(editor, data); +} + +QVariant PropertyAngleItem::toString(const QVariant& prop) const +{ + return PropertyUnitConstraintItem::toString(prop); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyBoolItem) + +PropertyBoolItem::PropertyBoolItem() = default; + +QVariant PropertyBoolItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + bool value = static_cast(prop)->getValue(); + return {value}; +} + +void PropertyBoolItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + bool val = value.toBool(); + QString data = (val ? QLatin1String("True") : QLatin1String("False")); + setPropertyValue(data); +} + +QWidget* PropertyBoolItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto cb = new QComboBox(parent); + cb->setFrame(false); + cb->addItem(QLatin1String("false")); + cb->addItem(QLatin1String("true")); + cb->setDisabled(isReadOnly()); + QObject::connect(cb, qOverload(&QComboBox::activated), method); + return cb; +} + +void PropertyBoolItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto cb = qobject_cast(editor); + cb->setCurrentIndex(cb->findText(data.toString())); +} + +QVariant PropertyBoolItem::editorData(QWidget* editor) const +{ + auto cb = qobject_cast(editor); + return {cb->currentText()}; +} + +// --------------------------------------------------------------- + +namespace Gui::PropertyEditor +{ +class VectorLineEdit: public Gui::ExpLineEdit +{ + int decimals; + +public: + explicit VectorLineEdit(int decimals, QWidget* parent = nullptr, bool expressionOnly = false) + : Gui::ExpLineEdit(parent, expressionOnly) + , decimals(decimals) + {} + + bool apply(const std::string& propName) override + { + // NOLINTNEXTLINE + if (!ExpressionBinding::apply(propName)) { // clazy:exclude=skipped-base-method + QVariant data = property("coords"); + if (data.canConvert()) { + const Base::Vector3d& value = data.value(); + + QString str = QString::fromLatin1("(%1, %2, %3)") + .arg(value.x, 0, 'f', decimals) + .arg(value.y, 0, 'f', decimals) + .arg(value.z, 0, 'f', decimals); + + Gui::Command::doCommand(Gui::Command::Doc, + "%s = %s", + propName.c_str(), + str.toLatin1().constData()); + return true; + } + } + + return false; + } +}; +} // namespace Gui::PropertyEditor + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorItem) + +PropertyVectorItem::PropertyVectorItem() +{ + m_x = static_cast(PropertyFloatItem::create()); + m_x->setParent(this); + m_x->setPropertyName(QLatin1String("x")); + this->appendChild(m_x); + m_y = static_cast(PropertyFloatItem::create()); + m_y->setParent(this); + m_y->setPropertyName(QLatin1String("y")); + this->appendChild(m_y); + m_z = static_cast(PropertyFloatItem::create()); + m_z->setParent(this); + m_z->setPropertyName(QLatin1String("z")); + this->appendChild(m_z); +} + +QVariant PropertyVectorItem::toString(const QVariant& prop) const +{ + QLocale loc; + const Base::Vector3d& value = prop.value(); + QString data = QString::fromLatin1("[%1 %2 %3]") + .arg(loc.toString(value.x, 'f', lowPrec), + loc.toString(value.y, 'f', lowPrec), + loc.toString(value.z, 'f', lowPrec)); + if (hasExpression()) { + data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + return {data}; +} + +QVariant PropertyVectorItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Vector3d& value = static_cast(prop)->getValue(); + return QVariant::fromValue(value); +} + +void PropertyVectorItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + const Base::Vector3d& val = value.value(); + QString data = QString::fromLatin1("(%1, %2, %3)") + .arg(val.x, 0, 'g', highPrec) + .arg(val.y, 0, 'g', highPrec) + .arg(val.z, 0, 'g', highPrec); + setPropertyValue(data); +} + +QWidget* PropertyVectorItem::createEditor(QWidget* parent, + const std::function& /*method*/) const +{ + auto le = new VectorLineEdit(decimals(), parent); + le->setFrame(false); + le->setReadOnly(true); + + if (isBound()) { + le->bind(getPath()); + le->setAutoApply(autoApply()); + } + + return le; +} + +void PropertyVectorItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + QLocale loc; + auto le = qobject_cast(editor); + const Base::Vector3d& value = data.value(); + QString text = QString::fromLatin1("[%1 %2 %3]") + .arg(loc.toString(value.x, 'f', lowPrec), + loc.toString(value.y, 'f', lowPrec), + loc.toString(value.z, 'f', lowPrec)); + le->setProperty("coords", data); + le->setText(text); +} + +QVariant PropertyVectorItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + return {le->text()}; +} + +double PropertyVectorItem::x() const +{ + return data(1, Qt::EditRole).value().x; +} + +void PropertyVectorItem::setX(double x) +{ + setData(QVariant::fromValue(Base::Vector3d(x, y(), z()))); +} + +double PropertyVectorItem::y() const +{ + return data(1, Qt::EditRole).value().y; +} + +void PropertyVectorItem::setY(double y) +{ + setData(QVariant::fromValue(Base::Vector3d(x(), y, z()))); +} + +double PropertyVectorItem::z() const +{ + return data(1, Qt::EditRole).value().z; +} + +void PropertyVectorItem::setZ(double z) +{ + setData(QVariant::fromValue(Base::Vector3d(x(), y(), z))); +} + +void PropertyVectorItem::propertyBound() +{ + m_x->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("x")); + m_y->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("y")); + m_z->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("z")); +} + +// --------------------------------------------------------------- + +PropertyEditorWidget::PropertyEditorWidget(QWidget* parent) + : QWidget(parent) +{ + auto layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(2); + + lineEdit = new QLineEdit(this); + lineEdit->setReadOnly(true); + layout->addWidget(lineEdit); + + button = new QPushButton(QLatin1String("..."), this); +#if defined(Q_OS_MACOS) + button->setAttribute( + Qt::WA_LayoutUsesWidgetRect); // layout size from QMacStyle was not correct +#endif + layout->addWidget(button); + + connect(button, &QPushButton::clicked, this, &PropertyEditorWidget::buttonClick); + + // QAbstractItemView will call selectAll() if a QLineEdit is the focus + // proxy. Since the QLineEdit here is read-only and not meant for editing, + // do not set it as focus proxy. Otherwise, the text won't even shown for + // most stylesheets (which contain a trick to hide the content of a selected + // read-only/disabled editor widgets). + // + // setFocusProxy(lineEdit); +} + +PropertyEditorWidget::~PropertyEditorWidget() = default; + +void PropertyEditorWidget::resizeEvent(QResizeEvent* e) +{ + button->setFixedWidth(e->size().height()); + button->setFixedHeight(e->size().height()); +} + +void PropertyEditorWidget::showValue(const QVariant& d) +{ + lineEdit->setText(d.toString()); +} + +QVariant PropertyEditorWidget::value() const +{ + return variant; +} + +void PropertyEditorWidget::setValue(const QVariant& val) +{ + variant = val; + showValue(variant); + Q_EMIT valueChanged(variant); +} + +// --------------------------------------------------------------- + +VectorListWidget::VectorListWidget(int decimals, QWidget* parent) + : PropertyEditorWidget(parent) + , decimals(decimals) +{ + connect(button, &QPushButton::clicked, this, &VectorListWidget::buttonClicked); +} + +void VectorListWidget::buttonClicked() +{ + auto dlg = new VectorListEditor(decimals, this); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->setValues(value().value>()); + QPoint p(0, 0); + p = this->mapToGlobal(p); + dlg->move(p); + connect(dlg, &VectorListEditor::accepted, this, [this, dlg] { + QVariant data = QVariant::fromValue>(dlg->getValues()); + setValue(data); + }); + + dlg->exec(); +} + +void VectorListWidget::showValue(const QVariant& d) +{ + QLocale loc; + QString data; + const QList& value = d.value>(); + if (value.isEmpty()) { + data = QString::fromLatin1("[]"); + } + else { + data = QString::fromLatin1("[%1 %2 %3], ...") + .arg(loc.toString(value[0].x, 'f', lowPrec), + loc.toString(value[0].y, 'f', lowPrec), + loc.toString(value[0].z, 'f', lowPrec)); + } + lineEdit->setText(data); +} +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorListItem) + +PropertyVectorListItem::PropertyVectorListItem() = default; + +QVariant PropertyVectorListItem::toString(const QVariant& prop) const +{ + QLocale loc; + QString data; + const QList& value = prop.value>(); + if (value.isEmpty()) { + data = QString::fromLatin1("[]"); + } + else { + data = QString::fromLatin1("[%1 %2 %3], ...") + .arg(loc.toString(value[0].x, 'f', lowPrec), + loc.toString(value[0].y, 'f', lowPrec), + loc.toString(value[0].z, 'f', lowPrec)); + } + + if (hasExpression()) { + data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + return {data}; +} + +QVariant PropertyVectorListItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const std::vector& value = + static_cast(prop)->getValue(); + QList list; + std::copy(value.begin(), value.end(), std::back_inserter(list)); + return QVariant::fromValue>(list); +} + +void PropertyVectorListItem::setValue(const QVariant& value) +{ + if (!value.canConvert>()) { + return; + } + const QList& val = value.value>(); + QString data; + QTextStream str(&data); + str << "["; + for (const auto& it : val) { + str << QString::fromLatin1("(%1, %2, %3), ") + .arg(it.x, 0, 'g', highPrec) + .arg(it.y, 0, 'g', highPrec) + .arg(it.z, 0, 'g', highPrec); + } + str << "]"; + setPropertyValue(data); +} + +QWidget* PropertyVectorListItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto pe = new VectorListWidget(decimals(), parent); + QObject::connect(pe, &VectorListWidget::valueChanged, method); + pe->setDisabled(isReadOnly()); + return pe; +} + +void PropertyVectorListItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto pe = qobject_cast(editor); + pe->setValue(data); +} + +QVariant PropertyVectorListItem::editorData(QWidget* editor) const +{ + auto pe = qobject_cast(editor); + return pe->value(); +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorDistanceItem) + +PropertyVectorDistanceItem::PropertyVectorDistanceItem() +{ + m_x = static_cast(PropertyUnitItem::create()); + m_x->setParent(this); + m_x->setPropertyName(QLatin1String("x")); + this->appendChild(m_x); + m_y = static_cast(PropertyUnitItem::create()); + m_y->setParent(this); + m_y->setPropertyName(QLatin1String("y")); + this->appendChild(m_y); + m_z = static_cast(PropertyUnitItem::create()); + m_z->setParent(this); + m_z->setPropertyName(QLatin1String("z")); + this->appendChild(m_z); +} + +QVariant PropertyVectorDistanceItem::toString(const QVariant& prop) const +{ + const Base::Vector3d& value = prop.value(); + QString data = QString::fromLatin1("[") + + Base::Quantity(value.x, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + + Base::Quantity(value.y, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + + Base::Quantity(value.z, Base::Unit::Length).getUserString() + QString::fromLatin1("]"); + if (hasExpression()) { + data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + } + return {data}; +} + + +QVariant PropertyVectorDistanceItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Vector3d& value = static_cast(prop)->getValue(); + return QVariant::fromValue(value); +} + +void PropertyVectorDistanceItem::setValue(const QVariant& variant) +{ + if (hasExpression() || !variant.canConvert()) { + return; + } + const Base::Vector3d& value = variant.value(); + + Base::Quantity x = Base::Quantity(value.x, Base::Unit::Length); + Base::Quantity y = Base::Quantity(value.y, Base::Unit::Length); + Base::Quantity z = Base::Quantity(value.z, Base::Unit::Length); + + Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); + QString data = QString::fromLatin1("(%1, %2, %3)") + .arg(Base::UnitsApi::toNumber(x, format), + Base::UnitsApi::toNumber(y, format), + Base::UnitsApi::toNumber(z, format)); + setPropertyValue(data); +} + +void PropertyVectorDistanceItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + le->setProperty("coords", data); + le->setText(toString(data).toString()); +} + +QWidget* PropertyVectorDistanceItem::createEditor(QWidget* parent, + const std::function& /*method*/) const +{ + auto le = new VectorLineEdit(decimals(), parent); + le->setFrame(false); + le->setReadOnly(true); + + if (isBound()) { + le->bind(getPath()); + le->setAutoApply(autoApply()); + } + + return le; +} + +QVariant PropertyVectorDistanceItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + return {le->text()}; +} + +Base::Quantity PropertyVectorDistanceItem::x() const +{ + return Base::Quantity(data(1, Qt::EditRole).value().x, Base::Unit::Length); +} + +void PropertyVectorDistanceItem::setX(Base::Quantity x) +{ + setData(QVariant::fromValue(Base::Vector3d(x.getValue(), y().getValue(), z().getValue()))); +} + +Base::Quantity PropertyVectorDistanceItem::y() const +{ + return Base::Quantity(data(1, Qt::EditRole).value().y, Base::Unit::Length); +} + +void PropertyVectorDistanceItem::setY(Base::Quantity y) +{ + setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y.getValue(), z().getValue()))); +} + +Base::Quantity PropertyVectorDistanceItem::z() const +{ + return Base::Quantity(data(1, Qt::EditRole).value().z, Base::Unit::Length); +} + +void PropertyVectorDistanceItem::setZ(Base::Quantity z) +{ + setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y().getValue(), z.getValue()))); +} + +void PropertyVectorDistanceItem::propertyBound() +{ + if (isBound()) { + m_x->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("x")); + m_y->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("y")); + m_z->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("z")); + }; +} + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPositionItem) + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyDirectionItem) + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMatrixItem) + +PropertyMatrixItem::PropertyMatrixItem() +{ + const int decimals = highPrec; + m_a11 = static_cast(PropertyFloatItem::create()); + m_a11->setParent(this); + m_a11->setPropertyName(QLatin1String("A11")); + m_a11->setDecimals(decimals); + this->appendChild(m_a11); + m_a12 = static_cast(PropertyFloatItem::create()); + m_a12->setParent(this); + m_a12->setPropertyName(QLatin1String("A12")); + m_a12->setDecimals(decimals); + this->appendChild(m_a12); + m_a13 = static_cast(PropertyFloatItem::create()); + m_a13->setParent(this); + m_a13->setPropertyName(QLatin1String("A13")); + m_a13->setDecimals(decimals); + this->appendChild(m_a13); + m_a14 = static_cast(PropertyFloatItem::create()); + m_a14->setParent(this); + m_a14->setPropertyName(QLatin1String("A14")); + m_a14->setDecimals(decimals); + this->appendChild(m_a14); + m_a21 = static_cast(PropertyFloatItem::create()); + m_a21->setParent(this); + m_a21->setPropertyName(QLatin1String("A21")); + m_a21->setDecimals(decimals); + this->appendChild(m_a21); + m_a22 = static_cast(PropertyFloatItem::create()); + m_a22->setParent(this); + m_a22->setPropertyName(QLatin1String("A22")); + m_a22->setDecimals(decimals); + this->appendChild(m_a22); + m_a23 = static_cast(PropertyFloatItem::create()); + m_a23->setParent(this); + m_a23->setPropertyName(QLatin1String("A23")); + m_a23->setDecimals(decimals); + this->appendChild(m_a23); + m_a24 = static_cast(PropertyFloatItem::create()); + m_a24->setParent(this); + m_a24->setPropertyName(QLatin1String("A24")); + m_a24->setDecimals(decimals); + this->appendChild(m_a24); + m_a31 = static_cast(PropertyFloatItem::create()); + m_a31->setParent(this); + m_a31->setPropertyName(QLatin1String("A31")); + m_a31->setDecimals(decimals); + this->appendChild(m_a31); + m_a32 = static_cast(PropertyFloatItem::create()); + m_a32->setParent(this); + m_a32->setPropertyName(QLatin1String("A32")); + m_a32->setDecimals(decimals); + this->appendChild(m_a32); + m_a33 = static_cast(PropertyFloatItem::create()); + m_a33->setParent(this); + m_a33->setPropertyName(QLatin1String("A33")); + m_a33->setDecimals(decimals); + this->appendChild(m_a33); + m_a34 = static_cast(PropertyFloatItem::create()); + m_a34->setParent(this); + m_a34->setPropertyName(QLatin1String("A34")); + m_a34->setDecimals(decimals); + this->appendChild(m_a34); + m_a41 = static_cast(PropertyFloatItem::create()); + m_a41->setParent(this); + m_a41->setPropertyName(QLatin1String("A41")); + m_a41->setDecimals(decimals); + this->appendChild(m_a41); + m_a42 = static_cast(PropertyFloatItem::create()); + m_a42->setParent(this); + m_a42->setPropertyName(QLatin1String("A42")); + m_a42->setDecimals(decimals); + this->appendChild(m_a42); + m_a43 = static_cast(PropertyFloatItem::create()); + m_a43->setParent(this); + m_a43->setPropertyName(QLatin1String("A43")); + m_a43->setDecimals(decimals); + this->appendChild(m_a43); + m_a44 = static_cast(PropertyFloatItem::create()); + m_a44->setParent(this); + m_a44->setPropertyName(QLatin1String("A44")); + m_a44->setDecimals(decimals); + this->appendChild(m_a44); +} + +QVariant PropertyMatrixItem::toString(const QVariant& prop) const +{ + QLocale loc; + const Base::Matrix4D& value = prop.value(); + // NOLINTBEGIN + QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) + loc.toString(value[0][1], 'f', lowPrec), + loc.toString(value[0][2], 'f', lowPrec), + loc.toString(value[0][3], 'f', lowPrec), + loc.toString(value[1][0], 'f', lowPrec), + loc.toString(value[1][1], 'f', lowPrec), + loc.toString(value[1][2], 'f', lowPrec), + loc.toString(value[1][3], 'f', lowPrec), + loc.toString(value[2][0], 'f', lowPrec)) + .arg(loc.toString(value[2][1], 'f', lowPrec), + loc.toString(value[2][2], 'f', lowPrec), + loc.toString(value[2][3], 'f', lowPrec), + loc.toString(value[3][0], 'f', lowPrec), + loc.toString(value[3][1], 'f', lowPrec), + loc.toString(value[3][2], 'f', lowPrec), + loc.toString(value[3][3], 'f', lowPrec)); + // NOLINTEND + return {text}; +} + +QVariant PropertyMatrixItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Matrix4D& value = static_cast(prop)->getValue(); + return QVariant::fromValue(value); +} + +QVariant PropertyMatrixItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Matrix4D& value = static_cast(prop)->getValue(); + return {QString::fromStdString(value.analyse())}; +} + +void PropertyMatrixItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + const Base::Matrix4D& val = value.value(); + // NOLINTBEGIN + QString data = + QString::fromLatin1( + "FreeCAD.Matrix(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)") + .arg(val[0][0], 0, 'g', highPrec) + .arg(val[0][1], 0, 'g', highPrec) + .arg(val[0][2], 0, 'g', highPrec) + .arg(val[0][3], 0, 'g', highPrec) + .arg(val[1][0], 0, 'g', highPrec) + .arg(val[1][1], 0, 'g', highPrec) + .arg(val[1][2], 0, 'g', highPrec) + .arg(val[1][3], 0, 'g', highPrec) + .arg(val[2][0], 0, 'g', highPrec) + .arg(val[2][1], 0, 'g', highPrec) + .arg(val[2][2], 0, 'g', highPrec) + .arg(val[2][3], 0, 'g', highPrec) + .arg(val[3][0], 0, 'g', highPrec) + .arg(val[3][1], 0, 'g', highPrec) + .arg(val[3][2], 0, 'g', highPrec) + .arg(val[3][3], 0, 'g', highPrec); + // NOLINTEND + setPropertyValue(data); +} + +QWidget* PropertyMatrixItem::createEditor(QWidget* parent, + const std::function& /*method*/) const +{ + auto le = new QLineEdit(parent); + le->setFrame(false); + le->setReadOnly(true); + return le; +} + +void PropertyMatrixItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + QLocale loc; + auto le = qobject_cast(editor); + const Base::Matrix4D& value = data.value(); + // NOLINTBEGIN + QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) + loc.toString(value[0][1], 'f', lowPrec), + loc.toString(value[0][2], 'f', lowPrec), + loc.toString(value[0][3], 'f', lowPrec), + loc.toString(value[1][0], 'f', lowPrec), + loc.toString(value[1][1], 'f', lowPrec), + loc.toString(value[1][2], 'f', lowPrec), + loc.toString(value[1][3], 'f', lowPrec), + loc.toString(value[2][0], 'f', lowPrec)) + .arg(loc.toString(value[2][1], 'f', lowPrec), + loc.toString(value[2][2], 'f', lowPrec), + loc.toString(value[2][3], 'f', lowPrec), + loc.toString(value[3][0], 'f', lowPrec), + loc.toString(value[3][1], 'f', lowPrec), + loc.toString(value[3][2], 'f', lowPrec), + loc.toString(value[3][3], 'f', lowPrec)); + // NOLINTEND + le->setText(text); +} + +QVariant PropertyMatrixItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + return {le->text()}; +} + +// clang-format off +double PropertyMatrixItem::getA11() const +{ + return data(1, Qt::EditRole).value()[0][0]; +} + +void PropertyMatrixItem::setA11(double A11) +{ + setData(QVariant::fromValue(Base::Matrix4D(A11, getA12(), getA13(),getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA12() const +{ + return data(1, Qt::EditRole).value()[0][1]; +} + +void PropertyMatrixItem::setA12(double A12) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), A12, getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA13() const +{ + return data(1, Qt::EditRole).value()[0][2]; +} + +void PropertyMatrixItem::setA13(double A13) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), A13, getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA14() const +{ + return data(1, Qt::EditRole).value()[0][3]; +} + +void PropertyMatrixItem::setA14(double A14) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), A14, + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA21() const +{ + return data(1, Qt::EditRole).value()[1][0]; +} + +void PropertyMatrixItem::setA21(double A21) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + A21, getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA22() const +{ + return data(1, Qt::EditRole).value()[1][1]; +} + +void PropertyMatrixItem::setA22(double A22) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), A22, getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA23() const +{ + return data(1, Qt::EditRole).value()[1][2]; +} + +void PropertyMatrixItem::setA23(double A23) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), A23, getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA24() const +{ + return data(1, Qt::EditRole).value()[1][3]; +} + +void PropertyMatrixItem::setA24(double A24) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), A24, + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA31() const +{ + return data(1, Qt::EditRole).value()[2][0]; +} + +void PropertyMatrixItem::setA31(double A31) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + A31, getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA32() const +{ + return data(1, Qt::EditRole).value()[2][1]; +} + +void PropertyMatrixItem::setA32(double A32) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), A32, getA33(), getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA33() const +{ + return data(1, Qt::EditRole).value()[2][2]; +} + +void PropertyMatrixItem::setA33(double A33) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), A33, getA34(), + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA34() const +{ + return data(1, Qt::EditRole).value()[2][3]; +} + +void PropertyMatrixItem::setA34(double A34) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), A34, + getA41(), getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA41() const +{ + return data(1, Qt::EditRole).value()[3][0]; +} + +void PropertyMatrixItem::setA41(double A41) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + A41, getA42(), getA43(), getA44()))); +} + +double PropertyMatrixItem::getA42() const +{ + return data(1, Qt::EditRole).value()[3][1]; +} + +void PropertyMatrixItem::setA42(double A42) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), A42, getA43(), getA44()))); +} + +double PropertyMatrixItem::getA43() const +{ + return data(1, Qt::EditRole).value()[3][2]; +} + +void PropertyMatrixItem::setA43(double A43) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), A43, getA44()))); +} + +double PropertyMatrixItem::getA44() const +{ + return data(1, Qt::EditRole).value()[3][3]; +} + +void PropertyMatrixItem::setA44(double A44) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(), getA12(), getA13(), getA14(), + getA21(), getA22(), getA23(), getA24(), + getA31(), getA32(), getA33(), getA34(), + getA41(), getA42(), getA43(), A44))); +} +// clang-format on + +// --------------------------------------------------------------- + +RotationHelper::RotationHelper() + : init_axis(false) + , changed_value(false) + , rot_angle(0) + , rot_axis(0, 0, 1) +{} + +void RotationHelper::setChanged(bool value) +{ + changed_value = value; +} + +bool RotationHelper::hasChangedAndReset() +{ + if (!changed_value) { + return false; + } + + changed_value = false; + return true; +} + +bool RotationHelper::isAxisInitialized() const +{ + return init_axis; +} + +void RotationHelper::setValue(const Base::Vector3d& axis, double angle) +{ + rot_axis = axis; + rot_angle = angle; + init_axis = true; +} + +void RotationHelper::getValue(Base::Vector3d& axis, double& angle) const +{ + axis = rot_axis; + angle = rot_angle; +} + +double RotationHelper::getAngle(const Base::Rotation& val) const +{ + double angle {}; + Base::Vector3d dir; + val.getRawValue(dir, angle); + if (dir * this->rot_axis < 0.0) { + angle = -angle; + } + return angle; +} + +Base::Rotation RotationHelper::setAngle(double angle) +{ + Base::Rotation rot; + rot.setValue(this->rot_axis, Base::toRadians(angle)); + changed_value = true; + rot_angle = angle; + return rot; +} + +Base::Vector3d RotationHelper::getAxis() const +{ + // We must store the rotation axis in a member because + // if we read the value from the property we would always + // get a normalized vector which makes it quite unhandy + // to work with + return this->rot_axis; +} + +Base::Rotation RotationHelper::setAxis(const Base::Rotation& value, const Base::Vector3d& axis) +{ + this->rot_axis = axis; + Base::Rotation rot = value; + Base::Vector3d dummy; + double angle {}; + rot.getValue(dummy, angle); + if (dummy * axis < 0.0) { + angle = -angle; + } + rot.setValue(axis, angle); + changed_value = true; + return rot; +} + +void RotationHelper::assignProperty(const Base::Rotation& value, double eps) +{ + double angle {}; + Base::Vector3d dir; + value.getRawValue(dir, angle); + Base::Vector3d cross = this->rot_axis.Cross(dir); + double len2 = cross.Sqr(); + if (angle != 0) { + // vectors are not parallel + if (len2 > eps) { + this->rot_axis = dir; + } + // vectors point into opposite directions + else if (this->rot_axis.Dot(dir) < 0) { + this->rot_axis = -this->rot_axis; + } + } + this->rot_angle = Base::toDegrees(angle); +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyRotationItem) + +PropertyRotationItem::PropertyRotationItem() +{ + m_a = static_cast(PropertyUnitItem::create()); + m_a->setParent(this); + m_a->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Angle"))); + this->appendChild(m_a); + m_d = static_cast(PropertyVectorItem::create()); + m_d->setParent(this); + m_d->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Axis"))); + m_d->setReadOnly(true); + this->appendChild(m_d); +} + +PropertyRotationItem::~PropertyRotationItem() = default; + +Base::Quantity PropertyRotationItem::getAngle() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return Base::Quantity(0.0); + } + + const Base::Rotation& val = value.value(); + double angle = h.getAngle(val); + return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); +} + +void PropertyRotationItem::setAngle(Base::Quantity angle) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + Base::Rotation rot = h.setAngle(angle.getValue()); + setValue(QVariant::fromValue(rot)); +} + +Base::Vector3d PropertyRotationItem::getAxis() const +{ + return h.getAxis(); +} + +void PropertyRotationItem::setAxis(const Base::Vector3d& axis) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto rot = value.value(); + rot = h.setAxis(rot, axis); + setValue(QVariant::fromValue(rot)); +} + +void PropertyRotationItem::assignProperty(const App::Property* prop) +{ + // Choose an adaptive epsilon to avoid changing the axis when they are considered to + // be equal. See https://forum.freecad.org/viewtopic.php?f=10&t=24662&start=10 + double eps = std::pow(10.0, -2 * (decimals() + 1)); // NOLINT + if (prop->isDerivedFrom()) { + const Base::Rotation& value = static_cast(prop)->getValue(); + h.assignProperty(value, eps); + } +} + +QVariant PropertyRotationItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Rotation& value = static_cast(prop)->getValue(); + double angle {}; + Base::Vector3d dir; + value.getRawValue(dir, angle); + if (!h.isAxisInitialized()) { + if (m_a->hasExpression()) { + QString str = m_a->expressionAsString(); + angle = str.toDouble(); + } + else { + angle = Base::toDegrees(angle); + } + + PropertyItem* x = m_d->child(0); + PropertyItem* y = m_d->child(1); + PropertyItem* z = m_d->child(2); + if (x->hasExpression()) { + QString str = x->expressionAsString(); + dir.x = str.toDouble(); + } + if (y->hasExpression()) { + QString str = y->expressionAsString(); + dir.y = str.toDouble(); + } + if (z->hasExpression()) { + QString str = z->expressionAsString(); + dir.z = str.toDouble(); + } + h.setValue(dir, angle); + } + return QVariant::fromValue(value); +} + +QVariant PropertyRotationItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Rotation& p = static_cast(prop)->getValue(); + double angle {}; + Base::Vector3d dir; + p.getRawValue(dir, angle); + angle = Base::toDegrees(angle); + + QLocale loc; + QString data = QString::fromUtf8("Axis: (%1 %2 %3)\n" + "Angle: %4") + .arg(loc.toString(dir.x, 'f', decimals()), + loc.toString(dir.y, 'f', decimals()), + loc.toString(dir.z, 'f', decimals()), + Base::Quantity(angle, Base::Unit::Angle).getUserString()); + return {data}; +} + +QVariant PropertyRotationItem::toString(const QVariant& prop) const +{ + const Base::Rotation& p = prop.value(); + double angle {}; + Base::Vector3d dir; + p.getRawValue(dir, angle); + angle = Base::toDegrees(angle); + + QLocale loc; + QString data = QString::fromUtf8("[(%1 %2 %3); %4]") + .arg(loc.toString(dir.x, 'f', lowPrec), + loc.toString(dir.y, 'f', lowPrec), + loc.toString(dir.z, 'f', lowPrec), + Base::Quantity(angle, Base::Unit::Angle).getUserString()); + return {data}; +} + +void PropertyRotationItem::setValue(const QVariant& value) +{ + if (!value.canConvert()) { + return; + } + // Accept this only if the user changed the axis, angle or position but + // not if >this< item loses focus + if (!h.hasChangedAndReset()) { + return; + } + + Base::Vector3d axis; + double angle {}; + h.getValue(axis, angle); + Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); + QString data = QString::fromLatin1("App.Rotation(App.Vector(%1,%2,%3),%4)") + .arg(Base::UnitsApi::toNumber(axis.x, format), + Base::UnitsApi::toNumber(axis.y, format), + Base::UnitsApi::toNumber(axis.z, format), + Base::UnitsApi::toNumber(angle, format)); + setPropertyValue(data); +} + +QWidget* PropertyRotationItem::createEditor(QWidget* parent, + const std::function& method) const +{ + Q_UNUSED(parent) + Q_UNUSED(method) + return nullptr; +} + +void PropertyRotationItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + Q_UNUSED(editor) + Q_UNUSED(data) +} + +QVariant PropertyRotationItem::editorData(QWidget* editor) const +{ + Q_UNUSED(editor) + return {}; +} + +void PropertyRotationItem::propertyBound() +{ + if (isBound()) { + m_a->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Angle")); + + m_d->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Axis")); + } +} + +// -------------------------------------------------------------------- + +PlacementEditor::PlacementEditor(QString name, QWidget* parent) + : LabelButton(parent) + , _task(nullptr) + , propertyname {std::move(name)} +{ + propertyname.replace(QLatin1String(" "), QLatin1String("")); +} + +PlacementEditor::~PlacementEditor() = default; + +void PlacementEditor::browse() +{ + Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); + Gui::Dialog::TaskPlacement* task {}; + task = qobject_cast(dlg); + if (dlg && !task) { + // there is already another task dialog which must be closed first + Gui::Control().showDialog(dlg); + return; + } + if (!task) { + task = new Gui::Dialog::TaskPlacement(); + } + if (!_task) { + _task = task; + connect(task, &TaskPlacement::placementChanged, this, &PlacementEditor::updateValue); + } + task->setPlacement(value().value()); + task->setPropertyName(propertyname); + task->setSelection(Gui::Selection().getSelectionEx()); + task->bindObject(); + Gui::Control().showDialog(task); +} + +void PlacementEditor::showValue(const QVariant& d) +{ + const Base::Placement& p = d.value(); + double angle {}; + Base::Vector3d dir; + Base::Vector3d pos; + p.getRotation().getRawValue(dir, angle); + angle = Base::toDegrees(angle); + pos = p.getPosition(); + + QLocale loc; + QString data = QString::fromUtf8("[(%1 %2 %3);%4 \xc2\xb0;(%5 %6 %7)]") + .arg(loc.toString(dir.x, 'f', lowPrec), + loc.toString(dir.y, 'f', lowPrec), + loc.toString(dir.z, 'f', lowPrec), + loc.toString(angle, 'f', lowPrec), + loc.toString(pos.x, 'f', lowPrec), + loc.toString(pos.y, 'f', lowPrec), + loc.toString(pos.z, 'f', lowPrec)); + getLabel()->setText(data); +} + +void PlacementEditor::updateValue(const QVariant& v, bool incr, bool data) +{ + if (data) { + if (incr) { + QVariant u = value(); + const Base::Placement& plm = u.value(); + const Base::Placement& rel = v.value(); + Base::Placement newp = rel * plm; + setValue(QVariant::fromValue(newp)); + } + else { + setValue(v); + } + } +} + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPlacementItem) + +PropertyPlacementItem::PropertyPlacementItem() +{ + m_a = static_cast(PropertyUnitItem::create()); + m_a->setParent(this); + m_a->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Angle"))); + this->appendChild(m_a); + m_d = static_cast(PropertyVectorItem::create()); + m_d->setParent(this); + m_d->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Axis"))); + m_d->setReadOnly(true); + this->appendChild(m_d); + m_p = static_cast(PropertyVectorDistanceItem::create()); + m_p->setParent(this); + m_p->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Position"))); + m_p->setReadOnly(true); + this->appendChild(m_p); +} + +PropertyPlacementItem::~PropertyPlacementItem() = default; + +Base::Quantity PropertyPlacementItem::getAngle() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return Base::Quantity(0.0); + } + + const Base::Placement& val = value.value(); + double angle = h.getAngle(val.getRotation()); + return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); +} + +void PropertyPlacementItem::setAngle(Base::Quantity angle) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto val = value.value(); + Base::Rotation rot = h.setAngle(angle.getValue()); + val.setRotation(rot); + setValue(QVariant::fromValue(val)); +} + +Base::Vector3d PropertyPlacementItem::getAxis() const +{ + return h.getAxis(); +} + +void PropertyPlacementItem::setAxis(const Base::Vector3d& axis) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto val = value.value(); + Base::Rotation rot = val.getRotation(); + rot = h.setAxis(rot, axis); + val.setRotation(rot); + setValue(QVariant::fromValue(val)); +} + +Base::Vector3d PropertyPlacementItem::getPosition() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return Base::Vector3d(0, 0, 0); + } + const Base::Placement& val = value.value(); + return val.getPosition(); +} + +void PropertyPlacementItem::setPosition(const Base::Vector3d& pos) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto val = value.value(); + val.setPosition(pos); + h.setChanged(true); + setValue(QVariant::fromValue(val)); +} + +void PropertyPlacementItem::assignProperty(const App::Property* prop) +{ + // Choose an adaptive epsilon to avoid changing the axis when they are considered to + // be equal. See https://forum.freecad.org/viewtopic.php?f=10&t=24662&start=10 + double eps = std::pow(10.0, -2 * (decimals() + 1)); // NOLINT + if (prop->isDerivedFrom()) { + const Base::Placement& value = static_cast(prop)->getValue(); + h.assignProperty(value.getRotation(), eps); + } +} + +QVariant PropertyPlacementItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Placement& value = static_cast(prop)->getValue(); + double angle {}; + Base::Vector3d dir; + value.getRotation().getRawValue(dir, angle); + if (!h.isAxisInitialized()) { + if (m_a->hasExpression()) { + QString str = m_a->expressionAsString(); + angle = str.toDouble(); + } + else { + angle = Base::toDegrees(angle); + } + + PropertyItem* x = m_d->child(0); + PropertyItem* y = m_d->child(1); + PropertyItem* z = m_d->child(2); + if (x->hasExpression()) { + QString str = x->expressionAsString(); + dir.x = str.toDouble(); + } + if (y->hasExpression()) { + QString str = y->expressionAsString(); + dir.y = str.toDouble(); + } + if (z->hasExpression()) { + QString str = z->expressionAsString(); + dir.z = str.toDouble(); + } + h.setValue(dir, angle); + } + return QVariant::fromValue(value); +} + +QVariant PropertyPlacementItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const Base::Placement& p = static_cast(prop)->getValue(); + double angle {}; + Base::Vector3d dir; + Base::Vector3d pos; + p.getRotation().getRawValue(dir, angle); + angle = Base::toDegrees(angle); + pos = p.getPosition(); + + QLocale loc; + QString data = QString::fromUtf8("Axis: (%1 %2 %3)\n" + "Angle: %4\n" + "Position: (%5 %6 %7)") + .arg(loc.toString(dir.x, 'f', decimals()), + loc.toString(dir.y, 'f', decimals()), + loc.toString(dir.z, 'f', decimals()), + Base::Quantity(angle, Base::Unit::Angle).getUserString(), + Base::Quantity(pos.x, Base::Unit::Length).getUserString(), + Base::Quantity(pos.y, Base::Unit::Length).getUserString(), + Base::Quantity(pos.z, Base::Unit::Length).getUserString()); + return {data}; +} + +QVariant PropertyPlacementItem::toString(const QVariant& prop) const +{ + const Base::Placement& p = prop.value(); + double angle {}; + Base::Vector3d dir; + Base::Vector3d pos; + p.getRotation().getRawValue(dir, angle); + angle = Base::toDegrees(angle); + pos = p.getPosition(); + + QLocale loc; + QString data = QString::fromUtf8("[(%1 %2 %3); %4; (%5 %6 %7)]") + .arg(loc.toString(dir.x, 'f', lowPrec), + loc.toString(dir.y, 'f', lowPrec), + loc.toString(dir.z, 'f', lowPrec), + Base::Quantity(angle, Base::Unit::Angle).getUserString(), + Base::Quantity(pos.x, Base::Unit::Length).getUserString(), + Base::Quantity(pos.y, Base::Unit::Length).getUserString(), + Base::Quantity(pos.z, Base::Unit::Length).getUserString()); + return {data}; +} + +void PropertyPlacementItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + // Accept this only if the user changed the axis, angle or position but + // not if >this< item loses focus + if (!h.hasChangedAndReset()) { + return; + } + + const Base::Placement& val = value.value(); + Base::Vector3d pos = val.getPosition(); + + Base::Vector3d axis; + double angle {}; + h.getValue(axis, angle); + + Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); + QString data = QString::fromLatin1("App.Placement(" + "App.Vector(%1,%2,%3)," + "App.Rotation(App.Vector(%4,%5,%6),%7))") + .arg(Base::UnitsApi::toNumber(pos.x, format), + Base::UnitsApi::toNumber(pos.y, format), + Base::UnitsApi::toNumber(pos.z, format), + Base::UnitsApi::toNumber(axis.x, format), + Base::UnitsApi::toNumber(axis.y, format), + Base::UnitsApi::toNumber(axis.z, format), + Base::UnitsApi::toNumber(angle, format)); + setPropertyValue(data); +} + +QWidget* PropertyPlacementItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto pe = new PlacementEditor(this->propertyName(), parent); + QObject::connect(pe, &PlacementEditor::valueChanged, method); + + // The Placement dialog only works if property is part of a DocumentObject + bool readonly = isReadOnly(); + if (auto prop = getFirstProperty()) { + readonly |= (!prop->getContainer()->isDerivedFrom()); + } + pe->setDisabled(readonly); + return pe; +} + +void PropertyPlacementItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto pe = qobject_cast(editor); + pe->setValue(data); +} + +QVariant PropertyPlacementItem::editorData(QWidget* editor) const +{ + auto pe = qobject_cast(editor); + return pe->value(); +} + +void PropertyPlacementItem::propertyBound() +{ + if (isBound()) { + m_a->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Rotation") + << App::ObjectIdentifier::String("Angle")); + + m_d->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Rotation") + << App::ObjectIdentifier::String("Axis")); + + m_p->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Base")); + } +} + + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyEnumItem) + +PropertyEnumItem::PropertyEnumItem() + : m_enum(nullptr) +{ + if (PropertyView::showAll()) { + m_enum = static_cast(PropertyStringListItem::create()); + m_enum->setParent(this); + m_enum->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Enum"))); + this->appendChild(m_enum); + } +} + +void PropertyEnumItem::propertyBound() +{ + if (m_enum && isBound()) { + m_enum->bind(App::ObjectIdentifier(getPath()) << App::ObjectIdentifier::String("Enum")); + } +} + +void PropertyEnumItem::setEnum(const QStringList& values) +{ + setData(values); +} + +QStringList PropertyEnumItem::getEnum() const +{ + QStringList res; + auto prop = getFirstProperty(); + if (prop && prop->isDerivedFrom()) { + const auto prop_enum = static_cast(prop); + std::vector enums = prop_enum->getEnumVector(); + for (const auto& it : enums) { + res.push_back(QString::fromStdString(it)); + } + } + return res; +} + +QVariant PropertyEnumItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const auto prop_enum = static_cast(prop); + if (!prop_enum->isValid()) { + return {QString()}; + } + return {QString::fromUtf8(prop_enum->getValueAsString())}; +} + +void PropertyEnumItem::setValue(const QVariant& value) +{ + if (hasExpression()) { + return; + } + + QString data; + + if (value.userType() == QMetaType::QStringList) { + QStringList values = value.toStringList(); + QTextStream str(&data); + str << "["; + for (const auto& it : values) { + QString text(it); + text.replace(QString::fromUtf8("'"), QString::fromUtf8("\\'")); + + std::string pystr = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); + pystr = Base::InterpreterSingleton::strToPython(pystr.c_str()); + str << "u\"" << pystr.c_str() << "\", "; + } + str << "]"; + setPropertyValue(data); + } + else if (value.canConvert()) { + QByteArray val = value.toString().toUtf8(); + std::string str = Base::Tools::escapedUnicodeFromUtf8(val); + data = QString::fromLatin1("u\"%1\"").arg(QString::fromStdString(str)); + setPropertyValue(data); + } +} + +namespace +{ + +class EnumItems; + +struct EnumItem +{ + QString text; + QString fullText; + std::shared_ptr children; + explicit EnumItem(QString t = QString(), QString f = QString()) + : text(std::move(t)) + , fullText(std::move(f)) + {} + void populate(QMenu* menu); +}; + +class EnumItems: public std::vector +{ +}; + +void EnumItem::populate(QMenu* menu) +{ + if (!children || children->empty()) { + auto action = menu->addAction(text); + action->setData(fullText); + return; + } + auto subMenu = menu->addMenu(text); + for (auto& item : *children) { + item.populate(subMenu); + } +} + +std::shared_ptr getEnumItems(const QStringList& commonModes) // NOLINT +{ + int index = -1; + std::shared_ptr enumItems; + for (auto& mode : commonModes) { + ++index; + auto fields = mode.split(QStringLiteral("|")); + if (!enumItems && fields.size() <= 1) { + continue; + } + if (!enumItems) { + enumItems = std::make_shared(); + for (int i = 0; i < index; ++i) { + enumItems->emplace_back(commonModes[i], mode); + } + } + auto children = enumItems; + int j = -1; + for (auto& field : fields) { + ++j; + field = field.trimmed(); + auto it = children->end(); + if (field.isEmpty()) { + if (!children->empty()) { + --it; + } + else { + continue; + } + } + else { + it = std::find_if(children->begin(), + children->end(), + [&field](const EnumItem& item) { + return item.text == field; + }); + if (it == children->end()) { + it = children->emplace(children->end(), field, mode); + } + } + if (j + 1 == (int)fields.size()) { + break; + } + if (!it->children) { + it->children = std::make_shared(); + } + children = it->children; + } + } + + return enumItems; +} + +} // anonymous namespace + +QStringList PropertyEnumItem::getCommonModes() const +{ + const std::vector& items = getPropertyData(); + + QStringList commonModes; + QStringList modes; + for (auto it = items.begin(); it != items.end(); ++it) { + if ((*it)->is()) { + auto prop = static_cast(*it); + if (!prop->hasEnums()) { + commonModes.clear(); + return {}; + } + const std::vector& value = prop->getEnumVector(); + if (it == items.begin()) { + for (const auto& jt : value) { + commonModes << QString::fromUtf8(jt.c_str()); + } + } + else { + for (const auto& jt : value) { + if (commonModes.contains(QString::fromUtf8(jt.c_str()))) { + modes << QString::fromUtf8(jt.c_str()); + } + } + + commonModes = modes; + modes.clear(); + } + } + } + + return commonModes; +} + +QWidget* PropertyEnumItem::createEditor(QWidget* parent, const std::function& method) const +{ + QStringList commonModes = getCommonModes(); + if (commonModes.isEmpty()) { + return nullptr; + } + + std::shared_ptr enumItems = getEnumItems(commonModes); + + if (!enumItems) { + auto cb = new QComboBox(parent); + cb->setFrame(false); + cb->setDisabled(isReadOnly()); + cb->addItems(commonModes); + QObject::connect(cb, qOverload(&QComboBox::activated), method); + return cb; + } + + auto button = new PropertyEnumButton(parent); + button->setDisabled(isReadOnly()); + auto menu = new QMenu(button); + for (auto& item : *enumItems) { + item.populate(menu); + } + button->setMenu(menu); + QObject::connect(menu, &QMenu::aboutToShow, this, [=]() { + menu->setMinimumWidth(button->width()); + }); + QObject::connect(menu, &QMenu::triggered, this, [=](QAction* action) { + button->setText(action->data().toString()); + Q_EMIT button->picked(); + }); + QObject::connect(button, &PropertyEnumButton::picked, method); + return button; +} + +void PropertyEnumItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + if (auto cb = qobject_cast(editor)) { + cb->setEditable(false); + cb->setCurrentIndex(cb->findText(data.toString())); + } + else if (auto btn = qobject_cast(editor)) { + btn->setText(data.toString()); + } +} + +QVariant PropertyEnumItem::editorData(QWidget* editor) const +{ + if (auto cb = qobject_cast(editor)) { + return {cb->currentText()}; + } + if (auto btn = qobject_cast(editor)) { + return btn->text(); + } + return {}; +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringListItem) + +PropertyStringListItem::PropertyStringListItem() = default; + +QWidget* PropertyStringListItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto le = new Gui::LabelEditor(parent); + le->setAutoFillBackground(true); + le->setDisabled(isReadOnly()); + QObject::connect(le, &Gui::LabelEditor::textChanged, method); + return le; +} + +void PropertyStringListItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + QStringList list = data.toStringList(); + le->setText(list.join(QChar::fromLatin1('\n'))); +} + +QVariant PropertyStringListItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + QString complete = le->text(); + QStringList list = complete.split(QChar::fromLatin1('\n')); + return {list}; +} + +QVariant PropertyStringListItem::toString(const QVariant& prop) const +{ + QStringList list = prop.toStringList(); + const int size = 10; + if (list.size() > size) { + list = list.mid(0, size); + list.append(QLatin1String("...")); + } + + QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + + return {text}; +} + +QVariant PropertyStringListItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + QStringList list; + const std::vector& value = + (static_cast(prop))->getValues(); + for (const auto& jt : value) { + list << QString::fromUtf8(jt.c_str()); + } + + return {list}; +} + +void PropertyStringListItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + QStringList values = value.toStringList(); + QString data; + QTextStream str(&data); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + str.setCodec("UTF-8"); +#endif + + str << "["; + for (const auto& it : values) { + QString text(it); + std::string pystr = Base::InterpreterSingleton::strToPython(text.toUtf8().constData()); + str << "\"" << QString::fromUtf8(pystr.c_str()) << "\", "; + } + str << "]"; + + setPropertyValue(data); +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatListItem) + +PropertyFloatListItem::PropertyFloatListItem() = default; + +QWidget* PropertyFloatListItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto le = new Gui::LabelEditor(parent); + le->setAutoFillBackground(true); + le->setInputType(Gui::LabelEditor::Float); + le->setDisabled(isReadOnly()); + QObject::connect(le, &Gui::LabelEditor::textChanged, method); + return le; +} + +void PropertyFloatListItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + QStringList list = data.toStringList(); + le->setText(list.join(QChar::fromLatin1('\n'))); +} + +QVariant PropertyFloatListItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + QString complete = le->text(); + QStringList list = complete.split(QChar::fromLatin1('\n')); + return {list}; +} + +QVariant PropertyFloatListItem::toString(const QVariant& prop) const +{ + QStringList list = prop.toStringList(); + const int size = 10; + if (list.size() > size) { + list = list.mid(0, size); + list.append(QLatin1String("...")); + } + QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + return {text}; +} + +QVariant PropertyFloatListItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + QStringList list; + const std::vector& value = + static_cast(prop)->getValues(); + for (double jt : value) { + list << QString::number(jt, 'f', decimals()); + } + + return {list}; +} + +void PropertyFloatListItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + QStringList values = value.toStringList(); + QString data; + QTextStream str(&data); + str << "["; + for (const auto& it : values) { + str << it << ","; + } + str << "]"; + if (data == QString::fromUtf8("[,]")) { + data = QString::fromUtf8("[]"); + } + setPropertyValue(data); +} + +// --------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerListItem) + +PropertyIntegerListItem::PropertyIntegerListItem() = default; + +QWidget* PropertyIntegerListItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto le = new Gui::LabelEditor(parent); + le->setAutoFillBackground(true); + le->setInputType(Gui::LabelEditor::Integer); + le->setDisabled(isReadOnly()); + QObject::connect(le, &Gui::LabelEditor::textChanged, method); + return le; +} + +void PropertyIntegerListItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto le = qobject_cast(editor); + QStringList list = data.toStringList(); + le->setText(list.join(QChar::fromLatin1('\n'))); +} + +QVariant PropertyIntegerListItem::editorData(QWidget* editor) const +{ + auto le = qobject_cast(editor); + QString complete = le->text(); + QStringList list = complete.split(QChar::fromLatin1('\n')); + return {list}; +} + +QVariant PropertyIntegerListItem::toString(const QVariant& prop) const +{ + QStringList list = prop.toStringList(); + const int size = 10; + if (list.size() > size) { + list = list.mid(0, size); + list.append(QLatin1String("...")); + } + QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + + return {text}; +} + +QVariant PropertyIntegerListItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + QStringList list; + const std::vector& value = + static_cast(prop)->getValues(); + for (long jt : value) { + list << QString::number(jt); + } + + return {list}; +} + +void PropertyIntegerListItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + QStringList values = value.toStringList(); + QString data; + QTextStream str(&data); + str << "["; + for (const auto& value : values) { + str << value << ","; + } + str << "]"; + if (data == QString::fromUtf8("[,]")) { + data = QString::fromUtf8("[]"); + } + setPropertyValue(data); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyColorItem) + +PropertyColorItem::PropertyColorItem() = default; + +QVariant PropertyColorItem::decoration(const QVariant& value) const +{ + auto color = value.value(); + + int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); + QPixmap p(size, size); + p.fill(color); + + return QVariant(p); +} + +QVariant PropertyColorItem::toString(const QVariant& prop) const +{ + auto value = prop.value(); + QString color = + QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + return {color}; +} + +QVariant PropertyColorItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + App::Color value = static_cast(prop)->getValue(); + return QVariant(value.asValue()); +} + +void PropertyColorItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + auto col = value.value(); + QString data = + QString::fromLatin1("(%1,%2,%3)").arg(col.red()).arg(col.green()).arg(col.blue()); + setPropertyValue(data); +} + +QWidget* PropertyColorItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto cb = new Gui::ColorButton(parent); + cb->setDisabled(isReadOnly()); + QObject::connect(cb, &Gui::ColorButton::changed, method); + return cb; +} + +void PropertyColorItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto cb = qobject_cast(editor); + auto color = data.value(); + cb->setColor(color); +} + +QVariant PropertyColorItem::editorData(QWidget* editor) const +{ + auto cb = qobject_cast(editor); + QVariant var; + var.setValue(cb->color()); + return var; +} + +// -------------------------------------------------------------------- + +namespace Gui::PropertyEditor +{ +class Material +{ +public: + QColor diffuseColor; + QColor ambientColor; + QColor specularColor; + QColor emissiveColor; + float shininess {}; + float transparency {}; +}; +} // namespace Gui::PropertyEditor + +Q_DECLARE_METATYPE(Gui::PropertyEditor::Material) // NOLINT + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialItem) + +PropertyMaterialItem::PropertyMaterialItem() +{ + const int min = 0; + const int max = 100; + const int steps = 5; + diffuse = static_cast(PropertyColorItem::create()); + diffuse->setParent(this); + diffuse->setPropertyName(QLatin1String("DiffuseColor")); + this->appendChild(diffuse); + + ambient = static_cast(PropertyColorItem::create()); + ambient->setParent(this); + ambient->setPropertyName(QLatin1String("AmbientColor")); + this->appendChild(ambient); + + specular = static_cast(PropertyColorItem::create()); + specular->setParent(this); + specular->setPropertyName(QLatin1String("SpecularColor")); + this->appendChild(specular); + + emissive = static_cast(PropertyColorItem::create()); + emissive->setParent(this); + emissive->setPropertyName(QLatin1String("EmissiveColor")); + this->appendChild(emissive); + + shininess = + static_cast(PropertyIntegerConstraintItem::create()); + shininess->setRange(min, max); + shininess->setStepSize(steps); + shininess->setParent(this); + shininess->setPropertyName(QLatin1String("Shininess")); + this->appendChild(shininess); + + transparency = + static_cast(PropertyIntegerConstraintItem::create()); + transparency->setRange(min, max); + transparency->setStepSize(steps); + transparency->setParent(this); + transparency->setPropertyName(QLatin1String("Transparency")); + this->appendChild(transparency); +} + +PropertyMaterialItem::~PropertyMaterialItem() = default; + +void PropertyMaterialItem::propertyBound() +{} + +QColor PropertyMaterialItem::getDiffuseColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + auto val = value.value(); + return val.diffuseColor; +} + +void PropertyMaterialItem::setDiffuseColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.diffuseColor = color; + setValue(QVariant::fromValue(mat)); +} + +QColor PropertyMaterialItem::getAmbientColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + auto val = value.value(); + return val.ambientColor; +} + +void PropertyMaterialItem::setAmbientColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.ambientColor = color; + setValue(QVariant::fromValue(mat)); +} + +QColor PropertyMaterialItem::getSpecularColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + auto val = value.value(); + return val.specularColor; +} + +void PropertyMaterialItem::setSpecularColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.specularColor = color; + setValue(QVariant::fromValue(mat)); +} + +QColor PropertyMaterialItem::getEmissiveColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + auto val = value.value(); + return val.emissiveColor; +} + +void PropertyMaterialItem::setEmissiveColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.emissiveColor = color; + setValue(QVariant::fromValue(mat)); +} + +int PropertyMaterialItem::getShininess() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return 0; + } + + auto val = value.value(); + return toPercent(val.shininess); +} + +void PropertyMaterialItem::setShininess(int s) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.shininess = fromPercent(s); + setValue(QVariant::fromValue(mat)); +} + +int PropertyMaterialItem::getTransparency() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return 0; + } + + auto val = value.value(); + return toPercent(val.transparency); +} + +void PropertyMaterialItem::setTransparency(int t) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + auto mat = value.value(); + mat.transparency = fromPercent(t); + setValue(QVariant::fromValue(mat)); +} + +QVariant PropertyMaterialItem::decoration(const QVariant& value) const +{ + // use the diffuse color + auto val = value.value(); + QColor color = val.diffuseColor; + + int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); + QPixmap p(size, size); + p.fill(color); + + return QVariant(p); +} + +QVariant PropertyMaterialItem::toString(const QVariant& prop) const +{ + // use the diffuse color + auto val = prop.value(); + QColor value = val.diffuseColor; + QString color = + QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + return {color}; +} + +QVariant PropertyMaterialItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const App::Material& value = static_cast(prop)->getValue(); + auto dc = value.diffuseColor.asValue(); + auto ac = value.ambientColor.asValue(); + auto sc = value.specularColor.asValue(); + auto ec = value.emissiveColor.asValue(); + + QString data = QString::fromUtf8("Diffuse color: [%1, %2, %3]\n" + "Ambient color: [%4, %5, %6]\n" + "Specular color: [%7, %8, %9]\n" + "Emissive color: [%10, %11, %12]\n" + "Shininess: %13\n" + "Transparency: %14") + .arg(dc.red()) + .arg(dc.green()) + .arg(dc.blue()) + .arg(ac.red()) + .arg(ac.green()) + .arg(ac.blue()) + .arg(sc.red()) + .arg(sc.green()) + .arg(sc.blue()) + .arg(ec.red()) + .arg(ec.green()) + .arg(ec.blue()) + .arg(toPercent(value.shininess)) + .arg(toPercent(value.transparency)); + + return {data}; +} + +QVariant PropertyMaterialItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const App::Material& value = static_cast(prop)->getValue(); + Material mat; + + mat.diffuseColor = value.diffuseColor.asValue(); + mat.ambientColor = value.ambientColor.asValue(); + mat.specularColor = value.specularColor.asValue(); + mat.emissiveColor = value.emissiveColor.asValue(); + mat.shininess = value.shininess; + mat.transparency = value.transparency; + + return QVariant::fromValue(mat); +} + +void PropertyMaterialItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + + auto mat = value.value(); + App::Color dc; + dc.setValue(mat.diffuseColor); + App::Color ac; + ac.setValue(mat.ambientColor); + App::Color sc; + sc.setValue(mat.specularColor); + App::Color ec; + ec.setValue(mat.emissiveColor); + float s = mat.shininess; + float t = mat.transparency; + + QString data = QString::fromLatin1("App.Material(" + "DiffuseColor=(%1,%2,%3)," + "AmbientColor=(%4,%5,%6)," + "SpecularColor=(%7,%8,%9)," + "EmissiveColor=(%10,%11,%12)," + "Shininess=(%13)," + "Transparency=(%14)," + ")") + .arg(dc.r, 0, 'f', decimals()) + .arg(dc.g, 0, 'f', decimals()) + .arg(dc.b, 0, 'f', decimals()) + .arg(ac.r, 0, 'f', decimals()) + .arg(ac.g, 0, 'f', decimals()) + .arg(ac.b, 0, 'f', decimals()) + .arg(sc.r, 0, 'f', decimals()) + .arg(sc.g, 0, 'f', decimals()) + .arg(sc.b, 0, 'f', decimals()) + .arg(ec.r, 0, 'f', decimals()) + .arg(ec.g, 0, 'f', decimals()) + .arg(ec.b, 0, 'f', decimals()) + .arg(s, 0, 'f', decimals()) + .arg(t, 0, 'f', decimals()); + + setPropertyValue(data); +} + +QWidget* PropertyMaterialItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto cb = new Gui::ColorButton(parent); + cb->setDisabled(isReadOnly()); + QObject::connect(cb, &Gui::ColorButton::changed, method); + return cb; +} + +void PropertyMaterialItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + if (!data.canConvert()) { + return; + } + + auto val = data.value(); + auto cb = qobject_cast(editor); + cb->setColor(val.diffuseColor); +} + +QVariant PropertyMaterialItem::editorData(QWidget* editor) const +{ + auto cb = qobject_cast(editor); + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + auto val = value.value(); + val.diffuseColor = cb->color(); + return QVariant::fromValue(val); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialListItem) + +PropertyMaterialListItem::PropertyMaterialListItem() +{ + const int min = 0; + const int max = 100; + const int steps = 5; + + // This editor gets a list of materials but it only edits the first item. + diffuse = static_cast(PropertyColorItem::create()); + diffuse->setParent(this); + diffuse->setPropertyName(QLatin1String("DiffuseColor")); + this->appendChild(diffuse); + + ambient = static_cast(PropertyColorItem::create()); + ambient->setParent(this); + ambient->setPropertyName(QLatin1String("AmbientColor")); + this->appendChild(ambient); + + specular = static_cast(PropertyColorItem::create()); + specular->setParent(this); + specular->setPropertyName(QLatin1String("SpecularColor")); + this->appendChild(specular); + + emissive = static_cast(PropertyColorItem::create()); + emissive->setParent(this); + emissive->setPropertyName(QLatin1String("EmissiveColor")); + this->appendChild(emissive); + + shininess = + static_cast(PropertyIntegerConstraintItem::create()); + shininess->setRange(min, max); + shininess->setStepSize(steps); + shininess->setParent(this); + shininess->setPropertyName(QLatin1String("Shininess")); + this->appendChild(shininess); + + transparency = + static_cast(PropertyIntegerConstraintItem::create()); + transparency->setRange(min, max); + transparency->setStepSize(steps); + transparency->setParent(this); + transparency->setPropertyName(QLatin1String("Transparency")); + this->appendChild(transparency); +} + +PropertyMaterialListItem::~PropertyMaterialListItem() = default; + +void PropertyMaterialListItem::propertyBound() +{} + +QColor PropertyMaterialListItem::getDiffuseColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + auto mat = list[0].value(); + return mat.diffuseColor; +} + +void PropertyMaterialListItem::setDiffuseColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.diffuseColor = color; + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +QColor PropertyMaterialListItem::getAmbientColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + auto mat = list[0].value(); + return mat.ambientColor; +} + +void PropertyMaterialListItem::setAmbientColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.ambientColor = color; + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +QColor PropertyMaterialListItem::getSpecularColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + auto mat = list[0].value(); + return mat.specularColor; +} + +void PropertyMaterialListItem::setSpecularColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.specularColor = color; + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +QColor PropertyMaterialListItem::getEmissiveColor() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + auto mat = list[0].value(); + return mat.emissiveColor; +} + +void PropertyMaterialListItem::setEmissiveColor(const QColor& color) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.emissiveColor = color; + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +int PropertyMaterialListItem::getShininess() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return 0; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return 0; + } + + if (!list[0].canConvert()) { + return 0; + } + + auto mat = list[0].value(); + return toPercent(mat.shininess); +} + +void PropertyMaterialListItem::setShininess(int s) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.shininess = fromPercent(s); + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +int PropertyMaterialListItem::getTransparency() const +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return 0; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return 0; + } + + if (!list[0].canConvert()) { + return 0; + } + + auto mat = list[0].value(); + return toPercent(mat.transparency); +} + +void PropertyMaterialListItem::setTransparency(int t) +{ + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + auto mat = list[0].value(); + mat.transparency = fromPercent(t); + list[0] = QVariant::fromValue(mat); + setValue(list); +} + +QVariant PropertyMaterialListItem::decoration(const QVariant& value) const +{ + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + // use the diffuse color + auto mat = list[0].value(); + QColor color = mat.diffuseColor; + + int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); + QPixmap p(size, size); + p.fill(color); + + return QVariant(p); +} + +QVariant PropertyMaterialListItem::toString(const QVariant& prop) const +{ + if (!prop.canConvert()) { + return {}; + } + + QVariantList list = prop.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + // use the diffuse color + auto mat = list[0].value(); + QColor value = mat.diffuseColor; + QString color = + QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + return {color}; +} + +QVariant PropertyMaterialListItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const std::vector& values = + static_cast(prop)->getValues(); + if (values.empty()) { + return {}; + } + + App::Material value = values.front(); + auto dc = value.diffuseColor.asValue(); + auto ac = value.ambientColor.asValue(); + auto sc = value.specularColor.asValue(); + auto ec = value.emissiveColor.asValue(); + + QString data = QString::fromUtf8("Diffuse color: [%1, %2, %3]\n" + "Ambient color: [%4, %5, %6]\n" + "Specular color: [%7, %8, %9]\n" + "Emissive color: [%10, %11, %12]\n" + "Shininess: %13\n" + "Transparency: %14") + .arg(dc.red()) + .arg(dc.green()) + .arg(dc.blue()) + .arg(ac.red()) + .arg(ac.green()) + .arg(ac.blue()) + .arg(sc.red()) + .arg(sc.green()) + .arg(sc.blue()) + .arg(ec.red()) + .arg(ec.green()) + .arg(ec.blue()) + .arg(toPercent(value.shininess)) + .arg(toPercent(value.transparency)); + + return {data}; +} + +QVariant PropertyMaterialListItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + const std::vector& value = + static_cast(prop)->getValues(); + QVariantList variantList; + + for (const auto& it : value) { + Material mat; + mat.diffuseColor = it.diffuseColor.asValue(); + mat.ambientColor = it.ambientColor.asValue(); + mat.specularColor = it.specularColor.asValue(); + mat.emissiveColor = it.emissiveColor.asValue(); + mat.shininess = it.shininess; + mat.transparency = it.transparency; + + variantList << QVariant::fromValue(mat); + } + + return variantList; +} + +void PropertyMaterialListItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return; + } + + // Setting an appearance using the property editor resets the + // per-face appearance + list = list.mid(0, 1); + + QString data; + QTextStream str(&data); + str << "("; + + auto mat = list[0].value(); + App::Color dc; + dc.setValue(mat.diffuseColor); + App::Color ac; + ac.setValue(mat.ambientColor); + App::Color sc; + sc.setValue(mat.specularColor); + App::Color ec; + ec.setValue(mat.emissiveColor); + float s = mat.shininess; + float t = mat.transparency; + + QString item = QString::fromLatin1("App.Material(" + "DiffuseColor=(%1,%2,%3)," + "AmbientColor=(%4,%5,%6)," + "SpecularColor=(%7,%8,%9)," + "EmissiveColor=(%10,%11,%12)," + "Shininess=(%13)," + "Transparency=(%14)," + ")") + .arg(dc.r, 0, 'f', decimals()) + .arg(dc.g, 0, 'f', decimals()) + .arg(dc.b, 0, 'f', decimals()) + .arg(ac.r, 0, 'f', decimals()) + .arg(ac.g, 0, 'f', decimals()) + .arg(ac.b, 0, 'f', decimals()) + .arg(sc.r, 0, 'f', decimals()) + .arg(sc.g, 0, 'f', decimals()) + .arg(sc.b, 0, 'f', decimals()) + .arg(ec.r, 0, 'f', decimals()) + .arg(ec.g, 0, 'f', decimals()) + .arg(ec.b, 0, 'f', decimals()) + .arg(s, 0, 'f', decimals()) + .arg(t, 0, 'f', decimals()); + str << item << ")"; + + setPropertyValue(data); +} + +QWidget* PropertyMaterialListItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto cb = new Gui::ColorButton(parent); + cb->setDisabled(isReadOnly()); + QObject::connect(cb, &Gui::ColorButton::changed, method); + return cb; +} + +void PropertyMaterialListItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + if (!data.canConvert()) { + return; + } + + QVariantList list = data.toList(); + if (list.isEmpty()) { + return; + } + + if (!list[0].canConvert()) { + return; + } + + // use the diffuse color + auto mat = list[0].value(); + QColor color = mat.diffuseColor; + + auto cb = qobject_cast(editor); + cb->setColor(color); +} + +QVariant PropertyMaterialListItem::editorData(QWidget* editor) const +{ + auto cb = qobject_cast(editor); + QVariant value = data(1, Qt::EditRole); + if (!value.canConvert()) { + return {}; + } + + QVariantList list = value.toList(); + if (list.isEmpty()) { + return {}; + } + + if (!list[0].canConvert()) { + return {}; + } + + // use the diffuse color + auto mat = list[0].value(); + mat.diffuseColor = cb->color(); + list[0] = QVariant::fromValue(mat); + + return list; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFileItem) + +PropertyFileItem::PropertyFileItem() = default; + +QVariant PropertyFileItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + std::string value = static_cast(prop)->getValue(); + return {QString::fromUtf8(value.c_str())}; +} + +void PropertyFileItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + QString val = value.toString(); + QString data = QString::fromLatin1("\"%1\"").arg(val); + setPropertyValue(data); +} + +QVariant PropertyFileItem::toolTip(const App::Property* prop) const +{ + return value(prop); +} + +QWidget* PropertyFileItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto fc = new Gui::FileChooser(parent); + fc->setAutoFillBackground(true); + fc->setDisabled(isReadOnly()); + QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); + return fc; +} + +void PropertyFileItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + const App::Property* prop = getFirstProperty(); + if (const auto propFile = dynamic_cast(prop)) { + std::string filter = propFile->getFilter(); + auto fc = qobject_cast(editor); + if (!filter.empty()) { + fc->setFilter(Base::Tools::fromStdString(filter)); + } + fc->setFileName(data.toString()); + } +} + +QVariant PropertyFileItem::editorData(QWidget* editor) const +{ + auto fc = qobject_cast(editor); + return {fc->fileName()}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPathItem) + +PropertyPathItem::PropertyPathItem() = default; + +QVariant PropertyPathItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + std::string value = static_cast(prop)->getValue().string(); + return {QString::fromUtf8(value.c_str())}; +} + +void PropertyPathItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + + QString val = value.toString(); + QString data = QString::fromLatin1("\"%1\"").arg(val); + setPropertyValue(data); +} + +QVariant PropertyPathItem::toolTip(const App::Property* prop) const +{ + return value(prop); +} + +QWidget* PropertyPathItem::createEditor(QWidget* parent, const std::function& method) const +{ + auto fc = new Gui::FileChooser(parent); + fc->setMode(FileChooser::Directory); + fc->setAutoFillBackground(true); + fc->setDisabled(isReadOnly()); + QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); + return fc; +} + +void PropertyPathItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto fc = qobject_cast(editor); + fc->setFileName(data.toString()); +} + +QVariant PropertyPathItem::editorData(QWidget* editor) const +{ + auto fc = qobject_cast(editor); + return {fc->fileName()}; +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyTransientFileItem) + +PropertyTransientFileItem::PropertyTransientFileItem() = default; + +QVariant PropertyTransientFileItem::value(const App::Property* prop) const +{ + assert(prop && prop->isDerivedFrom()); + + std::string value = static_cast(prop)->getValue(); + return {QString::fromUtf8(value.c_str())}; +} + +void PropertyTransientFileItem::setValue(const QVariant& value) +{ + if (hasExpression() || !value.canConvert()) { + return; + } + + QString val = value.toString(); + QString data = QString::fromLatin1("\"%1\"").arg(val); + setPropertyValue(data); +} + +QVariant PropertyTransientFileItem::toolTip(const App::Property* prop) const +{ + return value(prop); +} + +QWidget* PropertyTransientFileItem::createEditor(QWidget* parent, + const std::function& method) const +{ + auto fc = new Gui::FileChooser(parent); + fc->setAutoFillBackground(true); + fc->setDisabled(isReadOnly()); + QObject::connect(fc, &Gui::FileChooser::fileNameSelected, method); + return fc; +} + +void PropertyTransientFileItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + auto fc = qobject_cast(editor); + fc->setFileName(data.toString()); + + const auto prop = dynamic_cast(getFirstProperty()); + + if (prop) { + std::string filter = prop->getFilter(); + if (!filter.empty()) { + fc->setFilter(QString::fromStdString(filter)); + } + } +} + +QVariant PropertyTransientFileItem::editorData(QWidget* editor) const +{ + auto fc = qobject_cast(editor); + return {fc->fileName()}; +} + +// --------------------------------------------------------------- + +LinkSelection::LinkSelection(App::SubObjectT link) + : link(std::move(link)) +{} + +LinkSelection::~LinkSelection() = default; + +void LinkSelection::select() +{ + auto sobj = link.getSubObject(); + if (!sobj) { + QMessageBox::critical(getMainWindow(), tr("Error"), tr("Object not found")); + return; + } + Gui::Selection().selStackPush(); + Gui::Selection().clearSelection(); + Gui::Selection().addSelection(link.getDocumentName().c_str(), + link.getObjectName().c_str(), + link.getSubName().c_str()); + this->deleteLater(); +} + +// --------------------------------------------------------------- + +LinkLabel::LinkLabel(QWidget* parent, const App::Property* prop) + : QWidget(parent) + , objProp(prop) + , dlg(nullptr) +{ + auto layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(1); + + label = new QLabel(this); + label->setAutoFillBackground(true); + label->setTextFormat(Qt::RichText); + // Below is necessary for the hytperlink to be clickable without losing focus + label->setTextInteractionFlags(Qt::TextBrowserInteraction); + layout->addWidget(label); + + editButton = new QPushButton(QLatin1String("..."), this); +#if defined(Q_OS_MACOS) + editButton->setAttribute( + Qt::WA_LayoutUsesWidgetRect); // layout size from QMacStyle was not correct +#endif + editButton->setToolTip(tr("Change the linked object")); + layout->addWidget(editButton); + + this->setFocusPolicy(Qt::StrongFocus); + this->setFocusProxy(label); + + // setLayout(layout); + + connect(label, &QLabel::linkActivated, this, &LinkLabel::onLinkActivated); + connect(editButton, &QPushButton::clicked, this, &LinkLabel::onEditClicked); +} + +LinkLabel::~LinkLabel() = default; + +void LinkLabel::updatePropertyLink() +{ + QString text; + auto owner = objProp.getObject(); + auto prop = Base::freecad_dynamic_cast(objProp.getProperty()); + + link = QVariant(); + + if (owner && prop) { + auto links = DlgPropertyLink::getLinksFromProperty(prop); + if (links.size() == 1) { + auto& sobj = links.front(); + link = QVariant::fromValue(sobj); + QString linkcolor = QApplication::palette().color(QPalette::Link).name(); + text = QString::fromLatin1("" + "

" + "%5" + "

") + .arg(QLatin1String(sobj.getDocumentName().c_str()), + QLatin1String(sobj.getObjectName().c_str()), + QString::fromUtf8(sobj.getSubName().c_str()), + linkcolor, + DlgPropertyLink::formatObject(owner->getDocument(), + sobj.getObject(), + sobj.getSubName().c_str())); + } + else if (!links.empty()) { + text = DlgPropertyLink::formatLinks(owner->getDocument(), links); + } + } + label->setText(text); +} + +QVariant LinkLabel::propertyLink() const +{ + return link; +} + +void LinkLabel::onLinkActivated(const QString& s) +{ + Q_UNUSED(s); + auto select = new LinkSelection(qvariant_cast(link)); + QTimer::singleShot(50, select, &LinkSelection::select); // NOLINT +} + +void LinkLabel::onEditClicked() +{ + if (!dlg) { + dlg = new DlgPropertyLink(this); + dlg->init(objProp, true); + connect(dlg, &DlgPropertyLink::accepted, this, &LinkLabel::onLinkChanged); + } + else { + dlg->init(objProp, false); + } + + dlg->show(); +} + +void LinkLabel::onLinkChanged() +{ + if (dlg) { + auto links = dlg->currentLinks(); + if (links != dlg->originalLinks()) { + link = QVariant::fromValue(links); + Q_EMIT linkChanged(link); + updatePropertyLink(); + } + } +} + +void LinkLabel::resizeEvent(QResizeEvent* e) +{ + editButton->setFixedWidth(e->size().height()); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkItem) + +PropertyLinkItem::PropertyLinkItem() = default; + +QVariant PropertyLinkItem::toString(const QVariant& prop) const +{ + QString res; + if (!propertyItems.empty()) { + App::DocumentObjectT owner(propertyItems[0]); + res = DlgPropertyLink::formatLinks(owner.getDocument(), + qvariant_cast>(prop)); + } + return res; +} + +QVariant PropertyLinkItem::data(int column, int role) const +{ + if (!propertyItems.empty() && column == 1 + && (role == Qt::ForegroundRole || role == Qt::ToolTipRole)) { + if (auto propLink = dynamic_cast(propertyItems[0])) { + if (role == Qt::ForegroundRole && propLink->checkRestore() > 1) { + return QVariant::fromValue(QColor(0xff, 0, 0)); // NOLINT + } + if (role == Qt::ToolTipRole) { + if (auto xlink = dynamic_cast(propertyItems[0])) { + const char* filePath = xlink->getFilePath(); + if (filePath && filePath[0]) { + return QVariant::fromValue(QString::fromUtf8(filePath)); + } + } + } + } + } + + return PropertyItem::data(column, role); +} + +QVariant PropertyLinkItem::value(const App::Property* prop) const +{ + auto propLink = Base::freecad_dynamic_cast(prop); + if (!propLink) { + return {}; + } + + auto links = DlgPropertyLink::getLinksFromProperty(propLink); + if (links.empty()) { + return {}; + } + + return QVariant::fromValue(links); +} + +void PropertyLinkItem::setValue(const QVariant& value) +{ + auto links = qvariant_cast>(value); + setPropertyValue(DlgPropertyLink::linksToPython(links)); +} + +QWidget* PropertyLinkItem::createEditor(QWidget* parent, const std::function& method) const +{ + if (propertyItems.empty()) { + return nullptr; + } + auto ll = new LinkLabel(parent, propertyItems.front()); + ll->setAutoFillBackground(true); + ll->setDisabled(isReadOnly()); + QObject::connect(ll, &LinkLabel::linkChanged, method); + return ll; +} + +void PropertyLinkItem::setEditorData(QWidget* editor, const QVariant& data) const +{ + (void)data; + auto ll = dynamic_cast(editor); + return ll->updatePropertyLink(); +} + +QVariant PropertyLinkItem::editorData(QWidget* editor) const +{ + auto ll = dynamic_cast(editor); + return ll->propertyLink(); +} + +// -------------------------------------------------------------------- + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkListItem) + +PropertyLinkListItem::PropertyLinkListItem() = default; + +PropertyItemEditorFactory::PropertyItemEditorFactory() = default; + +PropertyItemEditorFactory::~PropertyItemEditorFactory() = default; + +QWidget* PropertyItemEditorFactory::createEditor(int /*type*/, QWidget* /*parent*/) const +{ + // do not allow to create any editor widgets because we do that in subclasses of PropertyItem + return nullptr; +} + +QByteArray PropertyItemEditorFactory::valuePropertyName(int /*type*/) const +{ + // do not allow to set properties because we do that in subclasses of PropertyItem + return ""; +} +// NOLINTEND(cppcoreguidelines-pro-*,cppcoreguidelines-prefer-member-initializer) + +#include "moc_PropertyItem.cpp" diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index 54d9ca860df3..682826232b8e 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -1,1272 +1,1304 @@ -/*************************************************************************** - * Copyright (c) 2004 Werner Mayer * - * * - * 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 PROPERTYEDITORITEM_H -#define PROPERTYEDITORITEM_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef Q_MOC_RUN -Q_DECLARE_METATYPE(Base::Vector3f) -Q_DECLARE_METATYPE(Base::Vector3d) -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(Base::Matrix4D) -Q_DECLARE_METATYPE(Base::Placement) -Q_DECLARE_METATYPE(Base::Rotation) -Q_DECLARE_METATYPE(Base::Quantity) -Q_DECLARE_METATYPE(QList) -#endif - - -#define PROPERTYITEM_HEADER \ -public: \ - static void *create(void); \ - static void init(void); - -#define PROPERTYITEM_SOURCE(_class_) \ -void * _class_::create(void) { \ - return new _class_ ();\ -} \ -void _class_::init(void) { \ - (void)new Gui::PropertyEditor::PropertyItemProducer<_class_>(#_class_); \ -} - -namespace Gui { - -namespace Dialog { -class TaskPlacement; -class DlgPropertyLink; -} - -namespace PropertyEditor { - -class PropertyItem; -class PropertyModel; -class PropertyEditorWidget; - -/** - * The PropertyItemFactory provides methods for the dynamic creation of property items. - * \author Werner Mayer - */ -class GuiExport PropertyItemFactory : public Base::Factory -{ -public: - static PropertyItemFactory& instance(); - - PropertyItem* createPropertyItem (const char* sName) const; - -private: - PropertyItemFactory() = default; - ~PropertyItemFactory() override = default; -}; - -template -class PropertyItemProducer : public Base::AbstractProducer -{ -public: - explicit PropertyItemProducer(const char* className) { - PropertyItemFactory::instance().AddProducer(className, this); - } - ~PropertyItemProducer() override = default; - void* Produce () const override { - return CLASS::create(); - } -}; - -class PropertyItemAttorney { -public: - static QVariant toString(PropertyItem* item, const QVariant& v); -}; - -class GuiExport PropertyItem : public QObject, public ExpressionBinding -{ - Q_OBJECT - PROPERTYITEM_HEADER - -public: - ~PropertyItem() override; - - /** Sets the current property objects. */ - void setPropertyData( const std::vector& ); - void updateData(); - const std::vector& getPropertyData() const; - bool hasProperty(const App::Property*) const; - virtual void assignProperty(const App::Property*); - bool removeProperty(const App::Property*); - App::Property* getFirstProperty(); - const App::Property* getFirstProperty() const; - - /** Creates the appropriate editor for this item and sets the editor to the value of overrideValue(). */ - virtual QWidget* createEditor(QWidget* parent, const std::function& method) const; - virtual void setEditorData(QWidget *editor, const QVariant& data) const; - virtual QVariant editorData(QWidget *editor) const; - virtual bool isSeparator() const { return false; } - - QWidget* createExpressionEditor(QWidget* parent, const std::function& method) const; - void setExpressionEditorData(QWidget *editor, const QVariant& data) const; - QVariant expressionEditorData(QWidget *editor) const; - - PropertyEditorWidget* createPropertyEditorWidget(QWidget* parent) const; - - /**override the bind functions to ensure we issue the propertyBound() call, which is then overloaded by - childs which like to be informed of a binding*/ - void bind(const App::Property& prop) override; - void bind(const App::ObjectIdentifier& _path) override; - virtual void propertyBound() {} - QString expressionAsString() const; - - void setParent(PropertyItem* parent); - PropertyItem *parent() const; - void appendChild(PropertyItem *child); - void insertChild(int, PropertyItem *child); - void moveChild(int from, int to); - void removeChildren(int from, int to); - PropertyItem *takeChild(int); - - void setReadOnly(bool); - bool isReadOnly() const; - bool testStatus(App::Property::Status pos) const; - void setDecimals(int); - int decimals() const; - - void setLinked(bool); - bool isLinked() const; - - bool isExpanded() const; - void setExpanded(bool e); - - PropertyItem *child(int row); - int childCount() const; - int columnCount() const; - QString propertyName() const; - void setPropertyName(const QString& name, const QString& realName=QString()); - void setPropertyValue(const QString&); - virtual QVariant data(int column, int role) const; - bool setData (const QVariant& value); - Qt::ItemFlags flags(int column) const; - virtual int row() const; - void reset(); - - bool hasAnyExpression() const; - -protected: - PropertyItem(); - - virtual QVariant displayName() const; - virtual QVariant decoration(const QVariant&) const; - virtual QVariant toolTip(const App::Property*) const; - virtual QVariant toString(const QVariant&) const; - virtual QVariant value(const App::Property*) const; - virtual void setValue(const QVariant&); - virtual void initialize(); - - //gets called when the bound expression is changed - void onChange() override; - -private: - QVariant dataProperty(int role) const; - QVariant dataValue(int role) const; - QString toString(const Py::Object&) const; - QString asNone(const Py::Object&) const; - QString asString(const Py::Object&) const; - QString asSequence(const Py::Object&) const; - QString asMapping(const Py::Object&) const; - -protected: - QString propName; - QString displayText; - std::vector propertyItems; - PropertyItem *parentItem; - QList childItems; - bool readonly; - int precision; - bool linked; - bool expanded; - - friend class PropertyItemAttorney; -}; - -/** - * Change a string property. - * \author Werner Mayer - */ -class GuiExport PropertyStringItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyStringItem(); -}; - -/** - * Change a font property. - * \author Werner Mayer - */ -class GuiExport PropertyFontItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyFontItem(); -}; - -/** - * Dummy property to separate groups of properties. - * \author Werner Mayer - */ -class GuiExport PropertySeparatorItem : public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - bool isSeparator() const override { return true; } - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - - int row() const override { - return _row<0?PropertyItem::row():_row; - } - -private: - friend PropertyModel; - int _row = -1; -}; - -/** - * Change a number. - * \author Werner Mayer - */ -class GuiExport PropertyIntegerItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyIntegerItem(); -}; - -/** - * Change a number with constraints. - * \author Werner Mayer - */ -class GuiExport PropertyIntegerConstraintItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void setRange(int min, int max) - { - this->min = min; - this->max = max; - } - - void setStepSize(int steps) - { - this->steps = steps; - } - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyIntegerConstraintItem(); - -private: - int min = INT_MIN; - int max = INT_MAX; - int steps = 1; -}; - -/** - * Change a floating point number. - * \author Werner Mayer - */ -class GuiExport PropertyFloatItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyFloatItem(); -}; - -/** - * Change a Unit based floating point number. - * \author Juergen Riegel - */ -class GuiExport PropertyUnitItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - - PropertyUnitItem(); -}; - -/** - * Change a Unit based floating point number within constraints. - * \author Stefan Troeger - */ -class GuiExport PropertyUnitConstraintItem: public PropertyUnitItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - void setEditorData(QWidget *editor, const QVariant& data) const override; - - void setRange(double min, double max) - { - this->min = min; - this->max = max; - } - - void setStepSize(double steps) - { - this->steps = steps; - } - -protected: - PropertyUnitConstraintItem(); - -private: - double min = double(INT_MIN); - double max = double(INT_MAX); - double steps = 0.1; -}; - -/** - * Change a floating point number with constraints. - * \author Werner Mayer - */ -class GuiExport PropertyFloatConstraintItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void setRange(double min, double max) - { - this->min = min; - this->max = max; - } - - void setStepSize(double steps) - { - this->steps = steps; - } - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyFloatConstraintItem(); - -private: - double min = double(INT_MIN); - double max = double(INT_MAX); - double steps = 0.1; -}; - -/** - * Change a floating point number with many decimal points (hard coded as 16) - */ -class GuiExport PropertyPrecisionItem: public PropertyFloatConstraintItem -{ - Q_OBJECT - PROPERTYITEM_HEADER -protected: - PropertyPrecisionItem(); -}; - -/** - * Change a floating point number. - * \author Werner Mayer - */ -class GuiExport PropertyAngleItem : public PropertyUnitConstraintItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - -protected: - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant toString(const QVariant&) const override; - -protected: - PropertyAngleItem(); -}; - -/** - * Edit properties of boolean type. - * \author Werner Mayer - */ -class GuiExport PropertyBoolItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyBoolItem(); -}; - -/** - * Edit properties of vector type. - * \author Werner Mayer - */ -class PropertyFloatItem; -class GuiExport PropertyVectorItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(double x READ x WRITE setX DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double y READ y WRITE setY DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double z READ z WRITE setZ DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - double x() const; - void setX(double x); - double y() const; - void setY(double y); - double z() const; - void setZ(double z); - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyVectorItem(); - void propertyBound() override; - -private: - PropertyFloatItem* m_x; - PropertyFloatItem* m_y; - PropertyFloatItem* m_z; -}; - -class PropertyEditorWidget : public QWidget -{ - Q_OBJECT - -public: - explicit PropertyEditorWidget (QWidget * parent = nullptr); - ~PropertyEditorWidget() override; - - QVariant value() const; - -public Q_SLOTS: - void setValue(const QVariant&); - -protected: - virtual void showValue(const QVariant& data); - void resizeEvent(QResizeEvent*) override; - -Q_SIGNALS: - void buttonClick(); - void valueChanged(const QVariant &); - -protected: - QVariant variant; - QLineEdit *lineEdit; - QPushButton *button; -}; - -class VectorListWidget : public PropertyEditorWidget -{ - Q_OBJECT - -public: - explicit VectorListWidget (int decimals, QWidget * parent = nullptr); - -protected: - void showValue(const QVariant& data) override; - -private Q_SLOTS: - void buttonClicked(); - -private: - int decimals; -}; - -/** - * Edit properties of vector list type. - * \author Werner Mayer - */ -class GuiExport PropertyVectorListItem : public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyVectorListItem(); -}; - -/** - * Edit properties of vector type which hold distances. - * \author Stefan Troeger - */ -class PropertyUnitItem; -class GuiExport PropertyVectorDistanceItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(Base::Quantity x READ x WRITE setX DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(Base::Quantity y READ y WRITE setY DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(Base::Quantity z READ z WRITE setZ DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void propertyBound() override; - - Base::Quantity x() const; - void setX(Base::Quantity x); - Base::Quantity y() const; - void setY(Base::Quantity y); - Base::Quantity z() const; - void setZ(Base::Quantity z); - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - - PropertyVectorDistanceItem(); - -private: - PropertyUnitItem* m_x; - PropertyUnitItem* m_y; - PropertyUnitItem* m_z; -}; - -class GuiExport PropertyPositionItem: public PropertyVectorDistanceItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - -}; - -class GuiExport PropertyDirectionItem: public PropertyVectorDistanceItem -{ - Q_OBJECT - PROPERTYITEM_HEADER -}; - -class GuiExport PropertyMatrixItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(double A11 READ getA11 WRITE setA11 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A12 READ getA12 WRITE setA12 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A13 READ getA13 WRITE setA13 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A14 READ getA14 WRITE setA14 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A21 READ getA21 WRITE setA21 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A22 READ getA22 WRITE setA22 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A23 READ getA23 WRITE setA23 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A24 READ getA24 WRITE setA24 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A31 READ getA31 WRITE setA31 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A32 READ getA32 WRITE setA32 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A33 READ getA33 WRITE setA33 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A34 READ getA34 WRITE setA34 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A41 READ getA41 WRITE setA41 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A42 READ getA42 WRITE setA42 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A43 READ getA43 WRITE setA43 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(double A44 READ getA44 WRITE setA44 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - double getA11() const; - void setA11(double A11); - double getA12() const; - void setA12(double A12); - double getA13() const; - void setA13(double A13); - double getA14() const; - void setA14(double A14); - double getA21() const; - void setA21(double A21); - double getA22() const; - void setA22(double A22); - double getA23() const; - void setA23(double A23); - double getA24() const; - void setA24(double A24); - double getA31() const; - void setA31(double A31); - double getA32() const; - void setA32(double A32); - double getA33() const; - void setA33(double A33); - double getA34() const; - void setA34(double A34); - double getA41() const; - void setA41(double A41); - double getA42() const; - void setA42(double A42); - double getA43() const; - void setA43(double A43); - double getA44() const; - void setA44(double A44); - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyMatrixItem(); - QVariant toolTip(const App::Property*) const override; - -private: - PropertyFloatItem* m_a11; - PropertyFloatItem* m_a12; - PropertyFloatItem* m_a13; - PropertyFloatItem* m_a14; - PropertyFloatItem* m_a21; - PropertyFloatItem* m_a22; - PropertyFloatItem* m_a23; - PropertyFloatItem* m_a24; - PropertyFloatItem* m_a31; - PropertyFloatItem* m_a32; - PropertyFloatItem* m_a33; - PropertyFloatItem* m_a34; - PropertyFloatItem* m_a41; - PropertyFloatItem* m_a42; - PropertyFloatItem* m_a43; - PropertyFloatItem* m_a44; -}; - -class RotationHelper -{ -public: - RotationHelper(); - void setChanged(bool); - bool hasChangedAndReset(); - bool isAxisInitialized() const; - void setValue(const Base::Vector3d& axis, double angle); - void getValue(Base::Vector3d& axis, double& angle) const; - double getAngle(const Base::Rotation& val) const; - Base::Rotation setAngle(double); - Base::Vector3d getAxis() const; - Base::Rotation setAxis(const Base::Rotation& value, const Base::Vector3d& axis); - void assignProperty(const Base::Rotation& value, double eps); - -private: - bool init_axis; - bool changed_value; - double rot_angle; - Base::Vector3d rot_axis; -}; - -/** - * Edit properties of rotation type. - * \author Werner Mayer - */ -class GuiExport PropertyRotationItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(Base::Quantity Angle READ getAngle WRITE setAngle DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(Base::Vector3d Axis READ getAxis WRITE setAxis DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void propertyBound() override; - void assignProperty(const App::Property*) override; - - Base::Quantity getAngle() const; - void setAngle(Base::Quantity); - Base::Vector3d getAxis() const; - void setAxis(const Base::Vector3d&); - -protected: - PropertyRotationItem(); - ~PropertyRotationItem() override; - QVariant toolTip(const App::Property*) const override; - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -private: - mutable RotationHelper h; - PropertyUnitItem * m_a; - PropertyVectorItem* m_d; -}; - -class PlacementEditor : public Gui::LabelButton -{ - Q_OBJECT - -public: - explicit PlacementEditor(QString name, QWidget * parent = nullptr); - ~PlacementEditor() override; - -private Q_SLOTS: - void updateValue(const QVariant& v, bool, bool); - -private: - void browse() override; - void showValue(const QVariant& d) override; - -private: - QPointer _task; - QString propertyname; -}; - -/** - * Edit properties of placement type. - * \author Werner Mayer - */ -class GuiExport PropertyPlacementItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(Base::Quantity Angle READ getAngle WRITE setAngle DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(Base::Vector3d Axis READ getAxis WRITE setAxis DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(Base::Vector3d Position READ getPosition WRITE setPosition DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void propertyBound() override; - void assignProperty(const App::Property*) override; - - Base::Quantity getAngle() const; - void setAngle(Base::Quantity); - Base::Vector3d getAxis() const; - void setAxis(const Base::Vector3d&); - Base::Vector3d getPosition() const; - void setPosition(const Base::Vector3d&); - -protected: - PropertyPlacementItem(); - ~PropertyPlacementItem() override; - QVariant toolTip(const App::Property*) const override; - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -private: - mutable RotationHelper h; - PropertyUnitItem * m_a; - PropertyVectorItem* m_d; - PropertyVectorDistanceItem* m_p; -}; - -class PropertyStringListItem; - -/** - * Edit properties of enum type. - * \author Werner Mayer - */ -class GuiExport PropertyEnumItem: public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(QStringList Enum READ getEnum WRITE setEnum DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - QStringList getEnum() const; - void setEnum(const QStringList&); - -private: - QStringList getCommonModes() const; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - void propertyBound() override; - -protected: - PropertyEnumItem(); - -private: - PropertyStringListItem* m_enum; -}; - -class PropertyEnumButton : public QPushButton -{ - Q_OBJECT -public: - explicit PropertyEnumButton(QWidget *parent = nullptr) - :QPushButton(parent) - {} - -Q_SIGNALS: - void picked(); -}; - -/** - * Edit properties of string list type. - * \author Werner Mayer - */ -class GuiExport PropertyStringListItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyStringListItem(); -}; - -/** - * Edit properties of float list type. - * \author Werner Mayer - */ -class GuiExport PropertyFloatListItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyFloatListItem(); -}; - -/** - * Edit properties of float list type. - * \author Werner Mayer - */ -class GuiExport PropertyIntegerListItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyIntegerListItem(); -}; - -/** - * Change a color property. - * \author Werner Mayer - */ -class GuiExport PropertyColorItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant decoration(const QVariant&) const override; - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyColorItem(); -}; - -/** -* Change a material property. -* \author Werner Mayer -*/ -class GuiExport PropertyMaterialItem : public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(QColor AmbientColor READ getAmbientColor WRITE setAmbientColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor DiffuseColor READ getDiffuseColor WRITE setDiffuseColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor SpecularColor READ getSpecularColor WRITE setSpecularColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor EmissiveColor READ getEmissiveColor WRITE setEmissiveColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(float Shininess READ getShininess WRITE setShininess DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(float Transparency READ getTransparency WRITE setTransparency DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void propertyBound() override; - - QColor getAmbientColor() const; - void setAmbientColor(const QColor&); - QColor getDiffuseColor() const; - void setDiffuseColor(const QColor&); - QColor getSpecularColor() const; - void setSpecularColor(const QColor&); - QColor getEmissiveColor() const; - void setEmissiveColor(const QColor&); - int getShininess() const; - void setShininess(int); - int getTransparency() const; - void setTransparency(int); - -protected: - PropertyMaterialItem(); - ~PropertyMaterialItem() override; - - QVariant decoration(const QVariant&) const override; - QVariant toolTip(const App::Property*) const override; - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -private: - PropertyColorItem* ambient; - PropertyColorItem* diffuse; - PropertyColorItem* specular; - PropertyColorItem* emissive; - PropertyIntegerConstraintItem* shininess; - PropertyIntegerConstraintItem* transparency; -}; - -class GuiExport PropertyMaterialListItem : public PropertyItem -{ - Q_OBJECT - Q_PROPERTY(QColor AmbientColor READ getAmbientColor WRITE setAmbientColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor DiffuseColor READ getDiffuseColor WRITE setDiffuseColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor SpecularColor READ getSpecularColor WRITE setSpecularColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(QColor EmissiveColor READ getEmissiveColor WRITE setEmissiveColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(float Shininess READ getShininess WRITE setShininess DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - Q_PROPERTY(float Transparency READ getTransparency WRITE setTransparency DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - - void propertyBound() override; - - QColor getAmbientColor() const; - void setAmbientColor(const QColor&); - QColor getDiffuseColor() const; - void setDiffuseColor(const QColor&); - QColor getSpecularColor() const; - void setSpecularColor(const QColor&); - QColor getEmissiveColor() const; - void setEmissiveColor(const QColor&); - int getShininess() const; - void setShininess(int); - int getTransparency() const; - void setTransparency(int); - -protected: - PropertyMaterialListItem(); - ~PropertyMaterialListItem() override; - - QVariant decoration(const QVariant&) const override; - QVariant toolTip(const App::Property*) const override; - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -private: - PropertyColorItem* ambient; - PropertyColorItem* diffuse; - PropertyColorItem* specular; - PropertyColorItem* emissive; - PropertyIntegerConstraintItem* shininess; - PropertyIntegerConstraintItem* transparency; -}; - -/** - * Change a file. - * \author Werner Mayer - */ -class GuiExport PropertyFileItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyFileItem(); - QVariant toolTip(const App::Property*) const override; -}; - -/** - * Change a path. - * \author Werner Mayer - */ -class GuiExport PropertyPathItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyPathItem(); - QVariant toolTip(const App::Property*) const override; -}; - -/** - * Show path of included file. - * \author Werner Mayer - */ -class GuiExport PropertyTransientFileItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - -protected: - PropertyTransientFileItem(); - QVariant toolTip(const App::Property*) const override; -}; - -class LinkSelection : public QObject -{ - Q_OBJECT - -public: - explicit LinkSelection(App::SubObjectT); - ~LinkSelection() override; - -public Q_SLOTS: - void select(); - -private: - App::SubObjectT link; -}; - - -class LinkLabel : public QWidget -{ - Q_OBJECT - -public: - LinkLabel (QWidget * parent, const App::Property *prop); - ~LinkLabel() override; - void updatePropertyLink(); - QVariant propertyLink() const; - -protected: - void resizeEvent(QResizeEvent*) override; - -protected Q_SLOTS: - void onLinkActivated(const QString&); - void onEditClicked(); - void onLinkChanged(); - -Q_SIGNALS: - void linkChanged(const QVariant&); - -private: - QLabel* label; - QPushButton* editButton; - QVariant link; - App::DocumentObjectT objProp; - - Gui::Dialog::DlgPropertyLink* dlg; -}; - -/** - * Edit properties of link type. - * \author Werner Mayer - */ -class GuiExport PropertyLinkItem: public PropertyItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - - QWidget* createEditor(QWidget* parent, const std::function& method) const override; - void setEditorData(QWidget *editor, const QVariant& data) const override; - QVariant editorData(QWidget *editor) const override; - -protected: - QVariant toString(const QVariant&) const override; - QVariant value(const App::Property*) const override; - void setValue(const QVariant&) override; - QVariant data(int column, int role) const override; - -protected: - PropertyLinkItem(); -}; - -/** - * Edit properties of link list type. - * \author Werner Mayer - */ -class GuiExport PropertyLinkListItem: public PropertyLinkItem -{ - Q_OBJECT - PROPERTYITEM_HEADER - -protected: - PropertyLinkListItem(); -}; - -class PropertyItemEditorFactory : public QItemEditorFactory -{ -public: - PropertyItemEditorFactory(); - ~PropertyItemEditorFactory() override; - - QWidget *createEditor(int userType, QWidget *parent) const override; - QByteArray valuePropertyName(int userType) const override; -}; - -} // namespace PropertyEditor -} // namespace Gui - -#endif // PROPERTYEDITORITEM_H +/*************************************************************************** + * Copyright (c) 2004 Werner Mayer * + * * + * 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 PROPERTYEDITORITEM_H +#define PROPERTYEDITORITEM_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef Q_MOC_RUN +Q_DECLARE_METATYPE(Base::Vector3f) +Q_DECLARE_METATYPE(Base::Vector3d) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(Base::Matrix4D) +Q_DECLARE_METATYPE(Base::Placement) +Q_DECLARE_METATYPE(Base::Rotation) +Q_DECLARE_METATYPE(Base::Quantity) +Q_DECLARE_METATYPE(QList) +#endif + + +#define PROPERTYITEM_HEADER \ +public: \ + static void* create(void); \ + static void init(void); + +#define PROPERTYITEM_SOURCE(_class_) \ + void* _class_::create(void) \ + { \ + return new _class_(); \ + } \ + void _class_::init(void) \ + { \ + (void)new Gui::PropertyEditor::PropertyItemProducer<_class_>(#_class_); \ + } + +namespace Gui +{ + +namespace Dialog +{ +class TaskPlacement; +class DlgPropertyLink; +} // namespace Dialog + +namespace PropertyEditor +{ + +class PropertyItem; +class PropertyModel; +class PropertyEditorWidget; + +/** + * The PropertyItemFactory provides methods for the dynamic creation of property items. + * \author Werner Mayer + */ +class GuiExport PropertyItemFactory: public Base::Factory +{ +public: + static PropertyItemFactory& instance(); + + PropertyItem* createPropertyItem(const char* sName) const; + +private: + PropertyItemFactory() = default; + ~PropertyItemFactory() override = default; +}; + +template +class PropertyItemProducer: public Base::AbstractProducer +{ +public: + explicit PropertyItemProducer(const char* className) + { + PropertyItemFactory::instance().AddProducer(className, this); + } + ~PropertyItemProducer() override = default; + void* Produce() const override + { + return CLASS::create(); + } +}; + +class PropertyItemAttorney +{ +public: + static QVariant toString(PropertyItem* item, const QVariant& v); +}; + +class GuiExport PropertyItem: public QObject, public ExpressionBinding +{ + Q_OBJECT + PROPERTYITEM_HEADER + +public: + ~PropertyItem() override; + + /** Sets the current property objects. */ + void setPropertyData(const std::vector&); + void updateData(); + const std::vector& getPropertyData() const; + bool hasProperty(const App::Property*) const; + virtual void assignProperty(const App::Property*); + bool removeProperty(const App::Property*); + App::Property* getFirstProperty(); + const App::Property* getFirstProperty() const; + + /** Creates the appropriate editor for this item and sets the editor to the value of + * overrideValue(). */ + virtual QWidget* createEditor(QWidget* parent, const std::function& method) const; + virtual void setEditorData(QWidget* editor, const QVariant& data) const; + virtual QVariant editorData(QWidget* editor) const; + virtual bool isSeparator() const + { + return false; + } + + QWidget* createExpressionEditor(QWidget* parent, const std::function& method) const; + void setExpressionEditorData(QWidget* editor, const QVariant& data) const; + QVariant expressionEditorData(QWidget* editor) const; + + PropertyEditorWidget* createPropertyEditorWidget(QWidget* parent) const; + + /**override the bind functions to ensure we issue the propertyBound() call, which is then + overloaded by childs which like to be informed of a binding*/ + void bind(const App::Property& prop) override; + void bind(const App::ObjectIdentifier& _path) override; + virtual void propertyBound() + {} + QString expressionAsString() const; + + void setParent(PropertyItem* parent); + PropertyItem* parent() const; + void appendChild(PropertyItem* child); + void insertChild(int, PropertyItem* child); + void moveChild(int from, int to); + void removeChildren(int from, int to); + PropertyItem* takeChild(int); + + void setReadOnly(bool); + bool isReadOnly() const; + bool testStatus(App::Property::Status pos) const; + void setDecimals(int); + int decimals() const; + + void setLinked(bool); + bool isLinked() const; + + bool isExpanded() const; + void setExpanded(bool e); + + PropertyItem* child(int row); + int childCount() const; + int columnCount() const; + QString propertyName() const; + void setPropertyName(const QString& name, const QString& realName = QString()); + void setPropertyValue(const QString&); + virtual QVariant data(int column, int role) const; + bool setData(const QVariant& value); + Qt::ItemFlags flags(int column) const; + virtual int row() const; + void reset(); + + bool hasAnyExpression() const; + +protected: + PropertyItem(); + + virtual QVariant displayName() const; + virtual QVariant decoration(const QVariant&) const; + virtual QVariant toolTip(const App::Property*) const; + virtual QVariant toString(const QVariant&) const; + virtual QVariant value(const App::Property*) const; + virtual void setValue(const QVariant&); + virtual void initialize(); + + // gets called when the bound expression is changed + void onChange() override; + +private: + QVariant dataProperty(int role) const; + QVariant dataValue(int role) const; + QString toString(const Py::Object&) const; + QString asNone(const Py::Object&) const; + QString asString(const Py::Object&) const; + QString asSequence(const Py::Object&) const; + QString asMapping(const Py::Object&) const; + +protected: + QString propName; + QString displayText; + std::vector propertyItems; + PropertyItem* parentItem; + QList childItems; + bool readonly; + int precision; + bool linked; + bool expanded; + + friend class PropertyItemAttorney; +}; + +/** + * Change a string property. + * \author Werner Mayer + */ +class GuiExport PropertyStringItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyStringItem(); +}; + +/** + * Change a font property. + * \author Werner Mayer + */ +class GuiExport PropertyFontItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyFontItem(); +}; + +/** + * Dummy property to separate groups of properties. + * \author Werner Mayer + */ +class GuiExport PropertySeparatorItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + bool isSeparator() const override + { + return true; + } + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + + int row() const override + { + return _row < 0 ? PropertyItem::row() : _row; + } + +private: + friend PropertyModel; + int _row = -1; +}; + +/** + * Change a number. + * \author Werner Mayer + */ +class GuiExport PropertyIntegerItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyIntegerItem(); +}; + +/** + * Change a number with constraints. + * \author Werner Mayer + */ +class GuiExport PropertyIntegerConstraintItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void setRange(int min, int max) + { + this->min = min; + this->max = max; + } + + void setStepSize(int steps) + { + this->steps = steps; + } + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyIntegerConstraintItem(); + +private: + int min = INT_MIN; + int max = INT_MAX; + int steps = 1; +}; + +/** + * Change a floating point number. + * \author Werner Mayer + */ +class GuiExport PropertyFloatItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyFloatItem(); +}; + +/** + * Change a Unit based floating point number. + * \author Juergen Riegel + */ +class GuiExport PropertyUnitItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + + PropertyUnitItem(); +}; + +/** + * Change a Unit based floating point number within constraints. + * \author Stefan Troeger + */ +class GuiExport PropertyUnitConstraintItem: public PropertyUnitItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + void setEditorData(QWidget* editor, const QVariant& data) const override; + + void setRange(double min, double max) + { + this->min = min; + this->max = max; + } + + void setStepSize(double steps) + { + this->steps = steps; + } + +protected: + PropertyUnitConstraintItem(); + +private: + double min = double(INT_MIN); + double max = double(INT_MAX); + double steps = 0.1; +}; + +/** + * Change a floating point number with constraints. + * \author Werner Mayer + */ +class GuiExport PropertyFloatConstraintItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void setRange(double min, double max) + { + this->min = min; + this->max = max; + } + + void setStepSize(double steps) + { + this->steps = steps; + } + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyFloatConstraintItem(); + +private: + double min = double(INT_MIN); + double max = double(INT_MAX); + double steps = 0.1; +}; + +/** + * Change a floating point number with many decimal points (hard coded as 16) + */ +class GuiExport PropertyPrecisionItem: public PropertyFloatConstraintItem +{ + Q_OBJECT + PROPERTYITEM_HEADER +protected: + PropertyPrecisionItem(); +}; + +/** + * Change a floating point number. + * \author Werner Mayer + */ +class GuiExport PropertyAngleItem: public PropertyUnitConstraintItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + +protected: + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant toString(const QVariant&) const override; + +protected: + PropertyAngleItem(); +}; + +/** + * Edit properties of boolean type. + * \author Werner Mayer + */ +class GuiExport PropertyBoolItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyBoolItem(); +}; + +/** + * Edit properties of vector type. + * \author Werner Mayer + */ +class PropertyFloatItem; +class GuiExport PropertyVectorItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(double x READ x WRITE setX DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double y READ y WRITE setY DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double z READ z WRITE setZ DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + double x() const; + void setX(double x); + double y() const; + void setY(double y); + double z() const; + void setZ(double z); + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyVectorItem(); + void propertyBound() override; + +private: + PropertyFloatItem* m_x; + PropertyFloatItem* m_y; + PropertyFloatItem* m_z; +}; + +class PropertyEditorWidget: public QWidget +{ + Q_OBJECT + +public: + explicit PropertyEditorWidget(QWidget* parent = nullptr); + ~PropertyEditorWidget() override; + + QVariant value() const; + +public Q_SLOTS: + void setValue(const QVariant&); + +protected: + virtual void showValue(const QVariant& data); + void resizeEvent(QResizeEvent*) override; + +Q_SIGNALS: + void buttonClick(); + void valueChanged(const QVariant&); + +protected: + QVariant variant; + QLineEdit* lineEdit; + QPushButton* button; +}; + +class VectorListWidget: public PropertyEditorWidget +{ + Q_OBJECT + +public: + explicit VectorListWidget(int decimals, QWidget* parent = nullptr); + +protected: + void showValue(const QVariant& data) override; + +private Q_SLOTS: + void buttonClicked(); + +private: + int decimals; +}; + +/** + * Edit properties of vector list type. + * \author Werner Mayer + */ +class GuiExport PropertyVectorListItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyVectorListItem(); +}; + +/** + * Edit properties of vector type which hold distances. + * \author Stefan Troeger + */ +class PropertyUnitItem; +class GuiExport PropertyVectorDistanceItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(Base::Quantity x READ x WRITE setX DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(Base::Quantity y READ y WRITE setY DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(Base::Quantity z READ z WRITE setZ DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void propertyBound() override; + + Base::Quantity x() const; + void setX(Base::Quantity x); + Base::Quantity y() const; + void setY(Base::Quantity y); + Base::Quantity z() const; + void setZ(Base::Quantity z); + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + + PropertyVectorDistanceItem(); + +private: + PropertyUnitItem* m_x; + PropertyUnitItem* m_y; + PropertyUnitItem* m_z; +}; + +class GuiExport PropertyPositionItem: public PropertyVectorDistanceItem +{ + Q_OBJECT + PROPERTYITEM_HEADER +}; + +class GuiExport PropertyDirectionItem: public PropertyVectorDistanceItem +{ + Q_OBJECT + PROPERTYITEM_HEADER +}; + +class GuiExport PropertyMatrixItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(double A11 READ getA11 WRITE setA11 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A12 READ getA12 WRITE setA12 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A13 READ getA13 WRITE setA13 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A14 READ getA14 WRITE setA14 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A21 READ getA21 WRITE setA21 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A22 READ getA22 WRITE setA22 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A23 READ getA23 WRITE setA23 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A24 READ getA24 WRITE setA24 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A31 READ getA31 WRITE setA31 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A32 READ getA32 WRITE setA32 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A33 READ getA33 WRITE setA33 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A34 READ getA34 WRITE setA34 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A41 READ getA41 WRITE setA41 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A42 READ getA42 WRITE setA42 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A43 READ getA43 WRITE setA43 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(double A44 READ getA44 WRITE setA44 DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + double getA11() const; + void setA11(double A11); + double getA12() const; + void setA12(double A12); + double getA13() const; + void setA13(double A13); + double getA14() const; + void setA14(double A14); + double getA21() const; + void setA21(double A21); + double getA22() const; + void setA22(double A22); + double getA23() const; + void setA23(double A23); + double getA24() const; + void setA24(double A24); + double getA31() const; + void setA31(double A31); + double getA32() const; + void setA32(double A32); + double getA33() const; + void setA33(double A33); + double getA34() const; + void setA34(double A34); + double getA41() const; + void setA41(double A41); + double getA42() const; + void setA42(double A42); + double getA43() const; + void setA43(double A43); + double getA44() const; + void setA44(double A44); + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyMatrixItem(); + QVariant toolTip(const App::Property*) const override; + +private: + PropertyFloatItem* m_a11; + PropertyFloatItem* m_a12; + PropertyFloatItem* m_a13; + PropertyFloatItem* m_a14; + PropertyFloatItem* m_a21; + PropertyFloatItem* m_a22; + PropertyFloatItem* m_a23; + PropertyFloatItem* m_a24; + PropertyFloatItem* m_a31; + PropertyFloatItem* m_a32; + PropertyFloatItem* m_a33; + PropertyFloatItem* m_a34; + PropertyFloatItem* m_a41; + PropertyFloatItem* m_a42; + PropertyFloatItem* m_a43; + PropertyFloatItem* m_a44; +}; + +class RotationHelper +{ +public: + RotationHelper(); + void setChanged(bool); + bool hasChangedAndReset(); + bool isAxisInitialized() const; + void setValue(const Base::Vector3d& axis, double angle); + void getValue(Base::Vector3d& axis, double& angle) const; + double getAngle(const Base::Rotation& val) const; + Base::Rotation setAngle(double); + Base::Vector3d getAxis() const; + Base::Rotation setAxis(const Base::Rotation& value, const Base::Vector3d& axis); + void assignProperty(const Base::Rotation& value, double eps); + +private: + bool init_axis; + bool changed_value; + double rot_angle; + Base::Vector3d rot_axis; +}; + +/** + * Edit properties of rotation type. + * \author Werner Mayer + */ +class GuiExport PropertyRotationItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(Base::Quantity Angle READ getAngle WRITE setAngle DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(Base::Vector3d Axis READ getAxis WRITE setAxis DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void propertyBound() override; + void assignProperty(const App::Property*) override; + + Base::Quantity getAngle() const; + void setAngle(Base::Quantity); + Base::Vector3d getAxis() const; + void setAxis(const Base::Vector3d&); + +protected: + PropertyRotationItem(); + ~PropertyRotationItem() override; + QVariant toolTip(const App::Property*) const override; + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +private: + mutable RotationHelper h; + PropertyUnitItem* m_a; + PropertyVectorItem* m_d; +}; + +class PlacementEditor: public Gui::LabelButton +{ + Q_OBJECT + +public: + explicit PlacementEditor(QString name, QWidget* parent = nullptr); + ~PlacementEditor() override; + +private Q_SLOTS: + void updateValue(const QVariant& v, bool, bool); + +private: + void browse() override; + void showValue(const QVariant& d) override; + +private: + QPointer _task; + QString propertyname; +}; + +/** + * Edit properties of placement type. + * \author Werner Mayer + */ +class GuiExport PropertyPlacementItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(Base::Quantity Angle READ getAngle WRITE setAngle DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(Base::Vector3d Axis READ getAxis WRITE setAxis DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(Base::Vector3d Position READ getPosition WRITE setPosition DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void propertyBound() override; + void assignProperty(const App::Property*) override; + + Base::Quantity getAngle() const; + void setAngle(Base::Quantity); + Base::Vector3d getAxis() const; + void setAxis(const Base::Vector3d&); + Base::Vector3d getPosition() const; + void setPosition(const Base::Vector3d&); + +protected: + PropertyPlacementItem(); + ~PropertyPlacementItem() override; + QVariant toolTip(const App::Property*) const override; + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +private: + mutable RotationHelper h; + PropertyUnitItem* m_a; + PropertyVectorItem* m_d; + PropertyVectorDistanceItem* m_p; +}; + +class PropertyStringListItem; + +/** + * Edit properties of enum type. + * \author Werner Mayer + */ +class GuiExport PropertyEnumItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(QStringList Enum READ getEnum WRITE setEnum DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + QStringList getEnum() const; + void setEnum(const QStringList&); + +private: + QStringList getCommonModes() const; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + void propertyBound() override; + +protected: + PropertyEnumItem(); + +private: + PropertyStringListItem* m_enum; +}; + +class PropertyEnumButton: public QPushButton +{ + Q_OBJECT +public: + explicit PropertyEnumButton(QWidget* parent = nullptr) + : QPushButton(parent) + {} + +Q_SIGNALS: + void picked(); +}; + +/** + * Edit properties of string list type. + * \author Werner Mayer + */ +class GuiExport PropertyStringListItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyStringListItem(); +}; + +/** + * Edit properties of float list type. + * \author Werner Mayer + */ +class GuiExport PropertyFloatListItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyFloatListItem(); +}; + +/** + * Edit properties of float list type. + * \author Werner Mayer + */ +class GuiExport PropertyIntegerListItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyIntegerListItem(); +}; + +/** + * Change a color property. + * \author Werner Mayer + */ +class GuiExport PropertyColorItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant decoration(const QVariant&) const override; + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyColorItem(); +}; + +/** + * Change a material property. + * \author Werner Mayer + */ +class GuiExport PropertyMaterialItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(QColor AmbientColor READ getAmbientColor WRITE setAmbientColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor DiffuseColor READ getDiffuseColor WRITE setDiffuseColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor SpecularColor READ getSpecularColor WRITE setSpecularColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor EmissiveColor READ getEmissiveColor WRITE setEmissiveColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(float Shininess READ getShininess WRITE setShininess DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(float Transparency READ getTransparency WRITE setTransparency DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void propertyBound() override; + + QColor getAmbientColor() const; + void setAmbientColor(const QColor&); + QColor getDiffuseColor() const; + void setDiffuseColor(const QColor&); + QColor getSpecularColor() const; + void setSpecularColor(const QColor&); + QColor getEmissiveColor() const; + void setEmissiveColor(const QColor&); + int getShininess() const; + void setShininess(int); + int getTransparency() const; + void setTransparency(int); + +protected: + PropertyMaterialItem(); + ~PropertyMaterialItem() override; + + QVariant decoration(const QVariant&) const override; + QVariant toolTip(const App::Property*) const override; + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +private: + PropertyColorItem* ambient; + PropertyColorItem* diffuse; + PropertyColorItem* specular; + PropertyColorItem* emissive; + PropertyIntegerConstraintItem* shininess; + PropertyIntegerConstraintItem* transparency; +}; + +class GuiExport PropertyMaterialListItem: public PropertyItem +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(QColor AmbientColor READ getAmbientColor WRITE setAmbientColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor DiffuseColor READ getDiffuseColor WRITE setDiffuseColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor SpecularColor READ getSpecularColor WRITE setSpecularColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(QColor EmissiveColor READ getEmissiveColor WRITE setEmissiveColor DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(float Shininess READ getShininess WRITE setShininess DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + Q_PROPERTY(float Transparency READ getTransparency WRITE setTransparency DESIGNABLE true USER true) // clazy:exclude=qproperty-without-notify + PROPERTYITEM_HEADER + // clang-format on + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + + void propertyBound() override; + + QColor getAmbientColor() const; + void setAmbientColor(const QColor&); + QColor getDiffuseColor() const; + void setDiffuseColor(const QColor&); + QColor getSpecularColor() const; + void setSpecularColor(const QColor&); + QColor getEmissiveColor() const; + void setEmissiveColor(const QColor&); + int getShininess() const; + void setShininess(int); + int getTransparency() const; + void setTransparency(int); + +protected: + PropertyMaterialListItem(); + ~PropertyMaterialListItem() override; + + QVariant decoration(const QVariant&) const override; + QVariant toolTip(const App::Property*) const override; + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +private: + PropertyColorItem* ambient; + PropertyColorItem* diffuse; + PropertyColorItem* specular; + PropertyColorItem* emissive; + PropertyIntegerConstraintItem* shininess; + PropertyIntegerConstraintItem* transparency; +}; + +/** + * Change a file. + * \author Werner Mayer + */ +class GuiExport PropertyFileItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyFileItem(); + QVariant toolTip(const App::Property*) const override; +}; + +/** + * Change a path. + * \author Werner Mayer + */ +class GuiExport PropertyPathItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyPathItem(); + QVariant toolTip(const App::Property*) const override; +}; + +/** + * Show path of included file. + * \author Werner Mayer + */ +class GuiExport PropertyTransientFileItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + +protected: + PropertyTransientFileItem(); + QVariant toolTip(const App::Property*) const override; +}; + +class LinkSelection: public QObject +{ + Q_OBJECT + +public: + explicit LinkSelection(App::SubObjectT); + ~LinkSelection() override; + +public Q_SLOTS: + void select(); + +private: + App::SubObjectT link; +}; + + +class LinkLabel: public QWidget +{ + Q_OBJECT + +public: + LinkLabel(QWidget* parent, const App::Property* prop); + ~LinkLabel() override; + void updatePropertyLink(); + QVariant propertyLink() const; + +protected: + void resizeEvent(QResizeEvent*) override; + +protected Q_SLOTS: + void onLinkActivated(const QString&); + void onEditClicked(); + void onLinkChanged(); + +Q_SIGNALS: + void linkChanged(const QVariant&); + +private: + QLabel* label; + QPushButton* editButton; + QVariant link; + App::DocumentObjectT objProp; + + Gui::Dialog::DlgPropertyLink* dlg; +}; + +/** + * Edit properties of link type. + * \author Werner Mayer + */ +class GuiExport PropertyLinkItem: public PropertyItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + + QWidget* createEditor(QWidget* parent, const std::function& method) const override; + void setEditorData(QWidget* editor, const QVariant& data) const override; + QVariant editorData(QWidget* editor) const override; + +protected: + QVariant toString(const QVariant&) const override; + QVariant value(const App::Property*) const override; + void setValue(const QVariant&) override; + QVariant data(int column, int role) const override; + +protected: + PropertyLinkItem(); +}; + +/** + * Edit properties of link list type. + * \author Werner Mayer + */ +class GuiExport PropertyLinkListItem: public PropertyLinkItem +{ + Q_OBJECT + PROPERTYITEM_HEADER + +protected: + PropertyLinkListItem(); +}; + +class PropertyItemEditorFactory: public QItemEditorFactory +{ +public: + PropertyItemEditorFactory(); + ~PropertyItemEditorFactory() override; + + QWidget* createEditor(int userType, QWidget* parent) const override; + QByteArray valuePropertyName(int userType) const override; +}; + +} // namespace PropertyEditor +} // namespace Gui + +#endif // PROPERTYEDITORITEM_H diff --git a/src/Gui/propertyeditor/PropertyModel.cpp b/src/Gui/propertyeditor/PropertyModel.cpp index 1b9e356c5e27..d20c8e0dfa66 100644 --- a/src/Gui/propertyeditor/PropertyModel.cpp +++ b/src/Gui/propertyeditor/PropertyModel.cpp @@ -1,559 +1,600 @@ -/*************************************************************************** - * Copyright (c) 2004 Werner Mayer * - * * - * 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 -#endif - -#include "PropertyItem.h" -#include "PropertyModel.h" -#include "PropertyView.h" - - -using namespace Gui; -using namespace Gui::PropertyEditor; - - -/* TRANSLATOR Gui::PropertyEditor::PropertyModel */ - -PropertyModel::PropertyModel(QObject* parent) - : QAbstractItemModel(parent) -{ - rootItem = static_cast(PropertyItem::create()); -} - -PropertyModel::~PropertyModel() -{ - delete rootItem; -} - -QModelIndex PropertyModel::buddy ( const QModelIndex & index ) const -{ - if (index.column() == 1) - return index; - return index.sibling(index.row(), 1); -} - -int PropertyModel::columnCount ( const QModelIndex & parent ) const -{ - // , hence always 2 - if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return rootItem->columnCount(); -} - -QVariant PropertyModel::data ( const QModelIndex & index, int role ) const -{ - if (!index.isValid()) - return {}; - - auto item = static_cast(index.internalPointer()); - return item->data(index.column(), role); -} - -bool PropertyModel::setData(const QModelIndex& index, const QVariant & value, int role) -{ - if (!index.isValid()) - return false; - - // we check whether the data has really changed, otherwise we ignore it - if (role == Qt::EditRole) { - auto item = static_cast(index.internalPointer()); - QVariant data = item->data(index.column(), role); - if (data.userType() == QMetaType::Double && value.userType() == QMetaType::Double) { - // since we store some properties as floats we get some round-off - // errors here. Thus, we use an epsilon here. - // NOTE: Since 0.14 PropertyFloat uses double precision, so this is maybe unnecessary now? - double d = data.toDouble(); - double v = value.toDouble(); - if (fabs(d-v) > DBL_EPSILON) - return item->setData(value); - } - // Special case handling for quantities - else if (data.canConvert() && value.canConvert()) { - const Base::Quantity& val1 = data.value(); - const Base::Quantity& val2 = value.value(); - if (!(val1 == val2)) - return item->setData(value); - } - else if (data != value) - return item->setData(value); - } - - return true; -} - -Qt::ItemFlags PropertyModel::flags(const QModelIndex &index) const -{ - auto item = static_cast(index.internalPointer()); - return item->flags(index.column()); -} - -QModelIndex PropertyModel::index ( int row, int column, const QModelIndex & parent ) const -{ - PropertyItem *parentItem; - - if (!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - PropertyItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return {}; -} - -QModelIndex PropertyModel::parent ( const QModelIndex & index ) const -{ - if (!index.isValid()) - return {}; - - auto childItem = static_cast(index.internalPointer()); - PropertyItem *parentItem = childItem->parent(); - - if (parentItem == rootItem) - return {}; - - return createIndex(parentItem->row(), 0, parentItem); -} - -int PropertyModel::rowCount ( const QModelIndex & parent ) const -{ - PropertyItem *parentItem; - - if (!parent.isValid()) - parentItem = rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -QVariant PropertyModel::headerData (int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal) { - if (role != Qt::DisplayRole) - return {}; - if (section == 0) - return tr("Property"); - if (section == 1) - return tr("Value"); - } - - return {}; -} - -bool PropertyModel::setHeaderData (int, Qt::Orientation, const QVariant &, int) -{ - return false; -} - -QStringList PropertyModel::propertyPathFromIndex(const QModelIndex& index) const -{ - QStringList path; - if (index.isValid()) { - auto item = static_cast(index.internalPointer()); - while (item && item != this->rootItem) { - path.push_front(item->propertyName()); - item = item->parent(); - } - } - - return path; -} - -QModelIndex PropertyModel::propertyIndexFromPath(const QStringList& path) const -{ - if (path.size() < 2) - return {}; - - auto it = groupItems.find(path.front()); - if (it == groupItems.end()) - return {}; - - PropertyItem *item = it->second.groupItem; - QModelIndex index = this->index(item->row(), 0, QModelIndex()); - - for (int j=1; jchildCount(); ichild(i); - if (child->propertyName() == path[j]) { - index = this->index(i, 1, index); - item = child; - found = true; - break; - } - } - if (!found) - return j==1?QModelIndex():index; - } - return index; -} - -static void setPropertyItemName(PropertyItem *item, const char *propName, QString groupName) { - QString name = QString::fromLatin1(propName); - QString realName = name; - if(name.size()>groupName.size()+1 - && name.startsWith(groupName + QLatin1Char('_'))) - name = name.right(name.size()-groupName.size()-1); - - item->setPropertyName(name, realName); -} - -static PropertyItem *createPropertyItem(App::Property *prop) -{ - const char *editor = prop->getEditorName(); - if (!editor || !editor[0]) { - if (PropertyView::showAll()) - editor = "Gui::PropertyEditor::PropertyItem"; - else - return nullptr; - } - auto item = static_cast( - PropertyItemFactory::instance().createPropertyItem(editor)); - if (!item) { - qWarning("No property item for type %s found\n", editor); - } - return item; -} - -PropertyModel::GroupInfo &PropertyModel::getGroupInfo(App::Property *prop) -{ - const char* group = prop->getGroup(); - bool isEmpty = (!group || group[0] == '\0'); - QString groupName = QString::fromLatin1( - isEmpty ? QT_TRANSLATE_NOOP("App::Property", "Base") : group); - - auto res = groupItems.insert(std::make_pair(groupName, GroupInfo())); - if (res.second) { - auto &groupInfo = res.first->second; - groupInfo.groupItem = static_cast(PropertySeparatorItem::create()); - groupInfo.groupItem->setReadOnly(true); - groupInfo.groupItem->setExpanded(true); - groupInfo.groupItem->setParent(rootItem); - groupInfo.groupItem->setPropertyName(groupName); - - auto it = res.first; - int row = 0; - if (it != groupItems.begin()) { - --it; - row = it->second.groupItem->_row + 1; - ++it; - } - groupInfo.groupItem->_row = row; - beginInsertRows(QModelIndex(), row, row); - rootItem->insertChild(row, groupInfo.groupItem); - // update row index for all group items behind - for (++it; it!=groupItems.end(); ++it) - ++it->second.groupItem->_row; - endInsertRows(); - } - - return res.first->second; -} - -void PropertyModel::buildUp(const PropertyModel::PropertyList& props) -{ - // If props empty, then simply reset all property items, but keep the group - // items. - if (props.empty()) { - resetGroups(); - return; - } - - // First step, init group info - initGroups(); - - // Second step, either find existing items or create new items for the given - // properties. There is no signaling of model change at this stage. The - // change information is kept pending in GroupInfo::children - findOrCreateChildren(props); - - // Third step, signal item insertion and movement. - insertOrMoveChildren(); - - - // Final step, signal item removal. This is separated from the above because - // of the possibility of moving items between groups. - removeChildren(); -} - -void PropertyModel::resetGroups() -{ - beginResetModel(); - for(auto &v : groupItems) { - auto &groupInfo = v.second; - groupInfo.groupItem->reset(); - groupInfo.children.clear(); - } - itemMap.clear(); - endResetModel(); -} - -void PropertyModel::initGroups() -{ - for (auto &v : groupItems) { - auto &groupInfo = v.second; - groupInfo.children.clear(); - } -} - -void PropertyModel::findOrCreateChildren(const PropertyModel::PropertyList& props) -{ - for (const auto & jt : props) { - App::Property* prop = jt.second.front(); - - PropertyItem *item = nullptr; - for (auto prop : jt.second) { - auto it = itemMap.find(prop); - if (it == itemMap.end() || !it->second) { - continue; - } - item = it->second; - break; - } - - if (!item) { - item = createPropertyItem(prop); - if (!item) { - continue; - } - } - - GroupInfo &groupInfo = getGroupInfo(prop); - groupInfo.children.push_back(item); - - item->setLinked(boost::ends_with(jt.first,"*")); - setPropertyItemName(item, prop->getName(), groupInfo.groupItem->propertyName()); - - if (jt.second != item->getPropertyData()) { - for (auto prop : item->getPropertyData()) { - itemMap.erase(prop); - } - for (auto prop : jt.second) { - itemMap[prop] = item; - } - // TODO: is it necessary to make sure the item has no pending commit? - item->setPropertyData(jt.second); - } - else { - item->updateData(); - } - } -} - -void PropertyModel::insertOrMoveChildren() -{ - for (auto &v : groupItems) { - auto &groupInfo = v.second; - int beginChange = -1; - int endChange = 0; - int beginInsert = -1; - int endInsert = 0; - int row = -1; - QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); - - auto flushInserts = [&]() { - if (beginInsert < 0) - return; - beginInsertRows(midx, beginInsert, endInsert); - for (int i=beginInsert; i<=endInsert; ++i) - groupInfo.groupItem->insertChild(i, groupInfo.children[i]); - endInsertRows(); - beginInsert = -1; - }; - - auto flushChanges = [&]() { - if (beginChange < 0) - return; - (void)endChange; - // There is no need to signal dataChange(), because PropertyEditor - // will call PropertyModel::updateProperty() on any property - // changes. - // - // dataChanged(this->index(beginChange,0,midx), this->index(endChange,1,midx)); - beginChange = -1; - }; - - for (auto item : groupInfo.children) { - ++row; - if (!item->parent()) { - flushChanges(); - item->setParent(groupInfo.groupItem); - if (beginInsert < 0) { - beginInsert = row; - } - endInsert = row; - } - else { - flushInserts(); - int oldRow = item->row(); - // Dynamic property can rename group, so must check - auto groupItem = item->parent(); - assert(groupItem); - if (oldRow == row && groupItem == groupInfo.groupItem) { - if (beginChange < 0) - beginChange = row; - endChange = row; - } - else { - flushChanges(); - beginMoveRows(createIndex(groupItem->row(), 0, groupItem), - oldRow, oldRow, midx, row); - if (groupItem == groupInfo.groupItem) { - groupInfo.groupItem->moveChild(oldRow, row); - } - else { - groupItem->takeChild(oldRow); - item->setParent(groupInfo.groupItem); - groupInfo.groupItem->insertChild(row, item); - } - endMoveRows(); - } - } - } - - flushChanges(); - flushInserts(); - } -} - -void PropertyModel::removeChildren() -{ - for (auto &v : groupItems) { - auto &groupInfo = v.second; - int first, last; - getRange(groupInfo, first, last); - if (last > first) { - QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); - // This can trigger a recursive call of PropertyView::onTimer() - beginRemoveRows(midx, first, last - 1); - groupInfo.groupItem->removeChildren(first, last - 1); - endRemoveRows(); - } - else { - assert(last == first); - } - } -} - -void PropertyModel::getRange(const PropertyModel::GroupInfo& groupInfo, int& first, int& last) const -{ - first = static_cast(groupInfo.children.size()); - last = groupInfo.groupItem->childCount(); -} - -void PropertyModel::updateProperty(const App::Property& prop) -{ - auto it = itemMap.find(const_cast(&prop)); - if (it == itemMap.end() || !it->second || !it->second->parent()) - return; - - int column = 1; - PropertyItem *item = it->second; - item->updateData(); - QModelIndex parent = this->index(item->parent()->row(), 0, QModelIndex()); - item->assignProperty(&prop); - QModelIndex data = this->index(item->row(), column, parent); - Q_EMIT dataChanged(data, data); - updateChildren(item, column, data); -} - -void PropertyModel::appendProperty(const App::Property& _prop) -{ - auto prop = const_cast(&_prop); - if (!prop->getName()) - return; - auto it = itemMap.find(prop); - if (it == itemMap.end() || !it->second) - return; - - PropertyItem *item = createPropertyItem(prop); - GroupInfo &groupInfo = getGroupInfo(prop); - - int row = 0; - for (int c=groupInfo.groupItem->childCount(); rowchild(row); - App::Property *firstProp = item->getFirstProperty(); - if (firstProp && firstProp->testStatus(App::Property::PropDynamic) - && item->propertyName() >= child->propertyName()) - break; - } - - QModelIndex midx = this->index(groupInfo.groupItem->_row,0,QModelIndex()); - beginInsertRows(midx, row, row); - groupInfo.groupItem->insertChild(row, item); - setPropertyItemName(item, prop->getName(), groupInfo.groupItem->propertyName()); - item->setPropertyData({prop}); - endInsertRows(); -} - -void PropertyModel::removeProperty(const App::Property& _prop) -{ - auto prop = const_cast(&_prop); - auto it = itemMap.find(prop); - if (it == itemMap.end() || !it->second) - return; - - PropertyItem *item = it->second; - if (item->removeProperty(prop)) { - PropertyItem *parent = item->parent(); - int row = item->row(); - beginRemoveRows(this->index(parent->row(), 0, QModelIndex()), row, row); - parent->removeChildren(row,row); - endRemoveRows(); - } -} - -void PropertyModel::updateChildren(PropertyItem* item, int column, const QModelIndex& parent) -{ - int numChild = item->childCount(); - if (numChild > 0) { - QModelIndex topLeft = this->index(0, column, parent); - QModelIndex bottomRight = this->index(numChild, column, parent); - Q_EMIT dataChanged(topLeft, bottomRight); - } -} - -bool PropertyModel::removeRows(int row, int count, const QModelIndex& parent) -{ - PropertyItem* item; - if (!parent.isValid()) - item = rootItem; - else - item = static_cast(parent.internalPointer()); - - int start = row; - int end = row+count-1; - beginRemoveRows(parent, start, end); - item->removeChildren(start, end); - endRemoveRows(); - return true; -} - -#include "moc_PropertyModel.cpp" +/*************************************************************************** + * Copyright (c) 2004 Werner Mayer * + * * + * 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 +#endif + +#include "PropertyItem.h" +#include "PropertyModel.h" +#include "PropertyView.h" + + +using namespace Gui; +using namespace Gui::PropertyEditor; + + +/* TRANSLATOR Gui::PropertyEditor::PropertyModel */ + +PropertyModel::PropertyModel(QObject* parent) + : QAbstractItemModel(parent) +{ + rootItem = static_cast(PropertyItem::create()); +} + +PropertyModel::~PropertyModel() +{ + delete rootItem; +} + +QModelIndex PropertyModel::buddy(const QModelIndex& index) const +{ + if (index.column() == 1) { + return index; + } + return index.sibling(index.row(), 1); +} + +int PropertyModel::columnCount(const QModelIndex& parent) const +{ + // , hence always 2 + if (parent.isValid()) { + return static_cast(parent.internalPointer())->columnCount(); + } + else { + return rootItem->columnCount(); + } +} + +QVariant PropertyModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) { + return {}; + } + + auto item = static_cast(index.internalPointer()); + return item->data(index.column(), role); +} + +bool PropertyModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (!index.isValid()) { + return false; + } + + // we check whether the data has really changed, otherwise we ignore it + if (role == Qt::EditRole) { + auto item = static_cast(index.internalPointer()); + QVariant data = item->data(index.column(), role); + if (data.userType() == QMetaType::Double && value.userType() == QMetaType::Double) { + // since we store some properties as floats we get some round-off + // errors here. Thus, we use an epsilon here. + // NOTE: Since 0.14 PropertyFloat uses double precision, so this is maybe unnecessary + // now? + double d = data.toDouble(); + double v = value.toDouble(); + if (fabs(d - v) > DBL_EPSILON) { + return item->setData(value); + } + } + // Special case handling for quantities + else if (data.canConvert() && value.canConvert()) { + const Base::Quantity& val1 = data.value(); + const Base::Quantity& val2 = value.value(); + if (!(val1 == val2)) { + return item->setData(value); + } + } + else if (data != value) { + return item->setData(value); + } + } + + return true; +} + +Qt::ItemFlags PropertyModel::flags(const QModelIndex& index) const +{ + auto item = static_cast(index.internalPointer()); + return item->flags(index.column()); +} + +QModelIndex PropertyModel::index(int row, int column, const QModelIndex& parent) const +{ + PropertyItem* parentItem; + + if (!parent.isValid()) { + parentItem = rootItem; + } + else { + parentItem = static_cast(parent.internalPointer()); + } + + PropertyItem* childItem = parentItem->child(row); + if (childItem) { + return createIndex(row, column, childItem); + } + else { + return {}; + } +} + +QModelIndex PropertyModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) { + return {}; + } + + auto childItem = static_cast(index.internalPointer()); + PropertyItem* parentItem = childItem->parent(); + + if (parentItem == rootItem) { + return {}; + } + + return createIndex(parentItem->row(), 0, parentItem); +} + +int PropertyModel::rowCount(const QModelIndex& parent) const +{ + PropertyItem* parentItem; + + if (!parent.isValid()) { + parentItem = rootItem; + } + else { + parentItem = static_cast(parent.internalPointer()); + } + + return parentItem->childCount(); +} + +QVariant PropertyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) { + if (role != Qt::DisplayRole) { + return {}; + } + if (section == 0) { + return tr("Property"); + } + if (section == 1) { + return tr("Value"); + } + } + + return {}; +} + +bool PropertyModel::setHeaderData(int, Qt::Orientation, const QVariant&, int) +{ + return false; +} + +QStringList PropertyModel::propertyPathFromIndex(const QModelIndex& index) const +{ + QStringList path; + if (index.isValid()) { + auto item = static_cast(index.internalPointer()); + while (item && item != this->rootItem) { + path.push_front(item->propertyName()); + item = item->parent(); + } + } + + return path; +} + +QModelIndex PropertyModel::propertyIndexFromPath(const QStringList& path) const +{ + if (path.size() < 2) { + return {}; + } + + auto it = groupItems.find(path.front()); + if (it == groupItems.end()) { + return {}; + } + + PropertyItem* item = it->second.groupItem; + QModelIndex index = this->index(item->row(), 0, QModelIndex()); + + for (int j = 1; j < path.size(); ++j) { + bool found = false; + for (int i = 0, c = item->childCount(); i < c; ++i) { + auto child = item->child(i); + if (child->propertyName() == path[j]) { + index = this->index(i, 1, index); + item = child; + found = true; + break; + } + } + if (!found) { + return j == 1 ? QModelIndex() : index; + } + } + return index; +} + +static void setPropertyItemName(PropertyItem* item, const char* propName, QString groupName) +{ + QString name = QString::fromLatin1(propName); + QString realName = name; + if (name.size() > groupName.size() + 1 && name.startsWith(groupName + QLatin1Char('_'))) { + name = name.right(name.size() - groupName.size() - 1); + } + + item->setPropertyName(name, realName); +} + +static PropertyItem* createPropertyItem(App::Property* prop) +{ + const char* editor = prop->getEditorName(); + if (!editor || !editor[0]) { + if (PropertyView::showAll()) { + editor = "Gui::PropertyEditor::PropertyItem"; + } + else { + return nullptr; + } + } + auto item = + static_cast(PropertyItemFactory::instance().createPropertyItem(editor)); + if (!item) { + qWarning("No property item for type %s found\n", editor); + } + return item; +} + +PropertyModel::GroupInfo& PropertyModel::getGroupInfo(App::Property* prop) +{ + const char* group = prop->getGroup(); + bool isEmpty = (!group || group[0] == '\0'); + QString groupName = + QString::fromLatin1(isEmpty ? QT_TRANSLATE_NOOP("App::Property", "Base") : group); + + auto res = groupItems.insert(std::make_pair(groupName, GroupInfo())); + if (res.second) { + auto& groupInfo = res.first->second; + groupInfo.groupItem = static_cast(PropertySeparatorItem::create()); + groupInfo.groupItem->setReadOnly(true); + groupInfo.groupItem->setExpanded(true); + groupInfo.groupItem->setParent(rootItem); + groupInfo.groupItem->setPropertyName(groupName); + + auto it = res.first; + int row = 0; + if (it != groupItems.begin()) { + --it; + row = it->second.groupItem->_row + 1; + ++it; + } + groupInfo.groupItem->_row = row; + beginInsertRows(QModelIndex(), row, row); + rootItem->insertChild(row, groupInfo.groupItem); + // update row index for all group items behind + for (++it; it != groupItems.end(); ++it) { + ++it->second.groupItem->_row; + } + endInsertRows(); + } + + return res.first->second; +} + +void PropertyModel::buildUp(const PropertyModel::PropertyList& props) +{ + // If props empty, then simply reset all property items, but keep the group + // items. + if (props.empty()) { + resetGroups(); + return; + } + + // First step, init group info + initGroups(); + + // Second step, either find existing items or create new items for the given + // properties. There is no signaling of model change at this stage. The + // change information is kept pending in GroupInfo::children + findOrCreateChildren(props); + + // Third step, signal item insertion and movement. + insertOrMoveChildren(); + + + // Final step, signal item removal. This is separated from the above because + // of the possibility of moving items between groups. + removeChildren(); +} + +void PropertyModel::resetGroups() +{ + beginResetModel(); + for (auto& v : groupItems) { + auto& groupInfo = v.second; + groupInfo.groupItem->reset(); + groupInfo.children.clear(); + } + itemMap.clear(); + endResetModel(); +} + +void PropertyModel::initGroups() +{ + for (auto& v : groupItems) { + auto& groupInfo = v.second; + groupInfo.children.clear(); + } +} + +void PropertyModel::findOrCreateChildren(const PropertyModel::PropertyList& props) +{ + for (const auto& jt : props) { + App::Property* prop = jt.second.front(); + + PropertyItem* item = nullptr; + for (auto prop : jt.second) { + auto it = itemMap.find(prop); + if (it == itemMap.end() || !it->second) { + continue; + } + item = it->second; + break; + } + + if (!item) { + item = createPropertyItem(prop); + if (!item) { + continue; + } + } + + GroupInfo& groupInfo = getGroupInfo(prop); + groupInfo.children.push_back(item); + + item->setLinked(boost::ends_with(jt.first, "*")); + setPropertyItemName(item, prop->getName(), groupInfo.groupItem->propertyName()); + + if (jt.second != item->getPropertyData()) { + for (auto prop : item->getPropertyData()) { + itemMap.erase(prop); + } + for (auto prop : jt.second) { + itemMap[prop] = item; + } + // TODO: is it necessary to make sure the item has no pending commit? + item->setPropertyData(jt.second); + } + else { + item->updateData(); + } + } +} + +void PropertyModel::insertOrMoveChildren() +{ + for (auto& v : groupItems) { + auto& groupInfo = v.second; + int beginChange = -1; + int endChange = 0; + int beginInsert = -1; + int endInsert = 0; + int row = -1; + QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); + + auto flushInserts = [&]() { + if (beginInsert < 0) { + return; + } + beginInsertRows(midx, beginInsert, endInsert); + for (int i = beginInsert; i <= endInsert; ++i) { + groupInfo.groupItem->insertChild(i, groupInfo.children[i]); + } + endInsertRows(); + beginInsert = -1; + }; + + auto flushChanges = [&]() { + if (beginChange < 0) { + return; + } + (void)endChange; + // There is no need to signal dataChange(), because PropertyEditor + // will call PropertyModel::updateProperty() on any property + // changes. + // + // dataChanged(this->index(beginChange,0,midx), this->index(endChange,1,midx)); + beginChange = -1; + }; + + for (auto item : groupInfo.children) { + ++row; + if (!item->parent()) { + flushChanges(); + item->setParent(groupInfo.groupItem); + if (beginInsert < 0) { + beginInsert = row; + } + endInsert = row; + } + else { + flushInserts(); + int oldRow = item->row(); + // Dynamic property can rename group, so must check + auto groupItem = item->parent(); + assert(groupItem); + if (oldRow == row && groupItem == groupInfo.groupItem) { + if (beginChange < 0) { + beginChange = row; + } + endChange = row; + } + else { + flushChanges(); + beginMoveRows(createIndex(groupItem->row(), 0, groupItem), + oldRow, + oldRow, + midx, + row); + if (groupItem == groupInfo.groupItem) { + groupInfo.groupItem->moveChild(oldRow, row); + } + else { + groupItem->takeChild(oldRow); + item->setParent(groupInfo.groupItem); + groupInfo.groupItem->insertChild(row, item); + } + endMoveRows(); + } + } + } + + flushChanges(); + flushInserts(); + } +} + +void PropertyModel::removeChildren() +{ + for (auto& v : groupItems) { + auto& groupInfo = v.second; + int first, last; + getRange(groupInfo, first, last); + if (last > first) { + QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); + // This can trigger a recursive call of PropertyView::onTimer() + beginRemoveRows(midx, first, last - 1); + groupInfo.groupItem->removeChildren(first, last - 1); + endRemoveRows(); + } + else { + assert(last == first); + } + } +} + +void PropertyModel::getRange(const PropertyModel::GroupInfo& groupInfo, int& first, int& last) const +{ + first = static_cast(groupInfo.children.size()); + last = groupInfo.groupItem->childCount(); +} + +void PropertyModel::updateProperty(const App::Property& prop) +{ + auto it = itemMap.find(const_cast(&prop)); + if (it == itemMap.end() || !it->second || !it->second->parent()) { + return; + } + + int column = 1; + PropertyItem* item = it->second; + item->updateData(); + QModelIndex parent = this->index(item->parent()->row(), 0, QModelIndex()); + item->assignProperty(&prop); + QModelIndex data = this->index(item->row(), column, parent); + Q_EMIT dataChanged(data, data); + updateChildren(item, column, data); +} + +void PropertyModel::appendProperty(const App::Property& _prop) +{ + auto prop = const_cast(&_prop); + if (!prop->getName()) { + return; + } + auto it = itemMap.find(prop); + if (it == itemMap.end() || !it->second) { + return; + } + + PropertyItem* item = createPropertyItem(prop); + GroupInfo& groupInfo = getGroupInfo(prop); + + int row = 0; + for (int c = groupInfo.groupItem->childCount(); row < c; ++row) { + PropertyItem* child = groupInfo.groupItem->child(row); + App::Property* firstProp = item->getFirstProperty(); + if (firstProp && firstProp->testStatus(App::Property::PropDynamic) + && item->propertyName() >= child->propertyName()) { + break; + } + } + + QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); + beginInsertRows(midx, row, row); + groupInfo.groupItem->insertChild(row, item); + setPropertyItemName(item, prop->getName(), groupInfo.groupItem->propertyName()); + item->setPropertyData({prop}); + endInsertRows(); +} + +void PropertyModel::removeProperty(const App::Property& _prop) +{ + auto prop = const_cast(&_prop); + auto it = itemMap.find(prop); + if (it == itemMap.end() || !it->second) { + return; + } + + PropertyItem* item = it->second; + if (item->removeProperty(prop)) { + PropertyItem* parent = item->parent(); + int row = item->row(); + beginRemoveRows(this->index(parent->row(), 0, QModelIndex()), row, row); + parent->removeChildren(row, row); + endRemoveRows(); + } +} + +void PropertyModel::updateChildren(PropertyItem* item, int column, const QModelIndex& parent) +{ + int numChild = item->childCount(); + if (numChild > 0) { + QModelIndex topLeft = this->index(0, column, parent); + QModelIndex bottomRight = this->index(numChild, column, parent); + Q_EMIT dataChanged(topLeft, bottomRight); + } +} + +bool PropertyModel::removeRows(int row, int count, const QModelIndex& parent) +{ + PropertyItem* item; + if (!parent.isValid()) { + item = rootItem; + } + else { + item = static_cast(parent.internalPointer()); + } + + int start = row; + int end = row + count - 1; + beginRemoveRows(parent, start, end); + item->removeChildren(start, end); + endRemoveRows(); + return true; +} + +#include "moc_PropertyModel.cpp" From a80c87c3a750bd2451087bafa18c0858cbfd8116 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Sat, 2 Nov 2024 19:44:00 +0100 Subject: [PATCH 108/161] Gui: propertyeditor: add setPropertyValue with std::string argument --- src/Gui/propertyeditor/PropertyItem.cpp | 10 +++++++--- src/Gui/propertyeditor/PropertyItem.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 83ec217cca1c..c6b8bd304447 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -598,7 +598,7 @@ void PropertyItem::setPropertyName(const QString& name, const QString& realName) displayText = str; } -void PropertyItem::setPropertyValue(const QString& value) +void PropertyItem::setPropertyValue(const std::string& value) { // Construct command for property assignment in one go, in case of any // intermediate changes caused by property change that may potentially @@ -631,8 +631,7 @@ void PropertyItem::setPropertyValue(const QString& value) continue; } - ss << parent->getPropertyPrefix() << prop->getName() << " = " << value.toUtf8().constData() - << '\n'; + ss << parent->getPropertyPrefix() << prop->getName() << " = " << value << '\n'; } std::string cmd = ss.str(); @@ -655,6 +654,11 @@ void PropertyItem::setPropertyValue(const QString& value) } } +void PropertyItem::setPropertyValue(const QString& value) +{ + setPropertyValue(value.toStdString()); +} + QVariant PropertyItem::dataProperty(int role) const { if (role == Qt::ForegroundRole && linked) { diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index 682826232b8e..04481b3000fc 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -203,6 +203,7 @@ class GuiExport PropertyItem: public QObject, public ExpressionBinding protected: PropertyItem(); + void setPropertyValue(const std::string& value); virtual QVariant displayName() const; virtual QVariant decoration(const QVariant&) const; virtual QVariant toolTip(const App::Property*) const; From 6860aab7ee7d8a3642c0a69a4c96883eb7253c18 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 15 Aug 2024 18:14:30 +0200 Subject: [PATCH 109/161] Gui: propertyeditor: use std::string setPropertyValue Avoid std::string->QString->std::string where possible. --- src/Gui/propertyeditor/PropertyItem.cpp | 156 +++++++++--------------- 1 file changed, 56 insertions(+), 100 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index c6b8bd304447..4c996ff0c52b 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ #include +#include #include #include #include @@ -842,14 +843,9 @@ QVariant PropertyStringItem::value(const App::Property* prop) const void PropertyStringItem::setValue(const QVariant& value) { - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - QString val = value.toString(); - val = QString::fromUtf8(Base::InterpreterSingleton::strToPython(val.toUtf8()).c_str()); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); + if (!hasExpression() && value.canConvert()) { + std::string val = Base::InterpreterSingleton::strToPython(value.toString().toStdString()); + setPropertyValue(Base::Tools::quoted(val)); } } @@ -896,13 +892,9 @@ QVariant PropertyFontItem::value(const App::Property* prop) const void PropertyFontItem::setValue(const QVariant& value) { - if (hasExpression() || !value.canConvert()) { - return; + if (!hasExpression() && value.canConvert()) { + setPropertyValue(Base::Tools::quoted(value.toString().toStdString())); } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); } QWidget* PropertyFontItem::createEditor(QWidget* parent, const std::function& method) const @@ -966,13 +958,9 @@ QVariant PropertyIntegerItem::value(const App::Property* prop) const void PropertyIntegerItem::setValue(const QVariant& value) { // if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } + if (!hasExpression() && value.canConvert()) { int val = value.toInt(); - QString data = QString::fromLatin1("%1").arg(val); - setPropertyValue(data); + setPropertyValue(std::to_string(val)); } } @@ -1035,13 +1023,9 @@ QVariant PropertyIntegerConstraintItem::value(const App::Property* prop) const void PropertyIntegerConstraintItem::setValue(const QVariant& value) { // if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } + if (!hasExpression() && value.canConvert()) { int val = value.toInt(); - QString data = QString::fromLatin1("%1").arg(val); - setPropertyValue(data); + setPropertyValue(std::to_string(val)); } } @@ -1133,13 +1117,10 @@ QVariant PropertyFloatItem::value(const App::Property* prop) const void PropertyFloatItem::setValue(const QVariant& value) { // if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - double val = value.toDouble(); - QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); - setPropertyValue(data); + if (!hasExpression() && value.canConvert()) { + std::ostringstream ss; + ss << std::setprecision(highPrec) << value.toDouble(); + setPropertyValue(ss.str()); } } @@ -1202,12 +1183,8 @@ QVariant PropertyUnitItem::value(const App::Property* prop) const void PropertyUnitItem::setValue(const QVariant& value) { // if the item has an expression it handles the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } + if (!hasExpression() && value.canConvert()) { const Base::Quantity& val = value.value(); - Base::QuantityFormat format(Base::QuantityFormat::Default, highPrec); QString unit = Base::UnitsApi::toString(val, format); setPropertyValue(unit); @@ -1305,13 +1282,10 @@ QVariant PropertyFloatConstraintItem::value(const App::Property* prop) const void PropertyFloatConstraintItem::setValue(const QVariant& value) { // if the item has an expression it issues the python code - if (!hasExpression()) { - if (!value.canConvert()) { - return; - } - double val = value.toDouble(); - QString data = QString::fromLatin1("%1").arg(val, 0, 'g', highPrec); - setPropertyValue(data); + if (!hasExpression() && value.canConvert()) { + std::ostringstream ss; + ss << std::setprecision(highPrec) << value.toDouble(); + setPropertyValue(ss.str()); } } @@ -1403,12 +1377,10 @@ QVariant PropertyBoolItem::value(const App::Property* prop) const void PropertyBoolItem::setValue(const QVariant& value) { - if (hasExpression() || !value.canConvert()) { - return; + if (!hasExpression() && value.canConvert()) { + std::string val = value.toBool() ? "True" : "False"; + setPropertyValue(val); } - bool val = value.toBool(); - QString data = (val ? QLatin1String("True") : QLatin1String("False")); - setPropertyValue(data); } QWidget* PropertyBoolItem::createEditor(QWidget* parent, const std::function& method) const @@ -3012,28 +2984,26 @@ void PropertyEnumItem::setValue(const QVariant& value) return; } - QString data; + std::ostringstream ss; if (value.userType() == QMetaType::QStringList) { QStringList values = value.toStringList(); - QTextStream str(&data); - str << "["; + ss << "["; for (const auto& it : values) { QString text(it); text.replace(QString::fromUtf8("'"), QString::fromUtf8("\\'")); - std::string pystr = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); - pystr = Base::InterpreterSingleton::strToPython(pystr.c_str()); - str << "u\"" << pystr.c_str() << "\", "; + std::string str = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); + str = Base::InterpreterSingleton::strToPython(str); + ss << "u\"" << str << "\", "; } - str << "]"; - setPropertyValue(data); + ss << "]"; + setPropertyValue(ss.str()); } else if (value.canConvert()) { - QByteArray val = value.toString().toUtf8(); - std::string str = Base::Tools::escapedUnicodeFromUtf8(val); - data = QString::fromLatin1("u\"%1\"").arg(QString::fromStdString(str)); - setPropertyValue(data); + std::string str = Base::Tools::escapedUnicodeFromUtf8(value.toString().toUtf8()); + ss << "u\"" << str << "\""; + setPropertyValue(ss.str()); } } @@ -3282,22 +3252,17 @@ void PropertyStringListItem::setValue(const QVariant& value) if (hasExpression() || !value.canConvert()) { return; } - QStringList values = value.toStringList(); - QString data; - QTextStream str(&data); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - str.setCodec("UTF-8"); -#endif - str << "["; + QStringList values = value.toStringList(); + std::ostringstream ss; + ss << "["; for (const auto& it : values) { QString text(it); std::string pystr = Base::InterpreterSingleton::strToPython(text.toUtf8().constData()); - str << "\"" << QString::fromUtf8(pystr.c_str()) << "\", "; + ss << "\"" << pystr << "\", "; } - str << "]"; - - setPropertyValue(data); + ss << "]"; + setPropertyValue(ss.str()); } // --------------------------------------------------------------- @@ -3363,17 +3328,18 @@ void PropertyFloatListItem::setValue(const QVariant& value) if (hasExpression() || !value.canConvert()) { return; } + QStringList values = value.toStringList(); QString data; QTextStream str(&data); str << "["; - for (const auto& it : values) { - str << it << ","; + for (auto it = values.begin(); it != values.end(); ++it) { + if (it != values.begin()) { + str << ","; + } + str << *it; } str << "]"; - if (data == QString::fromUtf8("[,]")) { - data = QString::fromUtf8("[]"); - } setPropertyValue(data); } @@ -3441,17 +3407,18 @@ void PropertyIntegerListItem::setValue(const QVariant& value) if (hasExpression() || !value.canConvert()) { return; } + QStringList values = value.toStringList(); QString data; QTextStream str(&data); str << "["; - for (const auto& value : values) { - str << value << ","; + for (auto it = values.begin(); it != values.end(); ++it) { + if (it != values.begin()) { + str << ","; + } + str << *it; } str << "]"; - if (data == QString::fromUtf8("[,]")) { - data = QString::fromUtf8("[]"); - } setPropertyValue(data); } @@ -4426,12 +4393,9 @@ QVariant PropertyFileItem::value(const App::Property* prop) const void PropertyFileItem::setValue(const QVariant& value) { - if (hasExpression() || !value.canConvert()) { - return; + if (!hasExpression() && value.canConvert()) { + setPropertyValue(Base::Tools::quoted(value.toString().toStdString())); } - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); } QVariant PropertyFileItem::toolTip(const App::Property* prop) const @@ -4483,13 +4447,9 @@ QVariant PropertyPathItem::value(const App::Property* prop) const void PropertyPathItem::setValue(const QVariant& value) { - if (hasExpression() || !value.canConvert()) { - return; + if (!hasExpression() && value.canConvert()) { + setPropertyValue(Base::Tools::quoted(value.toString().toStdString())); } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); } QVariant PropertyPathItem::toolTip(const App::Property* prop) const @@ -4535,13 +4495,9 @@ QVariant PropertyTransientFileItem::value(const App::Property* prop) const void PropertyTransientFileItem::setValue(const QVariant& value) { - if (hasExpression() || !value.canConvert()) { - return; + if (!hasExpression() && value.canConvert()) { + setPropertyValue(Base::Tools::quoted(value.toString().toStdString())); } - - QString val = value.toString(); - QString data = QString::fromLatin1("\"%1\"").arg(val); - setPropertyValue(data); } QVariant PropertyTransientFileItem::toolTip(const App::Property* prop) const From 354d0957872f5ae47e507c1ed50ebc506c43fef9 Mon Sep 17 00:00:00 2001 From: Jacob Oursland Date: Wed, 27 Nov 2024 15:05:41 -0800 Subject: [PATCH 110/161] CMake: emit message when ccache is detected. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97c0f4b6a312..e94db800da23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ if(FREECAD_USE_CCACHE) find_program(CCACHE_PROGRAM ccache) #This check should occur before project() if(CCACHE_PROGRAM) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") + message(NOTICE "-- Using ccache found at: " ${CCACHE_PROGRAM}) endif() endif() From 3595c301b72f7b0154f94ae5a8af4e575868b2b7 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 27 Nov 2024 17:01:10 +0100 Subject: [PATCH 111/161] Gui: Refactor PreferencePackManager & DlgPreferencePackManagementImp --- src/Gui/DlgPreferencePackManagementImp.cpp | 38 ++-------- src/Gui/DlgPreferencePackManagementImp.h | 2 - src/Gui/PreferencePackManager.cpp | 85 +++++++++++++++------- src/Gui/PreferencePackManager.h | 15 ++++ 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/Gui/DlgPreferencePackManagementImp.cpp b/src/Gui/DlgPreferencePackManagementImp.cpp index 50f3982f21e4..b1e96bb829fc 100644 --- a/src/Gui/DlgPreferencePackManagementImp.cpp +++ b/src/Gui/DlgPreferencePackManagementImp.cpp @@ -53,25 +53,25 @@ void DlgPreferencePackManagementImp::showEvent(QShowEvent* event) // Separate out user-saved packs from installed packs: we can remove individual user-saved packs, // but can only disable individual installed packs (though we can completely uninstall the pack's // containing Addon by redirecting to the Addon Manager). - auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = Application::Instance->prefPackManager()->getSavedPreferencePacksPath(); auto modDirectories = Application::Instance->prefPackManager()->modPaths(); - auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; + auto resourcePath = Application::Instance->prefPackManager()->getResourcePreferencePacksPath(); // The displayed tree has two levels: at the toplevel is either "User-Saved Packs" or the name // of the addon containing the pack. Beneath those are the individual packs themselves. The tree view shows // "Hide"/"Show" for packs installed as a Mod, and "Delete" for packs in the user-saved pack // section. - auto userPacks = getPacksFromDirectory(savedPreferencePacksDirectory); + auto userPacks = Application::Instance->prefPackManager()->getPacksFromDirectory(savedPreferencePacksDirectory); - auto builtinPacks = getPacksFromDirectory(resourcePath); + auto builtinPacks = Application::Instance->prefPackManager()->getPacksFromDirectory(resourcePath); std::map> installedPacks; for (const auto& modDirectory : modDirectories) { if (fs::exists(modDirectory) && fs::is_directory(modDirectory)) { for (const auto& mod : fs::directory_iterator(modDirectory)) { - auto packs = getPacksFromDirectory(mod); + auto packs = Application::Instance->prefPackManager()->getPacksFromDirectory(mod); if (!packs.empty()) { - auto modName = mod.path().filename().string(); + auto modName = Base::FileInfo::pathToString(mod.path().filename()); installedPacks.emplace(modName, packs); } } @@ -98,8 +98,7 @@ void DlgPreferencePackManagementImp::showEvent(QShowEvent* event) addTreeNode(installedPack.first, installedPack.second, TreeWidgetType::ADDON); } - if (event) - QDialog::showEvent(event); + QDialog::showEvent(event); } void DlgPreferencePackManagementImp::addTreeNode(const std::string &name, const std::vector &contents, TreeWidgetType twt) @@ -152,29 +151,6 @@ void DlgPreferencePackManagementImp::addTreeNode(const std::string &name, const } } -std::vector DlgPreferencePackManagementImp::getPacksFromDirectory(const fs::path& path) const -{ - std::vector results; - auto packageMetadataFile = path / "package.xml"; - if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { - try { - App::Metadata metadata(packageMetadataFile); - auto content = metadata.content(); - for (const auto& item : content) { - if (item.first == "preferencepack") { - results.push_back(item.second.name()); - } - } - } - catch (...) { - // Failed to read the metadata, or to create the preferencePack based on it... - Base::Console().Error(("Failed to read " + packageMetadataFile.string()).c_str()); - } - } - return results; -} - - void DlgPreferencePackManagementImp::deleteUserPack(const std::string& name) { // Do the deletion here... diff --git a/src/Gui/DlgPreferencePackManagementImp.h b/src/Gui/DlgPreferencePackManagementImp.h index 079d4a3be477..a2a5843cb507 100644 --- a/src/Gui/DlgPreferencePackManagementImp.h +++ b/src/Gui/DlgPreferencePackManagementImp.h @@ -76,9 +76,7 @@ protected Q_SLOTS: std::unique_ptr ui; - std::vector getPacksFromDirectory(const boost::filesystem::path& path) const; void addTreeNode(const std::string& name, const std::vector& contents, TreeWidgetType twt); - }; } // namespace Dialog diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index 2328bcb04d81..54b42784e4d7 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -50,6 +50,18 @@ using namespace Gui; using namespace xercesc; namespace fs = boost::filesystem; +static boost::filesystem::path getSavedPrefPacksPath() +{ + return fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) + / "SavedPreferencePacks"; +} + +static boost::filesystem::path getResourcePrefPacksPath() +{ + return fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" + / "PreferencePacks"; +} + PreferencePack::PreferencePack(const fs::path& path, const App::Metadata& metadata) : _path(path), _metadata(metadata) { @@ -90,7 +102,7 @@ bool PreferencePack::apply() const } // Back up the old config file - auto savedPreferencePacksDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = getSavedPrefPacksPath(); auto backupFile = savedPreferencePacksDirectory / "user.cfg.backup"; try { fs::remove(backupFile); @@ -137,8 +149,8 @@ void PreferencePack::applyConfigChanges() const PreferencePackManager::PreferencePackManager() : _preferencePackPaths(modPaths()) { - auto savedPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; - auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; + auto savedPath = getSavedPreferencePacksPath(); + auto resourcePath = getResourcePreferencePacksPath(); _preferencePackPaths.insert(_preferencePackPaths.begin(), resourcePath); _preferencePackPaths.push_back(savedPath); rescan(); @@ -166,8 +178,7 @@ void PreferencePackManager::rescan() void Gui::PreferencePackManager::AddPackToMetadata(const std::string &packName) const { std::lock_guard lock(_mutex); - auto savedPreferencePacksDirectory = - fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = getSavedPreferencePacksPath(); fs::path preferencePackDirectory(savedPreferencePacksDirectory / packName); if (fs::exists(preferencePackDirectory) && !fs::is_directory(preferencePackDirectory)) throw std::runtime_error("Cannot create " + savedPreferencePacksDirectory.string() @@ -221,8 +232,7 @@ void Gui::PreferencePackManager::importConfig(const std::string& packName, { AddPackToMetadata(packName); - auto savedPreferencePacksDirectory = - fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = getSavedPreferencePacksPath(); auto cfgFilename = savedPreferencePacksDirectory / packName / (packName + ".cfg"); #if BOOST_VERSION >= 107400 fs::copy_file(path, cfgFilename, fs::copy_options::overwrite_existing); @@ -252,6 +262,38 @@ std::vector Gui::PreferencePackManager::modPaths() cons return result; } +boost::filesystem::path Gui::PreferencePackManager::getSavedPreferencePacksPath() const +{ + return getSavedPrefPacksPath(); +} + +boost::filesystem::path Gui::PreferencePackManager::getResourcePreferencePacksPath() const +{ + return getResourcePrefPacksPath(); +} + +std::vector Gui::PreferencePackManager::getPacksFromDirectory(const fs::path& path) const +{ + std::vector results; + auto packageMetadataFile = path / "package.xml"; + if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { + try { + App::Metadata metadata(packageMetadataFile); + auto content = metadata.content(); + for (const auto& item : content) { + if (item.first == "preferencepack") { + results.push_back(item.second.name()); + } + } + } + catch (...) { + // Failed to read the metadata, or to create the preferencePack based on it... + Base::Console().Error(("Failed to read " + packageMetadataFile.string()).c_str()); + } + } + return results; +} + void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path &mod) { try { @@ -271,7 +313,7 @@ void PreferencePackManager::TryFindPreferencePacksInPackage(const boost::filesys { auto packageMetadataFile = mod / "package.xml"; static const auto modDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod" / "SavedPreferencePacks"; - static const auto resourcePath = fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; + static const auto resourcePath = getResourcePreferencePacksPath(); if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { App::Metadata metadata(packageMetadataFile); @@ -330,7 +372,7 @@ bool PreferencePackManager::apply(const std::string& preferencePackName) const } } -std::string findUnusedName(const std::string &basename, ParameterGrp::handle parent) +static std::string findUnusedName(const std::string &basename, ParameterGrp::handle parent) { int i = 1; while (true) { @@ -385,7 +427,7 @@ void Gui::PreferencePackManager::deleteUserPack(const std::string& name) { if (name.empty()) return; - auto savedPreferencePacksDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = getSavedPreferencePacksPath(); auto savedPath = savedPreferencePacksDirectory / name; std::unique_ptr metadata; if (fs::exists(savedPreferencePacksDirectory / "package.xml")) { @@ -401,7 +443,7 @@ void Gui::PreferencePackManager::deleteUserPack(const std::string& name) rescan(); } -void copyTemplateParameters(Base::Reference templateGroup, const std::string& path, Base::Reference outputGroup) +static void copyTemplateParameters(Base::Reference templateGroup, const std::string& path, Base::Reference outputGroup) { auto userParameterHandle = App::GetApplication().GetParameterGroupByPath(path.c_str()); @@ -452,7 +494,7 @@ void copyTemplateParameters(Base::Reference templateGroup, const s } } -void copyTemplateParameters(/*const*/ ParameterManager& templateParameterManager, ParameterManager& outputParameterManager) +static void copyTemplateParameters(/*const*/ ParameterManager& templateParameterManager, ParameterManager& outputParameterManager) { auto groups = templateParameterManager.GetGroups(); for (auto& group : groups) { @@ -477,19 +519,12 @@ void PreferencePackManager::save(const std::string& name, const std::vectorLoadDocument(Base::FileInfo::pathToString(t.path).c_str()); copyTemplateParameters(*templateParameterManager, *outputParameterManager); } - auto savedPreferencePacksDirectory = - fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; + auto savedPreferencePacksDirectory = getSavedPreferencePacksPath(); auto cfgFilename = savedPreferencePacksDirectory / name / (name + ".cfg"); outputParameterManager->SaveDocument(Base::FileInfo::pathToString(cfgFilename).c_str()); } -// Needed until we support only C++20 and above and can use std::string's built-in ends_with() -bool fc_ends_with(std::string_view str, std::string_view suffix) -{ - return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; -} - -std::vector scanForTemplateFolders(const std::string& groupName, const fs::path& entry) +static std::vector scanForTemplateFolders(const std::string& groupName, const fs::path& entry) { // From this location, find the folder(s) called "PreferencePackTemplates" std::vector templateFolders; @@ -511,7 +546,7 @@ std::vector scanForTemplateFolders(const std::string& groupName, const return templateFolders; } -std::vector scanForTemplateFiles(const std::string& groupName, const fs::path& entry) +static std::vector scanForTemplateFiles(const std::string& groupName, const fs::path& entry) { auto templateFolders = scanForTemplateFolders(groupName, entry); @@ -570,7 +605,7 @@ std::vector PreferencePackManager::template void Gui::PreferencePackManager::BackupCurrentConfig() const { - auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = getSavedPreferencePacksPath() / "Backups"; fs::create_directories(backupDirectory); // Create a timestamped filename: @@ -587,7 +622,7 @@ void Gui::PreferencePackManager::DeleteOldBackups() const { constexpr auto oneWeek = 60.0 * 60.0 * 24.0 * 7.0; const auto now = std::time(nullptr); - auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = getSavedPreferencePacksPath() / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { if (std::difftime(now, fs::last_write_time(backup)) > oneWeek) { @@ -603,7 +638,7 @@ void Gui::PreferencePackManager::DeleteOldBackups() const std::vector Gui::PreferencePackManager::configBackups() const { std::vector results; - auto backupDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks" / "Backups"; + auto backupDirectory = getSavedPreferencePacksPath() / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { results.push_back(backup); diff --git a/src/Gui/PreferencePackManager.h b/src/Gui/PreferencePackManager.h index e5776e47a02d..0358fe77ea6d 100644 --- a/src/Gui/PreferencePackManager.h +++ b/src/Gui/PreferencePackManager.h @@ -196,6 +196,21 @@ namespace Gui { */ std::vector modPaths() const; + /** + * Get the path to the saved preference packs. + */ + boost::filesystem::path getSavedPreferencePacksPath() const; + + /** + * Get the path to the preference packs of the resource directory. + */ + boost::filesystem::path getResourcePreferencePacksPath() const; + + /** + * Collect all preference packs of a directory. + */ + std::vector getPacksFromDirectory(const boost::filesystem::path& path) const; + private: void FindPreferencePacksInPackage(const boost::filesystem::path& mod); From 0cf2cec816165b57830fd7582f32ecec2efae2de Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Thu, 28 Nov 2024 14:01:52 +0100 Subject: [PATCH 112/161] Draft: Fix cursor scaling for xcb platform Forum topic: https://forum.freecad.org/viewtopic.php?t=92281 Apparently the extra scaling for the "xcb" platform is wrong. --- src/Mod/Draft/draftguitools/gui_snapper.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py index 6432d1bfe86f..28907032303f 100644 --- a/src/Mod/Draft/draftguitools/gui_snapper.py +++ b/src/Mod/Draft/draftguitools/gui_snapper.py @@ -1154,8 +1154,6 @@ def get_cursor_with_tail(self, base_icon_name, tail_icon_name=None): # src/Mod/Mesh/Gui/MeshSelection.cpp # src/Mod/Sketcher/Gui/CommandConstraints.cpp - # The code below follows the Sketcher example. - # +--------+ # | base | vertical offset = 0.5*w # w | +--------+ @@ -1176,14 +1174,8 @@ def get_cursor_with_tail(self, base_icon_name, tail_icon_name=None): tail_icon = QtGui.QPixmap(tail_icon_name).scaledToWidth(width) qp.drawPixmap(width, 0.5 * width, tail_icon) qp.end() - hot_x = 8 - hot_y = 8 new_icon.setDevicePixelRatio(dpr) - # Only X11 needs hot point coordinates to be scaled: - if QtGui.QGuiApplication.platformName() == "xcb": - hot_x *= dpr - hot_x *= dpr - return QtGui.QCursor(new_icon, hot_x, hot_y) + return QtGui.QCursor(new_icon, 8, 8) def setCursor(self, mode=None): """Set or reset the cursor to the given mode or resets.""" From 8f18cfaf3a9ced77a7d2d4bcc6d5c310dc3c5943 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 17 Aug 2024 19:36:04 +0200 Subject: [PATCH 113/161] Mesh: Workaround to load 3mf files not supported by zipios library --- src/Base/Tools.cpp | 14 ++++++++++++++ src/Base/Tools.h | 8 ++++++++ src/Ext/freecad/CMakeLists.txt | 1 + src/Ext/freecad/utils_zip.py | 18 +++++++++++++++++ src/Mod/Mesh/App/Core/MeshIO.cpp | 33 +++++++++++++++++++++++++++++++- 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/Ext/freecad/utils_zip.py diff --git a/src/Base/Tools.cpp b/src/Base/Tools.cpp index eab37f58601f..71f6021bee1e 100644 --- a/src/Base/Tools.cpp +++ b/src/Base/Tools.cpp @@ -393,3 +393,17 @@ std::vector Base::Tools::splitSubName(const std::string& subname) return subNames; } + +// ------------------------------------------------------------------------------------------------ + +void Base::ZipTools::rewrite(const std::string& source, const std::string& target) +{ + Base::PyGILStateLocker lock; + PyObject* module = PyImport_ImportModule("freecad.utils_zip"); + if (!module) { + throw Py::Exception(); + } + + Py::Module commands(module, true); + commands.callMemberFunction("rewrite", Py::TupleN(Py::String(source), Py::String(target))); +} diff --git a/src/Base/Tools.h b/src/Base/Tools.h index e2018b988919..7e07dc841ace 100644 --- a/src/Base/Tools.h +++ b/src/Base/Tools.h @@ -329,6 +329,14 @@ struct BaseExport Tools static std::vector splitSubName(const std::string& subname); }; +struct BaseExport ZipTools +{ + /** + * @brief rewrite Rewrite a zip file under a new name. + */ + static void rewrite(const std::string& source, const std::string& target); +}; + } // namespace Base diff --git a/src/Ext/freecad/CMakeLists.txt b/src/Ext/freecad/CMakeLists.txt index caaf5b5eb5e0..4681b8f88199 100644 --- a/src/Ext/freecad/CMakeLists.txt +++ b/src/Ext/freecad/CMakeLists.txt @@ -35,6 +35,7 @@ set(EXT_FILES sketcher.py UiTools.py utils.py + utils_zip.py ) foreach (it ${EXT_FILES}) diff --git a/src/Ext/freecad/utils_zip.py b/src/Ext/freecad/utils_zip.py new file mode 100644 index 000000000000..d3ae1d007fc9 --- /dev/null +++ b/src/Ext/freecad/utils_zip.py @@ -0,0 +1,18 @@ +# (c) 2024 Werner Mayer LGPL + +__author__ = "Werner Mayer" +__url__ = "https://www.freecad.org" +__doc__ = "Helper module to convert zip files" + + +import zipfile + +def rewrite(source: str, target: str): + source_zip = zipfile.ZipFile(source, "r") + target_zip = zipfile.ZipFile(target, "w") + + for name in source_zip.namelist(): + target_zip.writestr(name, source_zip.open(name).read()) + + source_zip.close() + target_zip.close() diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 47ccec3adbfb..6f12b48662fc 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -108,6 +108,31 @@ struct QUAD int iV[4]; }; +class ZipFixer +{ +public: + ZipFixer(const char* filename) + : tmp {Base::FileInfo::getTempFileName()} + { + Base::ZipTools::rewrite(filename, tmp.filePath().c_str()); + str.open(tmp, std::ios::in | std::ios::binary); + } + + ~ZipFixer() + { + tmp.deleteFile(); + } + + Base::ifstream& getStream() + { + return str; + } + +private: + Base::FileInfo tmp; + Base::ifstream str; +}; + } // namespace MeshCore // -------------------------------------------------------------- @@ -227,7 +252,13 @@ bool MeshInput::LoadAny(const char* FileName) ok = LoadSMF(str); } else if (fi.hasExtension("3mf")) { - ok = Load3MF(str); + try { + ok = Load3MF(str); + } + catch (const zipios::FCollException&) { + ZipFixer zip(FileName); + ok = Load3MF(zip.getStream()); + } } else if (fi.hasExtension("off")) { ok = LoadOFF(str); From d795acc3786caf5227aa6290be7b90e870360709 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 23 Nov 2024 20:18:00 +0100 Subject: [PATCH 114/161] Mesh: Add comment explaining the workaround --- src/Mod/Mesh/App/Core/MeshIO.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 6f12b48662fc..ba855663bc29 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -108,6 +108,12 @@ struct QUAD int iV[4]; }; +// This is a workaround for the issue described at: +// https://github.com/Zipios/Zipios/issues/43#issue-1618151314 +// +// The workaround creates a tmp. ZIP file and uses the Python API +// to open the file zipios++ isn't able to handle and to copy over +// the files. class ZipFixer { public: From 92e96839c9075ecac0401ae4cd4d515eec5f7311 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 19 Oct 2024 00:57:49 +0200 Subject: [PATCH 115/161] PD: Avoid touching the document when opening pad or pocket dialog --- .../PartDesign/Gui/TaskDressUpParameters.cpp | 24 ++++++++++++------- .../PartDesign/Gui/TaskDressUpParameters.h | 1 + .../PartDesign/Gui/TaskExtrudeParameters.cpp | 3 +-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp index 6bb7b87e0e56..b326a68f3879 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp @@ -380,22 +380,28 @@ void TaskDressUpParameters::hideOnError() showObject(); } -void TaskDressUpParameters::hideObject() +void TaskDressUpParameters::setDressUpVisibility(bool visible) { App::DocumentObject* base = getBase(); - if(base) { - DressUpView->getObject()->Visibility.setValue(false); - base->Visibility.setValue(true); + if (base) { + App::DocumentObject* duv = DressUpView->getObject(); + if (duv->Visibility.getValue() != visible) { + duv->Visibility.setValue(visible); + } + if (base->Visibility.getValue() == visible) { + base->Visibility.setValue(!visible); + } } } +void TaskDressUpParameters::hideObject() +{ + setDressUpVisibility(false); +} + void TaskDressUpParameters::showObject() { - App::DocumentObject* base = getBase(); - if (base) { - DressUpView->getObject()->Visibility.setValue(true); - base->Visibility.setValue(false); - } + setDressUpVisibility(true); } ViewProviderDressUp* TaskDressUpParameters::getDressUpView() const diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h index 9220f2395c6f..d5a338415db1 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h @@ -104,6 +104,7 @@ protected Q_SLOTS: private: void tryAddSelection(const std::string& doc, const std::string& obj, const std::string& sub); + void setDressUpVisibility(bool visible); protected: QWidget* proxy; diff --git a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp index a26f18f179ab..59a348635f30 100644 --- a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp @@ -186,11 +186,10 @@ void TaskExtrudeParameters::setupDialog() ui->listWidgetReferences->addAction(unselectShapeFaceAction); ui->listWidgetReferences->setContextMenuPolicy(Qt::ActionsContextMenu); + ui->checkBoxAllFaces->setChecked(ui->listWidgetReferences->count() == 0); connectSlots(); - ui->checkBoxAllFaces->setChecked(ui->listWidgetReferences->count() == 0); - this->propReferenceAxis = &(extrude->ReferenceAxis); // Due to signals attached after changes took took into effect we should update the UI now. From d7989015152a53106df5a0da3c0e219d614ac8ec Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Nov 2024 19:22:15 +0100 Subject: [PATCH 116/161] Core: Fix crash in ActiveObjectList Forum: https://forum.freecad.org/viewtopic.php?t=91823 --- src/Gui/ActiveObjectList.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Gui/ActiveObjectList.cpp b/src/Gui/ActiveObjectList.cpp index 717a65ad2ba1..0fc064cdb6f7 100644 --- a/src/Gui/ActiveObjectList.cpp +++ b/src/Gui/ActiveObjectList.cpp @@ -184,11 +184,16 @@ bool Gui::ActiveObjectList::hasObject(const char*name)const void ActiveObjectList::objectDeleted(const ViewProviderDocumentObject &vp) { - //maybe boost::bimap or boost::multi_index - for (auto it = _ObjectMap.begin(); it != _ObjectMap.end(); ++it) { - if (it->second.obj == vp.getObject()) { - _ObjectMap.erase(it); - return; + // Hint: With C++20 std::erase_if for containers can be used + auto isEqual = [&vp](const auto& item) { + return item.second.obj == vp.getObject(); + }; + for (auto it = _ObjectMap.begin(); it != _ObjectMap.end();) { + if (isEqual(*it)) { + it = _ObjectMap.erase(it); + } + else { + ++it; } } } From 601637320d0392a12fe613cade33f969b0157a6f Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Nov 2024 20:04:51 +0100 Subject: [PATCH 117/161] PD: Add test case to show the fix for the crash with active objects --- src/Mod/PartDesign/CMakeLists.txt | 1 + .../PartDesignTests/TestActiveObject.py | 61 +++++++++++++++++++ src/Mod/PartDesign/TestPartDesignGui.py | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/Mod/PartDesign/PartDesignTests/TestActiveObject.py diff --git a/src/Mod/PartDesign/CMakeLists.txt b/src/Mod/PartDesign/CMakeLists.txt index 28cd8003f996..58ceaa4c3a23 100644 --- a/src/Mod/PartDesign/CMakeLists.txt +++ b/src/Mod/PartDesign/CMakeLists.txt @@ -34,6 +34,7 @@ set(PartDesign_OtherScripts set(PartDesign_TestScripts PartDesignTests/__init__.py + PartDesignTests/TestActiveObject.py PartDesignTests/TestDatum.py PartDesignTests/TestShapeBinder.py PartDesignTests/TestPad.py diff --git a/src/Mod/PartDesign/PartDesignTests/TestActiveObject.py b/src/Mod/PartDesign/PartDesignTests/TestActiveObject.py new file mode 100644 index 000000000000..c4b83e011d8f --- /dev/null +++ b/src/Mod/PartDesign/PartDesignTests/TestActiveObject.py @@ -0,0 +1,61 @@ +#*************************************************************************** +#* Copyright (c) 2024 Werner Mayer * +#* * +#* This file is part of FreeCAD. * +#* * +#* FreeCAD is free software: you can redistribute it and/or modify it * +#* under the terms of the GNU Lesser General Public License as * +#* published by the Free Software Foundation, either version 2.1 of the * +#* License, or (at your option) any later version. * +#* * +#* FreeCAD is distributed in the hope that it will be useful, but * +#* WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +#* Lesser General Public License for more details. * +#* * +#* You should have received a copy of the GNU Lesser General Public * +#* License along with FreeCAD. If not, see * +#* . * +#* * +#*************************************************************************** + +import unittest + +import FreeCAD +import FreeCADGui + +""" Test active object list """ +class TestActiveObject(unittest.TestCase): + def setUp(self): + self.doc = FreeCAD.newDocument("PartDesignTestSketch") + self.doc.UndoMode = True + + def testPartBody(self): + self.doc.openTransaction("Create part") + part = self.doc.addObject("App::Part", "Part") + FreeCADGui.activateView('Gui::View3DInventor', True) + FreeCADGui.activeView().setActiveObject('part', part) + self.doc.commitTransaction() + + self.doc.openTransaction("Create body") + body = self.doc.addObject('PartDesign::Body', 'Body') + part.addObject(body) + FreeCADGui.activateView('Gui::View3DInventor', True) + FreeCADGui.activeView().setActiveObject('pdbody', body) + self.doc.commitTransaction() + + self.doc.undo() # undo body creation + self.doc.undo() # undo part creation + + FreeCADGui.updateGui() + + self.doc.openTransaction("Create body") + body = self.doc.addObject('PartDesign::Body', 'Body') + FreeCADGui.activateView('Gui::View3DInventor', True) + FreeCADGui.activeView().setActiveObject('pdbody', body) + self.doc.commitTransaction() + + FreeCADGui.updateGui() + + def tearDown(self): + FreeCAD.closeDocument("PartDesignTestSketch") diff --git a/src/Mod/PartDesign/TestPartDesignGui.py b/src/Mod/PartDesign/TestPartDesignGui.py index 1e92c0818020..e7838e0e98b8 100644 --- a/src/Mod/PartDesign/TestPartDesignGui.py +++ b/src/Mod/PartDesign/TestPartDesignGui.py @@ -35,6 +35,7 @@ from PySide.QtGui import QApplication from PartDesignTests.TestMaterial import TestMaterial +from PartDesignTests.TestActiveObject import TestActiveObject #timer runs this class in order to access modal dialog class CallableCheckWorkflow: From 82b4dcd58aa8b031461b321eeff08e1bf2c92e68 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Nov 2024 00:20:08 +0100 Subject: [PATCH 118/161] Gui: Fixes #16637: Can no longer set transparency of Link faces --- src/Gui/TaskElementColors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gui/TaskElementColors.cpp b/src/Gui/TaskElementColors.cpp index f9f43d092b80..d3653f9ebae3 100644 --- a/src/Gui/TaskElementColors.cpp +++ b/src/Gui/TaskElementColors.cpp @@ -234,7 +234,7 @@ class ElementColors::Private: public Gui::SelectionGate QColorDialog cd(color, parent); cd.setOption(QColorDialog::ShowAlphaChannel); if (DialogOptions::dontUseNativeColorDialog()) - cd.setOptions(QColorDialog::DontUseNativeDialog); + cd.setOption(QColorDialog::DontUseNativeDialog); if (cd.exec()!=QDialog::Accepted || color==cd.selectedColor()) return; color = cd.selectedColor(); @@ -459,7 +459,7 @@ void ElementColors::onAddSelectionClicked() QColorDialog cd(color, this); cd.setOption(QColorDialog::ShowAlphaChannel); if (DialogOptions::dontUseNativeColorDialog()) - cd.setOptions(QColorDialog::DontUseNativeDialog); + cd.setOption(QColorDialog::DontUseNativeDialog); if (cd.exec()!=QDialog::Accepted) return; color = cd.selectedColor(); From f741655bf637abf1a1bc1ed91615e710680d22ad Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Nov 2024 00:29:22 +0100 Subject: [PATCH 119/161] Gui: Apply clang-format --- src/Gui/TaskElementColors.cpp | 415 ++++++++++++++++++++-------------- 1 file changed, 242 insertions(+), 173 deletions(-) diff --git a/src/Gui/TaskElementColors.cpp b/src/Gui/TaskElementColors.cpp index d3653f9ebae3..d5c007536d21 100644 --- a/src/Gui/TaskElementColors.cpp +++ b/src/Gui/TaskElementColors.cpp @@ -23,9 +23,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -54,10 +54,10 @@ class ElementColors::Private: public Gui::SelectionGate public: using Connection = boost::signals2::connection; std::unique_ptr ui; - ViewProviderDocumentObject *vp; - ViewProviderDocumentObject *vpParent; - Document *vpDoc; - std::map elements; + ViewProviderDocumentObject* vp; + ViewProviderDocumentObject* vpParent; + Document* vpDoc; + std::map elements; std::vector items; std::string hiddenSub; Connection connectDelDoc; @@ -72,22 +72,24 @@ class ElementColors::Private: public Gui::SelectionGate std::string editSub; std::string editElement; - explicit Private(ViewProviderDocumentObject* vp, const char *element="") - : ui(new Ui_TaskElementColors()), vp(vp),editElement(element) + explicit Private(ViewProviderDocumentObject* vp, const char* element = "") + : ui(new Ui_TaskElementColors()) + , vp(vp) + , editElement(element) { vpDoc = vp->getDocument(); vpParent = vp; auto doc = Application::Instance->editDocument(); - if(doc) { - auto editVp = doc->getInEdit(&vpParent,&editSub); - if(editVp == vp) { + if (doc) { + auto editVp = doc->getInEdit(&vpParent, &editSub); + if (editVp == vp) { auto obj = vpParent->getObject(); editDoc = obj->getDocument()->getName(); editObj = obj->getNameInDocument(); editSub = Data::noElementName(editSub.c_str()); } } - if(editDoc.empty()) { + if (editDoc.empty()) { vpParent = vp; editDoc = vp->getObject()->getDocument()->getName(); editObj = vp->getObject()->getNameInDocument(); @@ -97,10 +99,11 @@ class ElementColors::Private: public Gui::SelectionGate busy = false; touched = false; int w = QApplication::style()->standardPixmap(QStyle::SP_DirClosedIcon).width(); - px = QPixmap(w,w); + px = QPixmap(w, w); } - ~Private() override { + ~Private() override + { try { vpParent->OnTopWhenSelected.setValue(onTopMode); } @@ -109,94 +112,111 @@ class ElementColors::Private: public Gui::SelectionGate } } - bool allow(App::Document *doc, App::DocumentObject *obj, const char *subname) override { - if(editDoc!=doc->getName() || - editObj!=obj->getNameInDocument() || - !boost::starts_with(subname,editSub)) + bool allow(App::Document* doc, App::DocumentObject* obj, const char* subname) override + { + if (editDoc != doc->getName() || editObj != obj->getNameInDocument() + || !boost::starts_with(subname, editSub)) { return false; - if(editElement.empty()) + } + if (editElement.empty()) { return true; - const char *dot = strrchr(subname,'.'); - if(!dot) + } + const char* dot = strrchr(subname, '.'); + if (!dot) { dot = subname; - else + } + else { ++dot; - return *dot==0 || boost::starts_with(dot,editElement); + } + return *dot == 0 || boost::starts_with(dot, editElement); } - void populate() { - int i=0; - for(auto &v : vp->getElementColors()) - addItem(i++,v.first.c_str()); + void populate() + { + int i = 0; + for (auto& v : vp->getElementColors()) { + addItem(i++, v.first.c_str()); + } apply(); } - void addItem(int i,const char *sub, bool push=false) { + void addItem(int i, const char* sub, bool push = false) + { auto itE = elements.find(sub); - if(i<0 && itE!=elements.end()) { - if(push && !ViewProvider::hasHiddenMarker(sub)) + if (i < 0 && itE != elements.end()) { + if (push && !ViewProvider::hasHiddenMarker(sub)) { items.push_back(itE->second); + } return; } - const char *marker = ViewProvider::hasHiddenMarker(sub); - if(marker) { + const char* marker = ViewProvider::hasHiddenMarker(sub); + if (marker) { auto icon = BitmapFactory().pixmap("Invisible"); - auto item = new QListWidgetItem(icon, - QString::fromLatin1(std::string(sub,marker-sub).c_str()), ui->elementList); - item->setData(Qt::UserRole,QColor()); - item->setData(Qt::UserRole+1,QString::fromLatin1(sub)); - elements.emplace(sub,item); + auto item = + new QListWidgetItem(icon, + QString::fromLatin1(std::string(sub, marker - sub).c_str()), + ui->elementList); + item->setData(Qt::UserRole, QColor()); + item->setData(Qt::UserRole + 1, QString::fromLatin1(sub)); + elements.emplace(sub, item); return; } - for(auto &v : vp->getElementColors(sub)) { + for (auto& v : vp->getElementColors(sub)) { auto it = elements.find(v.first.c_str()); - if(it!=elements.end()) { - if(push) + if (it != elements.end()) { + if (push) { items.push_back(it->second); + } continue; } auto color = v.second; QColor c; - c.setRgbF(color.r,color.g,color.b,1.0-color.a); + c.setRgbF(color.r, color.g, color.b, 1.0 - color.a); px.fill(c); - auto item = new QListWidgetItem(QIcon(px), - QString::fromLatin1(Data::oldElementName(v.first.c_str()).c_str()), - ui->elementList); - item->setData(Qt::UserRole,c); - item->setData(Qt::UserRole+1,QString::fromLatin1(v.first.c_str())); - if(push) + auto item = new QListWidgetItem( + QIcon(px), + QString::fromLatin1(Data::oldElementName(v.first.c_str()).c_str()), + ui->elementList); + item->setData(Qt::UserRole, c); + item->setData(Qt::UserRole + 1, QString::fromLatin1(v.first.c_str())); + if (push) { items.push_back(item); - elements.emplace(v.first,item); + } + elements.emplace(v.first, item); } } - void apply() { - std::map info; + void apply() + { + std::map info; int count = ui->elementList->count(); - for(int i=0;ielementList->item(i); auto color = item->data(Qt::UserRole).value(); - std::string sub = qPrintable(item->data(Qt::UserRole+1).value()); - info.emplace(qPrintable(item->data(Qt::UserRole+1).value()), - App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF())); + info.emplace( + qPrintable(item->data(Qt::UserRole + 1).value()), + App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF())); } - if(!App::GetApplication().getActiveTransaction()) + if (!App::GetApplication().getActiveTransaction()) { App::GetApplication().setActiveTransaction("Set colors"); + } vp->setElementColors(info); touched = true; Selection().clearSelection(); } - void reset() { + void reset() + { touched = false; App::GetApplication().closeActiveTransaction(true); Selection().clearSelection(); } - void accept() { - if(touched && ui->recompute->isChecked()) { + void accept() + { + if (touched && ui->recompute->isChecked()) { auto obj = vp->getObject(); obj->touch(); obj->getDocument()->recompute(obj->getInListRecursive()); @@ -205,8 +225,9 @@ class ElementColors::Private: public Gui::SelectionGate App::GetApplication().closeActiveTransaction(); } - void removeAll() { - if(!elements.empty()) { + void removeAll() + { + if (!elements.empty()) { hiddenSub.clear(); ui->elementList->clear(); elements.clear(); @@ -214,93 +235,111 @@ class ElementColors::Private: public Gui::SelectionGate } } - void removeItems() { + void removeItems() + { const auto items = ui->elementList->selectedItems(); - for(auto item : items) { - std::string sub = qPrintable(item->data(Qt::UserRole+1).value()); - if(sub == hiddenSub) + for (auto item : items) { + std::string sub = qPrintable(item->data(Qt::UserRole + 1).value()); + if (sub == hiddenSub) { hiddenSub.clear(); + } elements.erase(sub); delete item; } apply(); } - void editItem(QWidget *parent, QListWidgetItem *item) { - std::string sub = qPrintable(item->data(Qt::UserRole+1).value()); - if(ViewProvider::hasHiddenMarker(sub.c_str())) + void editItem(QWidget* parent, QListWidgetItem* item) + { + std::string sub = qPrintable(item->data(Qt::UserRole + 1).value()); + if (ViewProvider::hasHiddenMarker(sub.c_str())) { return; + } auto color = item->data(Qt::UserRole).value(); QColorDialog cd(color, parent); cd.setOption(QColorDialog::ShowAlphaChannel); - if (DialogOptions::dontUseNativeColorDialog()) + if (DialogOptions::dontUseNativeColorDialog()) { cd.setOption(QColorDialog::DontUseNativeDialog); - if (cd.exec()!=QDialog::Accepted || color==cd.selectedColor()) + } + if (cd.exec() != QDialog::Accepted || color == cd.selectedColor()) { return; + } color = cd.selectedColor(); - item->setData(Qt::UserRole,color); + item->setData(Qt::UserRole, color); px.fill(color); item->setIcon(QIcon(px)); apply(); } - void onSelectionChanged(const SelectionChanges &msg) { + void onSelectionChanged(const SelectionChanges& msg) + { // no object selected in the combobox or no sub-element was selected - if (busy) + if (busy) { return; + } busy = true; - switch(msg.Type) { - case SelectionChanges::ClrSelection: - ui->elementList->clearSelection(); - break; - case SelectionChanges::AddSelection: - case SelectionChanges::RmvSelection: - if(msg.pDocName && msg.pObjectName && msg.pSubName && msg.pSubName[0]) { - if(editDoc == msg.pDocName && - editObj == msg.pObjectName && - boost::starts_with(msg.pSubName,editSub)) - { - const auto items = ui->elementList->findItems(QString::fromLatin1(msg.pSubName-editSub.size()), Qt::MatchExactly); - for(auto item : items) - item->setSelected(msg.Type==SelectionChanges::AddSelection); + switch (msg.Type) { + case SelectionChanges::ClrSelection: + ui->elementList->clearSelection(); + break; + case SelectionChanges::AddSelection: + case SelectionChanges::RmvSelection: + if (msg.pDocName && msg.pObjectName && msg.pSubName && msg.pSubName[0]) { + if (editDoc == msg.pDocName && editObj == msg.pObjectName + && boost::starts_with(msg.pSubName, editSub)) { + const auto items = ui->elementList->findItems( + QString::fromLatin1(msg.pSubName - editSub.size()), + Qt::MatchExactly); + for (auto item : items) { + item->setSelected(msg.Type == SelectionChanges::AddSelection); + } + } } - } - default: - break; + default: + break; } busy = false; } - void onSelectionChanged() { - if(busy) + void onSelectionChanged() + { + if (busy) { return; + } busy = true; - std::map sels; - for(auto &sel : Selection().getSelectionEx( - editDoc.c_str(),App::DocumentObject::getClassTypeId(), ResolveMode::NoResolve)) - { - if(sel.getFeatName()!=editObj) continue; - for(auto &sub : sel.getSubNames()) { - if(boost::starts_with(sub,editSub)) - sels[sub.c_str()+editSub.size()] = 1; + std::map sels; + for (auto& sel : Selection().getSelectionEx(editDoc.c_str(), + App::DocumentObject::getClassTypeId(), + ResolveMode::NoResolve)) { + if (sel.getFeatName() != editObj) { + continue; + } + for (auto& sub : sel.getSubNames()) { + if (boost::starts_with(sub, editSub)) { + sels[sub.c_str() + editSub.size()] = 1; + } } break; } const auto items = ui->elementList->selectedItems(); - for(auto item : items) { - std::string name(qPrintable(item->data(Qt::UserRole+1).value())); - if(ViewProvider::hasHiddenMarker(name.c_str())) + for (auto item : items) { + std::string name(qPrintable(item->data(Qt::UserRole + 1).value())); + if (ViewProvider::hasHiddenMarker(name.c_str())) { continue; - auto &v = sels[name]; - if(!v) + } + auto& v = sels[name]; + if (!v) { Selection().addSelection(editDoc.c_str(), - editObj.c_str(), (editSub+name).c_str()); + editObj.c_str(), + (editSub + name).c_str()); + } v = 2; } - for(auto &v : sels) { - if(v.second!=2) { + for (auto& v : sels) { + if (v.second != 2) { Selection().rmvSelection(editDoc.c_str(), - editObj.c_str(), (editSub+v.first).c_str()); + editObj.c_str(), + (editSub + v.first).c_str()); } } busy = false; @@ -310,34 +349,36 @@ class ElementColors::Private: public Gui::SelectionGate /* TRANSLATOR Gui::TaskElementColors */ ElementColors::ElementColors(ViewProviderDocumentObject* vp, bool noHide) - :d(new Private(vp)) + : d(new Private(vp)) { d->ui->setupUi(this); setupConnections(); d->ui->objectLabel->setText(QString::fromUtf8(vp->getObject()->Label.getValue())); - d->ui->elementList->setMouseTracking(true); // needed for itemEntered() to work + d->ui->elementList->setMouseTracking(true); // needed for itemEntered() to work if (noHide) { d->ui->hideSelection->setVisible(false); } - ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View"); - d->ui->recompute->setChecked(hPart->GetBool("ColorRecompute",true)); - d->ui->onTop->setChecked(hPart->GetBool("ColorOnTop",true)); + ParameterGrp::handle hPart = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); + d->ui->recompute->setChecked(hPart->GetBool("ColorRecompute", true)); + d->ui->onTop->setChecked(hPart->GetBool("ColorOnTop", true)); if (d->ui->onTop->isChecked()) { d->vpParent->OnTopWhenSelected.setValue(3); } Selection().addSelectionGate(d, ResolveMode::NoResolve); - //NOLINTBEGIN + // NOLINTBEGIN + // clang-format off d->connectDelDoc = Application::Instance->signalDeleteDocument.connect(std::bind (&ElementColors::slotDeleteDocument, this, sp::_1)); d->connectDelObj = Application::Instance->signalDeletedObject.connect(std::bind (&ElementColors::slotDeleteObject, this, sp::_1)); - //NOLINTEND + // clang-format on + // NOLINTEND d->populate(); } @@ -351,6 +392,7 @@ ElementColors::~ElementColors() void ElementColors::setupConnections() { + // clang-format off connect(d->ui->removeSelection, &QPushButton::clicked, this, &ElementColors::onRemoveSelectionClicked); connect(d->ui->addSelection, &QPushButton::clicked, @@ -371,33 +413,36 @@ void ElementColors::setupConnections() this, &ElementColors::onHideSelectionClicked); connect(d->ui->boxSelect, &QPushButton::clicked, this, &ElementColors::onBoxSelectClicked); + // clang-format on } void ElementColors::onRecomputeClicked(bool checked) { - ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View"); - hPart->SetBool("ColorRecompute",checked); + ParameterGrp::handle hPart = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); + hPart->SetBool("ColorRecompute", checked); } void ElementColors::onTopClicked(bool checked) { - ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View"); - hPart->SetBool("ColorOnTop",checked); - d->vpParent->OnTopWhenSelected.setValue(checked?3:d->onTopMode); + ParameterGrp::handle hPart = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); + hPart->SetBool("ColorOnTop", checked); + d->vpParent->OnTopWhenSelected.setValue(checked ? 3 : d->onTopMode); } void ElementColors::slotDeleteDocument(const Document& Doc) { - if (d->vpDoc==&Doc || d->editDoc==Doc.getDocument()->getName()) + if (d->vpDoc == &Doc || d->editDoc == Doc.getDocument()->getName()) { Control().closeDialog(); + } } void ElementColors::slotDeleteObject(const ViewProvider& obj) { - if (d->vp==&obj) + if (d->vp == &obj) { Control().closeDialog(); + } } void ElementColors::onRemoveSelectionClicked() @@ -408,22 +453,27 @@ void ElementColors::onRemoveSelectionClicked() void ElementColors::onBoxSelectClicked() { auto cmd = Application::Instance->commandManager().getCommandByName("Std_BoxElementSelection"); - if(cmd) + if (cmd) { cmd->invoke(0); + } } -void ElementColors::onHideSelectionClicked() { - auto sels = Selection().getSelectionEx(d->editDoc.c_str(), App::DocumentObject::getClassTypeId(), ResolveMode::NoResolve); - for(auto &sel : sels) { - if(d->editObj!=sel.getFeatName()) +void ElementColors::onHideSelectionClicked() +{ + auto sels = Selection().getSelectionEx(d->editDoc.c_str(), + App::DocumentObject::getClassTypeId(), + ResolveMode::NoResolve); + for (auto& sel : sels) { + if (d->editObj != sel.getFeatName()) { continue; - const auto &subs = sel.getSubNames(); - if(!subs.empty()) { - for(auto &sub : subs) { - if(boost::starts_with(sub,d->editSub)) { - auto name = Data::noElementName(sub.c_str()+d->editSub.size()); + } + const auto& subs = sel.getSubNames(); + if (!subs.empty()) { + for (auto& sub : subs) { + if (boost::starts_with(sub, d->editSub)) { + auto name = Data::noElementName(sub.c_str() + d->editSub.size()); name += ViewProvider::hiddenMarker(); - d->addItem(-1,name.c_str()); + d->addItem(-1, name.c_str()); } } d->apply(); @@ -434,37 +484,45 @@ void ElementColors::onHideSelectionClicked() { void ElementColors::onAddSelectionClicked() { - auto sels = Selection().getSelectionEx(d->editDoc.c_str(), App::DocumentObject::getClassTypeId(), ResolveMode::NoResolve); + auto sels = Selection().getSelectionEx(d->editDoc.c_str(), + App::DocumentObject::getClassTypeId(), + ResolveMode::NoResolve); d->items.clear(); - if(sels.empty()) - d->addItem(-1,"Face",true); + if (sels.empty()) { + d->addItem(-1, "Face", true); + } else { - for(auto &sel : sels) { - if(d->editObj!=sel.getFeatName()) + for (auto& sel : sels) { + if (d->editObj != sel.getFeatName()) { continue; - const auto &subs = sel.getSubNames(); - if(subs.empty()) { - d->addItem(-1,"Face",true); + } + const auto& subs = sel.getSubNames(); + if (subs.empty()) { + d->addItem(-1, "Face", true); break; } - for(auto &sub : subs) { - if(boost::starts_with(sub,d->editSub)) - d->addItem(-1,sub.c_str()+d->editSub.size(),true); + for (auto& sub : subs) { + if (boost::starts_with(sub, d->editSub)) { + d->addItem(-1, sub.c_str() + d->editSub.size(), true); + } } break; } } - if(!d->items.empty()) { + + if (!d->items.empty()) { auto color = d->items.front()->data(Qt::UserRole).value(); QColorDialog cd(color, this); cd.setOption(QColorDialog::ShowAlphaChannel); - if (DialogOptions::dontUseNativeColorDialog()) + if (DialogOptions::dontUseNativeColorDialog()) { cd.setOption(QColorDialog::DontUseNativeDialog); - if (cd.exec()!=QDialog::Accepted) + } + if (cd.exec() != QDialog::Accepted) { return; + } color = cd.selectedColor(); - for(auto item : d->items) { - item->setData(Qt::UserRole,color); + for (auto item : d->items) { + item->setData(Qt::UserRole, color); d->px.fill(color); item->setIcon(QIcon(d->px)); } @@ -491,7 +549,7 @@ bool ElementColors::reject() return true; } -void ElementColors::changeEvent(QEvent *e) +void ElementColors::changeEvent(QEvent* e) { QWidget::changeEvent(e); if (e->type() == QEvent::LanguageChange) { @@ -499,33 +557,44 @@ void ElementColors::changeEvent(QEvent *e) } } -void ElementColors::leaveEvent(QEvent *e) { +void ElementColors::leaveEvent(QEvent* e) +{ QWidget::leaveEvent(e); Selection().rmvPreselect(); - if(!d->hiddenSub.empty()) { - d->vp->partialRender({d->hiddenSub},false); + + if (!d->hiddenSub.empty()) { + d->vp->partialRender({d->hiddenSub}, false); d->hiddenSub.clear(); } } -void ElementColors::onElementListItemEntered(QListWidgetItem *item) { - std::string name(qPrintable(item->data(Qt::UserRole+1).value())); - if(!d->hiddenSub.empty()) { - d->vp->partialRender({d->hiddenSub},false); +void ElementColors::onElementListItemEntered(QListWidgetItem* item) +{ + std::string name(qPrintable(item->data(Qt::UserRole + 1).value())); + if (!d->hiddenSub.empty()) { + d->vp->partialRender({d->hiddenSub}, false); d->hiddenSub.clear(); } - if(ViewProvider::hasHiddenMarker(name.c_str())) { + + if (ViewProvider::hasHiddenMarker(name.c_str())) { d->hiddenSub = name; - d->vp->partialRender({name},true); - name.resize(name.size()-ViewProvider::hiddenMarker().size()); + d->vp->partialRender({name}, true); + name.resize(name.size() - ViewProvider::hiddenMarker().size()); } + Selection().setPreselect(d->editDoc.c_str(), - d->editObj.c_str(), (d->editSub+name).c_str(),0,0,0, - d->ui->onTop->isChecked() ? Gui::SelectionChanges::MsgSource::TreeView - : Gui::SelectionChanges::MsgSource::Internal); + d->editObj.c_str(), + (d->editSub + name).c_str(), + 0, + 0, + 0, + d->ui->onTop->isChecked() + ? Gui::SelectionChanges::MsgSource::TreeView + : Gui::SelectionChanges::MsgSource::Internal); } -void ElementColors::onElementListItemSelectionChanged() { +void ElementColors::onElementListItemSelectionChanged() +{ d->onSelectionChanged(); } @@ -534,23 +603,23 @@ void ElementColors::onSelectionChanged(const SelectionChanges& msg) d->onSelectionChanged(msg); } -void ElementColors::onElementListItemDoubleClicked(QListWidgetItem *item) { - d->editItem(this,item); +void ElementColors::onElementListItemDoubleClicked(QListWidgetItem* item) +{ + d->editItem(this, item); } /* TRANSLATOR Gui::TaskElementColors */ TaskElementColors::TaskElementColors(ViewProviderDocumentObject* vp, bool noHide) { - widget = new ElementColors(vp,noHide); + widget = new ElementColors(vp, noHide); addTaskBox(widget); } TaskElementColors::~TaskElementColors() = default; void TaskElementColors::open() -{ -} +{} void TaskElementColors::clicked(int) { From 5202748c0a43b0dd4c58af68c43ef9682e8ab4a2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Nov 2024 00:46:52 +0100 Subject: [PATCH 120/161] Gui: Fix some linter warnings --- src/Gui/TaskElementColors.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Gui/TaskElementColors.cpp b/src/Gui/TaskElementColors.cpp index d5c007536d21..0ccd998e20df 100644 --- a/src/Gui/TaskElementColors.cpp +++ b/src/Gui/TaskElementColors.cpp @@ -75,10 +75,10 @@ class ElementColors::Private: public Gui::SelectionGate explicit Private(ViewProviderDocumentObject* vp, const char* element = "") : ui(new Ui_TaskElementColors()) , vp(vp) + , vpParent(vp) + , vpDoc(vp->getDocument()) , editElement(element) { - vpDoc = vp->getDocument(); - vpParent = vp; auto doc = Application::Instance->editDocument(); if (doc) { auto editVp = doc->getInEdit(&vpParent, &editSub); @@ -164,7 +164,7 @@ class ElementColors::Private: public Gui::SelectionGate } for (auto& v : vp->getElementColors(sub)) { - auto it = elements.find(v.first.c_str()); + auto it = elements.find(v.first); if (it != elements.end()) { if (push) { items.push_back(it->second); @@ -194,10 +194,9 @@ class ElementColors::Private: public Gui::SelectionGate int count = ui->elementList->count(); for (int i = 0; i < count; ++i) { auto item = ui->elementList->item(i); - auto color = item->data(Qt::UserRole).value(); - info.emplace( - qPrintable(item->data(Qt::UserRole + 1).value()), - App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF())); + auto col = item->data(Qt::UserRole).value(); + std::string sub = qPrintable(item->data(Qt::UserRole + 1).value()); + info.emplace(sub, App::Color(col.redF(), col.greenF(), col.blueF(), col.alphaF())); } if (!App::GetApplication().getActiveTransaction()) { App::GetApplication().setActiveTransaction("Set colors"); @@ -621,8 +620,9 @@ TaskElementColors::~TaskElementColors() = default; void TaskElementColors::open() {} -void TaskElementColors::clicked(int) +void TaskElementColors::clicked(int id) { + Q_UNUSED(id) } bool TaskElementColors::accept() From f51804729e8710a24bc93afae60662238abecbdc Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 22 Nov 2024 14:23:16 +0100 Subject: [PATCH 121/161] Start: Fix extracting thumbnails on Windows --- src/Mod/Start/App/DisplayedFilesModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Start/App/DisplayedFilesModel.cpp b/src/Mod/Start/App/DisplayedFilesModel.cpp index d7607b767273..70898fc77b92 100644 --- a/src/Mod/Start/App/DisplayedFilesModel.cpp +++ b/src/Mod/Start/App/DisplayedFilesModel.cpp @@ -168,7 +168,7 @@ QByteArray loadFCStdThumbnail(const std::string& pathToFCStdFile) if (proj.containsFile(thumb)) { createThumbnailsDir(); Base::FileInfo fi(thumbnailFile); - Base::ofstream str(fi); + Base::ofstream str(fi, std::ios::in | std::ios::binary); proj.readInputFileDirect(thumb, str); str.close(); } From f7da5f8505586fdec5e8d32670365ddee7c18429 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 11 Nov 2024 23:22:49 +0100 Subject: [PATCH 122/161] Core: Implement SoFCTransform node In its doAction() method it only sets the model matrix if it's not the identity matrix. This improves the issue #7606 --- src/Gui/CMakeLists.txt | 2 + src/Gui/Inventor/SoFCTransform.cpp | 91 ++++++++++++++++++++++++++++++ src/Gui/Inventor/SoFCTransform.h | 54 ++++++++++++++++++ src/Gui/SoFCDB.cpp | 2 + src/Gui/ViewProvider.cpp | 3 +- 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/Gui/Inventor/SoFCTransform.cpp create mode 100644 src/Gui/Inventor/SoFCTransform.h diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index ad10921ae214..2bf2d8428609 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1025,6 +1025,7 @@ SET(Inventor_CPP_SRCS Inventor/SoFCBackgroundGradient.cpp Inventor/SoFCBoundingBox.cpp Inventor/SoMouseWheelEvent.cpp + Inventor/SoFCTransform.cpp SoFCColorBar.cpp SoFCColorBarNotifier.cpp SoFCColorGradient.cpp @@ -1055,6 +1056,7 @@ SET(Inventor_SRCS Inventor/SoFCBackgroundGradient.h Inventor/SoFCBoundingBox.h Inventor/SoMouseWheelEvent.h + Inventor/SoFCTransform.h SoFCColorBar.h SoFCColorBarNotifier.h SoFCColorGradient.h diff --git a/src/Gui/Inventor/SoFCTransform.cpp b/src/Gui/Inventor/SoFCTransform.cpp new file mode 100644 index 000000000000..c0bb145a70b9 --- /dev/null +++ b/src/Gui/Inventor/SoFCTransform.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#include +#include +#include +#include +#include +#include +#endif + +#include "SoFCTransform.h" + + +using namespace Gui; + +SO_NODE_SOURCE(SoFCTransform) + +void SoFCTransform::initClass() +{ + SO_NODE_INIT_CLASS(SoFCTransform, SoTransform, "Transform"); +} + +SoFCTransform::SoFCTransform() +{ + SO_NODE_CONSTRUCTOR(SoFCTransform); +} + +void SoFCTransform::GLRender(SoGLRenderAction * action) +{ + SoFCTransform::doAction(action); +} + +void SoFCTransform::callback(SoCallbackAction * action) +{ + SoFCTransform::doAction(action); +} + +void SoFCTransform::pick(SoPickAction * action) +{ + SoFCTransform::doAction(action); +} + +void SoFCTransform::getPrimitiveCount(SoGetPrimitiveCountAction * action) +{ + SoFCTransform::doAction(action); +} + +void SoFCTransform::getBoundingBox(SoGetBoundingBoxAction * action) +{ + SoFCTransform::doAction(action); +} + +void SoFCTransform::doAction(SoAction * action) +{ + SbMatrix matrix; + matrix.setTransform(this->translation.getValue(), + this->rotation.getValue(), + this->scaleFactor.getValue(), + this->scaleOrientation.getValue(), + this->center.getValue()); + + // This is different to SoTransform::doAction() where model matrix + // is always set + if (matrix != SbMatrix::identity()) { + SoModelMatrixElement::mult(action->getState(), this, matrix); + } +} diff --git a/src/Gui/Inventor/SoFCTransform.h b/src/Gui/Inventor/SoFCTransform.h new file mode 100644 index 000000000000..9e79f64c3c51 --- /dev/null +++ b/src/Gui/Inventor/SoFCTransform.h @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef GUI_INVENTOR_SOFCTRANSFORM_H +#define GUI_INVENTOR_SOFCTRANSFORM_H + +#include +#include + +namespace Gui +{ + +class GuiExport SoFCTransform : public SoTransform +{ + using inherited = SoTransform; + + SO_NODE_HEADER(SoFCTransform); + +public: + static void initClass(); + SoFCTransform(); + +protected: + void GLRender(SoGLRenderAction * action) override; + void callback(SoCallbackAction * action) override; + void pick(SoPickAction * action) override; + void getPrimitiveCount(SoGetPrimitiveCountAction * action) override; + void getBoundingBox(SoGetBoundingBoxAction * action) override; + void doAction(SoAction * action) override; +}; + +} // namespace Gui + +#endif // GUI_INVENTOR_SOFCTRANSFORM_H diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 26b17df1729e..fc746a2fbe95 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -74,6 +74,7 @@ #include "Inventor/SoFCBackgroundGradient.h" #include "Inventor/SoFCBoundingBox.h" #include "Inventor/SoMouseWheelEvent.h" +#include "Inventor/SoFCTransform.h" #include "propertyeditor/PropertyItem.h" #include "ArcEngine.h" @@ -134,6 +135,7 @@ void Gui::SoFCDB::init() SoAxisCrossKit ::initClass(); SoRegPoint ::initClass(); SoDrawingGrid ::initClass(); + SoFCTransform ::initClass(); SoAutoZoomTranslation ::initClass(); MarkerBitmaps ::initClass(); SoFCCSysDragger ::initClass(); diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index fdd63583bede..95085b677d70 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -42,6 +42,7 @@ #include #include "Inventor/SoMouseWheelEvent.h" +#include "Inventor/SoFCTransform.h" #include "ViewProvider.h" #include "ActionFunction.h" #include "Application.h" @@ -104,7 +105,7 @@ ViewProvider::ViewProvider() pcRoot->ref(); pcModeSwitch = new SoSwitch(); pcModeSwitch->ref(); - pcTransform = new SoTransform(); + pcTransform = new SoFCTransform(); pcTransform->ref(); pcRoot->addChild(pcTransform); pcRoot->addChild(pcModeSwitch); From c0b9191cf54fec2760da78819f2623408e8063fa Mon Sep 17 00:00:00 2001 From: wwmayer Date: Sun, 17 Nov 2024 08:30:29 +0100 Subject: [PATCH 123/161] Add doc string to SoFCTransform Co-authored-by: Benjamin Nauck --- src/Gui/Inventor/SoFCTransform.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Gui/Inventor/SoFCTransform.h b/src/Gui/Inventor/SoFCTransform.h index 9e79f64c3c51..806377dd7029 100644 --- a/src/Gui/Inventor/SoFCTransform.h +++ b/src/Gui/Inventor/SoFCTransform.h @@ -30,6 +30,17 @@ namespace Gui { +/** + * @class SoFCTransform + * @brief A temporary workaround for coin3d/coin#534. + * + * This class is a workaround for a missing feature to reduce the OpenGL stack size. + * The issue was reported here: https://github.com/coin3d/coin/issues/534 + * And was merged here: https://github.com/coin3d/coin/pull/535 + * + * Once this feature is available in all supported versions of Coin3D, this class should + * be removed and all instances should revert to using SoTransform. + */ class GuiExport SoFCTransform : public SoTransform { using inherited = SoTransform; From c534e655f98948c7f428abb28ed5fd6df009a610 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 19 Nov 2024 21:04:30 +0100 Subject: [PATCH 124/161] Mesh: Improve 3MF format to support files from 'Make World' --- src/Mod/Mesh/App/Core/IO/Reader3MF.cpp | 398 +++++++++++++++++-------- src/Mod/Mesh/App/Core/IO/Reader3MF.h | 57 ++-- 2 files changed, 310 insertions(+), 145 deletions(-) diff --git a/src/Mod/Mesh/App/Core/IO/Reader3MF.cpp b/src/Mod/Mesh/App/Core/IO/Reader3MF.cpp index 63d4d0cf7bb2..6f7610173e85 100644 --- a/src/Mod/Mesh/App/Core/IO/Reader3MF.cpp +++ b/src/Mod/Mesh/App/Core/IO/Reader3MF.cpp @@ -41,26 +41,21 @@ using namespace MeshCore; -#ifndef XERCES_CPP_NAMESPACE_BEGIN -#define XERCES_CPP_NAMESPACE_QUALIFIER using namespace XERCES_CPP_NAMESPACE; -#else -XERCES_CPP_NAMESPACE_USE -#endif Reader3MF::Reader3MF(std::istream& str) { - zipios::ZipHeader zipHeader(str); - if (zipHeader.isValid()) { - zip.reset(zipHeader.getInputStream("3D/3dmodel.model")); + file = std::make_unique(str); + if (file->isValid()) { + zip.reset(file->getInputStream("3D/3dmodel.model")); } } Reader3MF::Reader3MF(const std::string& filename) { - zipios::ZipFile zipFile(filename); - if (zipFile.isValid()) { - zip.reset(zipFile.getInputStream("3D/3dmodel.model")); + file = std::make_unique(filename); + if (file->isValid()) { + zip.reset(file->getInputStream("3D/3dmodel.model")); } } @@ -78,30 +73,36 @@ std::vector Reader3MF::GetMeshIds() const bool Reader3MF::Load() { try { - if (!zip) { - return false; - } - return LoadModel(*zip); + return TryLoad(); } catch (const std::exception&) { return false; } } +bool Reader3MF::TryLoad() +{ + if (!zip) { + return false; + } + if (LoadModel(*zip)) { + return true; + } + + return LoadMeshFromComponents(); +} + bool Reader3MF::LoadModel(std::istream& str) +{ + Component comp; + comp.path = "3dmodel.model"; + return LoadModel(str, comp); +} + +bool Reader3MF::LoadModel(std::istream& str, const Component& comp) { try { - std::unique_ptr parser(new XercesDOMParser); - parser->setValidationScheme(XercesDOMParser::Val_Auto); - parser->setDoNamespaces(false); - parser->setDoSchema(false); - parser->setValidationSchemaFullChecking(false); - parser->setCreateEntityReferenceNodes(false); - - Base::StdInputSource inputSource(str, "3dmodel.model"); - parser->parse(inputSource); - std::unique_ptr xmlDocument(parser->adoptDocument()); - return LoadModel(*xmlDocument); + return TryLoadModel(str, comp); } catch (const XMLException&) { return false; @@ -111,24 +112,52 @@ bool Reader3MF::LoadModel(std::istream& str) } } -bool Reader3MF::LoadModel(XERCES_CPP_NAMESPACE::DOMDocument& xmlDocument) +std::unique_ptr Reader3MF::makeDomParser() +{ + std::unique_ptr parser(new XercesDOMParser); + parser->setValidationScheme(XercesDOMParser::Val_Auto); + parser->setDoNamespaces(false); + parser->setDoSchema(false); + parser->setValidationSchemaFullChecking(false); + parser->setCreateEntityReferenceNodes(false); + return parser; +} + +bool Reader3MF::TryLoadModel(std::istream& str, const Component& comp) +{ + if (!str) { + return false; + } + + Base::StdInputSource inputSource(str, comp.path.c_str()); + std::unique_ptr parser = makeDomParser(); + parser->parse(inputSource); + std::unique_ptr xmlDocument(parser->adoptDocument()); + return LoadModel(*xmlDocument, comp); +} + +bool Reader3MF::LoadModel(DOMDocument& xmlDocument, const Component& comp) { DOMNodeList* nodes = xmlDocument.getElementsByTagName(XStr("model").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - bool resource = LoadResources(static_cast(node)->getElementsByTagName( - XStr("resources").unicodeForm())); - bool build = LoadBuild( - static_cast(node)->getElementsByTagName(XStr("build").unicodeForm())); - return (resource && build); + return LoadResourcesAndBuild(static_cast(node), comp); } } return false; } -bool Reader3MF::LoadResources(DOMNodeList* nodes) +bool Reader3MF::LoadResourcesAndBuild(DOMElement* node, const Component& comp) +{ + bool resource = + LoadResources(node->getElementsByTagName(XStr("resources").unicodeForm()), comp); + bool build = LoadBuild(node->getElementsByTagName(XStr("build").unicodeForm())); + return (resource && build); +} + +bool Reader3MF::LoadResources(DOMNodeList* nodes, const Component& comp) { if (!nodes) { return false; @@ -137,16 +166,16 @@ bool Reader3MF::LoadResources(DOMNodeList* nodes) for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("object").unicodeForm()); - return LoadObjects(objectList); + auto elem = static_cast(node); + DOMNodeList* objectList = elem->getElementsByTagName(XStr("object").unicodeForm()); + return LoadObject(objectList, comp); } } return false; } -bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) +bool Reader3MF::LoadBuild(DOMNodeList* nodes) { if (!nodes) { return false; @@ -155,8 +184,8 @@ bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* objectList = - static_cast(node)->getElementsByTagName(XStr("item").unicodeForm()); + auto elem = static_cast(node); + DOMNodeList* objectList = elem->getElementsByTagName(XStr("item").unicodeForm()); return LoadItems(objectList); } } @@ -164,57 +193,85 @@ bool Reader3MF::LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) return false; } -bool Reader3MF::LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) +bool Reader3MF::LoadItems(DOMNodeList* nodes) { - const std::size_t numEntries = 12; if (!nodes) { return false; } for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* itemNode = nodes->item(i); - DOMNode* idAttr = itemNode->getAttributes()->getNamedItem(XStr("objectid").unicodeForm()); - if (idAttr) { - std::string id = StrX(idAttr->getNodeValue()).c_str(); - int idValue = std::stoi(id); - Base::Matrix4D mat; + DOMNamedNodeMap* nodeMap = itemNode->getAttributes(); + LoadItem(nodeMap); + } + + return true; +} + +void Reader3MF::LoadItem(DOMNamedNodeMap* nodeMap) +{ + DOMNode* idAttr = nodeMap->getNamedItem(XStr("objectid").unicodeForm()); + if (idAttr) { + std::string id = StrX(idAttr->getNodeValue()).c_str(); + int idValue = std::stoi(id); + + DOMNode* transformAttr = nodeMap->getNamedItem(XStr("transform").unicodeForm()); + if (transformAttr) { + std::optional mat = ReadTransform(transformAttr); + if (mat) { + auto it = meshes.find(idValue); + if (it != meshes.end()) { + it->second.second = mat.value(); + } - DOMNode* transformAttr = - itemNode->getAttributes()->getNamedItem(XStr("transform").unicodeForm()); - if (transformAttr) { - std::string transform = StrX(transformAttr->getNodeValue()).c_str(); - boost::char_separator sep(" ,"); - boost::tokenizer> tokens(transform, sep); - std::vector token_results; - token_results.assign(tokens.begin(), tokens.end()); - if (token_results.size() == numEntries) { - mat[0][0] = std::stod(token_results[0]); - mat[1][0] = std::stod(token_results[1]); - mat[2][0] = std::stod(token_results[2]); - mat[0][1] = std::stod(token_results[3]); - mat[1][1] = std::stod(token_results[4]); - mat[2][1] = std::stod(token_results[5]); - mat[0][2] = std::stod(token_results[6]); - mat[1][2] = std::stod(token_results[7]); - mat[2][2] = std::stod(token_results[8]); - mat[0][3] = std::stod(token_results[9]); - mat[1][3] = std::stod(token_results[10]); - mat[2][3] = std::stod(token_results[11]); - - try { - meshes.at(idValue).second = mat; - } - catch (const std::exception&) { - } + auto jt = std::find_if(components.begin(), + components.end(), + [idValue](const Component& comp) { + return comp.id == idValue; + }); + if (jt != components.end()) { + jt->transform = mat.value(); } } } } +} - return true; +std::optional Reader3MF::ReadTransform(DOMNode* transformAttr) +{ + constexpr const std::size_t numEntries = 12; + using Pos2d = std::array, numEntries>; + // clang-format off + static Pos2d pos = {{ + {0, 0}, {1, 0}, {2, 0}, + {0, 1}, {1, 1}, {2, 1}, + {0, 2}, {1, 2}, {2, 2}, + {0, 3}, {1, 3}, {2, 3} + }}; + // clang-format on + + if (transformAttr) { + std::string transform = StrX(transformAttr->getNodeValue()).c_str(); + boost::char_separator sep(" ,"); + boost::tokenizer> tokens(transform, sep); + std::vector token_results; + token_results.assign(tokens.begin(), tokens.end()); + if (token_results.size() == numEntries) { + Base::Matrix4D mat; + // NOLINTBEGIN + int index = 0; + for (const auto& it : pos) { + auto [r, c] = it; + mat[r][c] = std::stod(token_results[index++]); + } + // NOLINTEND + return mat; + } + } + return {}; } -bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) +bool Reader3MF::LoadObject(DOMNodeList* nodes, const Component& comp) { if (!nodes) { return false; @@ -224,11 +281,18 @@ bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) DOMNode* objectNode = nodes->item(i); if (objectNode->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNode* idAttr = objectNode->getAttributes()->getNamedItem(XStr("id").unicodeForm()); + auto elem = static_cast(objectNode); if (idAttr) { int id = std::stoi(StrX(idAttr->getNodeValue()).c_str()); - DOMNodeList* meshList = static_cast(objectNode) - ->getElementsByTagName(XStr("mesh").unicodeForm()); - LoadMesh(meshList, id); + DOMNodeList* meshNode = elem->getElementsByTagName(XStr("mesh").unicodeForm()); + if (meshNode->getLength() > 0) { + LoadMesh(meshNode, id, comp); + } + else { + DOMNodeList* compNode = + elem->getElementsByTagName(XStr("components").unicodeForm()); + LoadComponents(compNode, id); + } } } } @@ -236,7 +300,77 @@ bool Reader3MF::LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes) return (!meshes.empty()); } -void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int id) +bool Reader3MF::LoadMeshFromComponents() +{ + for (const auto& it : components) { + std::string path = it.path.substr(1); + zip.reset(file->getInputStream(path)); + LoadModel(*zip, it); + } + + return (!meshes.empty()); +} + +void Reader3MF::LoadComponents(DOMNodeList* nodes, int id) +{ + if (!nodes) { + return; + } + + for (XMLSize_t i = 0; i < nodes->getLength(); i++) { + DOMNode* objectNode = nodes->item(i); + if (objectNode->getNodeType() == DOMNode::ELEMENT_NODE) { + auto elem = static_cast(objectNode); + DOMNodeList* compNode = elem->getElementsByTagName(XStr("component").unicodeForm()); + if (compNode->getLength() > 0) { + LoadComponent(compNode, id); + } + } + } +} + +void Reader3MF::LoadComponent(DOMNodeList* nodes, int id) +{ + if (!nodes) { + return; + } + + for (XMLSize_t i = 0; i < nodes->getLength(); i++) { + DOMNode* compNode = nodes->item(i); + if (compNode->getNodeType() == DOMNode::ELEMENT_NODE) { + if (DOMNamedNodeMap* attr = compNode->getAttributes()) { + LoadComponent(attr, id); + } + } + } +} + +void Reader3MF::LoadComponent(DOMNamedNodeMap* attr, int id) +{ + auto validComponent = [](const Component& comp) { + return (comp.id > 0 && comp.objectId >= 0 && !comp.path.empty()); + }; + + Component component; + component.id = id; + if (DOMNode* pathAttr = attr->getNamedItem(XStr("p:path").unicodeForm())) { + component.path = StrX(pathAttr->getNodeValue()).c_str(); + } + if (DOMNode* idAttr = attr->getNamedItem(XStr("objectid").unicodeForm())) { + component.objectId = std::stoi(StrX(idAttr->getNodeValue()).c_str()); + } + if (DOMNode* transformAttr = attr->getNamedItem(XStr("transform").unicodeForm())) { + std::optional mat = ReadTransform(transformAttr); + if (mat) { + component.transform = mat.value(); + } + } + if (validComponent(component)) { + components.push_back(component); + } +} + +void Reader3MF::LoadMesh(DOMNodeList* nodes, int id, const Component& comp) { if (!nodes) { return; @@ -245,29 +379,26 @@ void Reader3MF::LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, int for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { + auto elem = static_cast(node); MeshPointArray points; MeshFacetArray facets; - LoadVertices(static_cast(node)->getElementsByTagName( - XStr("vertices").unicodeForm()), - points); - LoadTriangles(static_cast(node)->getElementsByTagName( - XStr("triangles").unicodeForm()), - facets); + LoadVertices(elem->getElementsByTagName(XStr("vertices").unicodeForm()), points); + LoadTriangles(elem->getElementsByTagName(XStr("triangles").unicodeForm()), facets); MeshCleanup meshCleanup(points, facets); meshCleanup.RemoveInvalids(); MeshPointFacetAdjacency meshAdj(points.size(), facets); meshAdj.SetFacetNeighbourhood(); + Base::Matrix4D mat = comp.transform; MeshKernel kernel; kernel.Adopt(points, facets); - meshes.emplace(id, std::make_pair(kernel, Base::Matrix4D())); + meshes.emplace(id, std::make_pair(kernel, mat)); } } } -void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, - MeshPointArray& points) +void Reader3MF::LoadVertices(DOMNodeList* nodes, MeshPointArray& points) { if (!nodes) { return; @@ -276,33 +407,39 @@ void Reader3MF::LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* vertexList = - static_cast(node)->getElementsByTagName(XStr("vertex").unicodeForm()); + auto elem = static_cast(node); + DOMNodeList* vertexList = elem->getElementsByTagName(XStr("vertex").unicodeForm()); if (vertexList) { - XMLSize_t numVertices = vertexList->getLength(); - points.reserve(numVertices); - for (XMLSize_t j = 0; j < numVertices; j++) { - DOMNode* vertexNode = vertexList->item(j); - DOMNamedNodeMap* attr = vertexNode->getAttributes(); - if (attr) { - DOMNode* xAttr = attr->getNamedItem(XStr("x").unicodeForm()); - DOMNode* yAttr = attr->getNamedItem(XStr("y").unicodeForm()); - DOMNode* zAttr = attr->getNamedItem(XStr("z").unicodeForm()); - if (xAttr && yAttr && zAttr) { - float x = std::stof(StrX(xAttr->getNodeValue()).c_str()); - float y = std::stof(StrX(yAttr->getNodeValue()).c_str()); - float z = std::stof(StrX(zAttr->getNodeValue()).c_str()); - points.emplace_back(x, y, z); - } - } - } + ReadVertices(vertexList, points); } } } } -void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, - MeshFacetArray& facets) +void Reader3MF::ReadVertices(DOMNodeList* vertexList, MeshPointArray& points) +{ + XMLSize_t numVertices = vertexList->getLength(); + points.reserve(numVertices); + for (XMLSize_t j = 0; j < numVertices; j++) { + DOMNode* vertexNode = vertexList->item(j); + DOMNamedNodeMap* attr = vertexNode->getAttributes(); + if (attr) { + DOMNode* xAttr = attr->getNamedItem(XStr("x").unicodeForm()); + DOMNode* yAttr = attr->getNamedItem(XStr("y").unicodeForm()); + DOMNode* zAttr = attr->getNamedItem(XStr("z").unicodeForm()); + if (xAttr && yAttr && zAttr) { + // NOLINTBEGIN + float x = std::stof(StrX(xAttr->getNodeValue()).c_str()); + float y = std::stof(StrX(yAttr->getNodeValue()).c_str()); + float z = std::stof(StrX(zAttr->getNodeValue()).c_str()); + points.emplace_back(x, y, z); + // NOLINTEND + } + } + } +} + +void Reader3MF::LoadTriangles(DOMNodeList* nodes, MeshFacetArray& facets) { if (!nodes) { return; @@ -311,26 +448,31 @@ void Reader3MF::LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList* nodes, for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { - DOMNodeList* triangleList = static_cast(node)->getElementsByTagName( - XStr("triangle").unicodeForm()); + auto elem = static_cast(node); + DOMNodeList* triangleList = elem->getElementsByTagName(XStr("triangle").unicodeForm()); if (triangleList) { - XMLSize_t numTriangles = triangleList->getLength(); - facets.reserve(numTriangles); - for (XMLSize_t j = 0; j < numTriangles; j++) { - DOMNode* triangleNode = triangleList->item(j); - DOMNamedNodeMap* attr = triangleNode->getAttributes(); - if (attr) { - DOMNode* v1Attr = attr->getNamedItem(XStr("v1").unicodeForm()); - DOMNode* v2Attr = attr->getNamedItem(XStr("v2").unicodeForm()); - DOMNode* v3Attr = attr->getNamedItem(XStr("v3").unicodeForm()); - if (v1Attr && v2Attr && v3Attr) { - PointIndex v1 = std::stoul(StrX(v1Attr->getNodeValue()).c_str()); - PointIndex v2 = std::stoul(StrX(v2Attr->getNodeValue()).c_str()); - PointIndex v3 = std::stoul(StrX(v3Attr->getNodeValue()).c_str()); - facets.emplace_back(v1, v2, v3); - } - } - } + ReadTriangles(triangleList, facets); + } + } + } +} + +void Reader3MF::ReadTriangles(DOMNodeList* triangleList, MeshFacetArray& facets) +{ + XMLSize_t numTriangles = triangleList->getLength(); + facets.reserve(numTriangles); + for (XMLSize_t j = 0; j < numTriangles; j++) { + DOMNode* triangleNode = triangleList->item(j); + DOMNamedNodeMap* attr = triangleNode->getAttributes(); + if (attr) { + DOMNode* v1Attr = attr->getNamedItem(XStr("v1").unicodeForm()); + DOMNode* v2Attr = attr->getNamedItem(XStr("v2").unicodeForm()); + DOMNode* v3Attr = attr->getNamedItem(XStr("v3").unicodeForm()); + if (v1Attr && v2Attr && v3Attr) { + PointIndex v1 = std::stoul(StrX(v1Attr->getNodeValue()).c_str()); + PointIndex v2 = std::stoul(StrX(v2Attr->getNodeValue()).c_str()); + PointIndex v3 = std::stoul(StrX(v3Attr->getNodeValue()).c_str()); + facets.emplace_back(v1, v2, v3); } } } diff --git a/src/Mod/Mesh/App/Core/IO/Reader3MF.h b/src/Mod/Mesh/App/Core/IO/Reader3MF.h index 13c837d2fe7c..bc261061f268 100644 --- a/src/Mod/Mesh/App/Core/IO/Reader3MF.h +++ b/src/Mod/Mesh/App/Core/IO/Reader3MF.h @@ -28,23 +28,24 @@ #include #include #include +#include #include #include -#ifndef XERCES_CPP_NAMESPACE_BEGIN -#define XERCES_CPP_NAMESPACE_QUALIFIER -using namespace XERCES_CPP_NAMESPACE; namespace XERCES_CPP_NAMESPACE { class DOMDocument; +class DOMElement; +class DOMNode; class DOMNodeList; +class DOMNamedNodeMap; +class XercesDOMParser; } // namespace XERCES_CPP_NAMESPACE -#else -XERCES_CPP_NAMESPACE_BEGIN -class DOMDocument; -class DOMNodeList; -XERCES_CPP_NAMESPACE_END -#endif + +namespace zipios +{ +class FileCollection; +} namespace MeshCore { @@ -84,19 +85,41 @@ class MeshExport Reader3MF } private: + struct Component + { + int id = -1; + int objectId = -1; + std::string path; + Base::Matrix4D transform; + }; + static std::unique_ptr makeDomParser(); + bool TryLoad(); bool LoadModel(std::istream&); - bool LoadModel(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument&); - bool LoadResources(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*); - bool LoadBuild(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*); - bool LoadItems(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*); - bool LoadObjects(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*); - void LoadMesh(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, int id); - void LoadVertices(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, MeshPointArray&); - void LoadTriangles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList*, MeshFacetArray&); + bool LoadModel(std::istream&, const Component&); + bool TryLoadModel(std::istream&, const Component&); + bool LoadModel(XERCES_CPP_NAMESPACE::DOMDocument&, const Component&); + bool LoadResourcesAndBuild(XERCES_CPP_NAMESPACE::DOMElement*, const Component&); + bool LoadResources(XERCES_CPP_NAMESPACE::DOMNodeList*, const Component&); + bool LoadBuild(XERCES_CPP_NAMESPACE::DOMNodeList*); + bool LoadItems(XERCES_CPP_NAMESPACE::DOMNodeList*); + void LoadItem(XERCES_CPP_NAMESPACE::DOMNamedNodeMap*); + bool LoadObject(XERCES_CPP_NAMESPACE::DOMNodeList*, const Component&); + void LoadComponents(XERCES_CPP_NAMESPACE::DOMNodeList*, int id); + void LoadComponent(XERCES_CPP_NAMESPACE::DOMNodeList*, int id); + void LoadComponent(XERCES_CPP_NAMESPACE::DOMNamedNodeMap*, int id); + void LoadMesh(XERCES_CPP_NAMESPACE::DOMNodeList*, int id, const Component&); + void LoadVertices(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshPointArray&); + void ReadVertices(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshPointArray&); + void LoadTriangles(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshFacetArray&); + void ReadTriangles(XERCES_CPP_NAMESPACE::DOMNodeList*, MeshFacetArray&); + bool LoadMeshFromComponents(); + std::optional ReadTransform(XERCES_CPP_NAMESPACE::DOMNode*); private: + std::vector components; using MeshKernelAndTransform = std::pair; std::unordered_map meshes; + std::unique_ptr file; std::unique_ptr zip; }; From 597e42d12f04695cd48091944b0c86196e70db14 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 20 Nov 2024 14:35:10 +0100 Subject: [PATCH 125/161] Test: Add unit test to read in 3MF file --- data/tests/mesh.3mf | Bin 0 -> 12279 bytes tests/src/Mod/Mesh/App/CMakeLists.txt | 3 +++ tests/src/Mod/Mesh/App/Importer.cpp | 30 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 data/tests/mesh.3mf create mode 100644 tests/src/Mod/Mesh/App/Importer.cpp diff --git a/data/tests/mesh.3mf b/data/tests/mesh.3mf new file mode 100644 index 0000000000000000000000000000000000000000..be9b26e41bba001553f854430b636b9c854aaa3c GIT binary patch literal 12279 zcmbt)1z1#Vw>DiviZV!}f^;Y;Eush_AV^E2BEx`m!%zmL(jhG&HKMeHq!Lnsbf@G< zN}fHl$78(j`L6T-XS^;SMmMYPd#yF|XsF^7oW#cgUWK+!`snlL3;mB5uLx>jA0WXz zkazKo#yBnx&RGH+9BS}^i^;r0g-r>;+3A$?N`q(J5XN`U{^poDVP~N zI{`hJOd@rBJ(vn^WO?JMT_%}-)3*V|jO^=-r*3~-9zFL$T-#-TlSDzomyY>Mj&XYN zqJLhMuj?*nJ5svY>dR_C2Xa--{Nn}VkKMAql9jJeBMbL&Wz z`;w@5*H*2q@28cp=M3^Iyp}wb>ewL2akk5Xikkq{cm68N8kzb&cdt|)ti7cZ>NoCA z6Cu;M%yRrO?sS`##=;k>n+wr5PDqkSu^I{G;wc>o98phbos;b}TB2RJ73&+cx|F$+ zQ-95BTd9>CP%&l#P9W70NzJWH2T&>9nSD%;eM%|ML8+NSvy&+CLrOIwwh3iEfV&RTN` zXH^n{zj}=d=r(PPIo@Zuqo_H2!dRTGMCY-XbDJbv&ilFH$+9QT5^~)~tUrqZ2j}3g zYJq^opl<%a%EHOc*+sWoN@29k@ zyoVO^<~hwU6rmU^4)@I%JffU#nZx_tR-?;9K@f=<*BZh3B&Om^ZDcn`^wMr4URa0v z@n)%}jgh_c9=#HAza)t|SJhadAdvUj$=e*~Tu0c}2Sc8U@#%JNzdFnHvN9z@kK+sT7NHN_{EWf$>@*;8iCLz0hY{u97ko%2k&&wWd6E^CuUirBH z^vCJXgijp^V(q;HA;-Z-9V6G$QSBsowc1x7U)i}$vbz0L;_Sghp4h5a9XGc|=tNZM zp_~<=O27@l7$UxH&+-IH(;wx*?L<6bQd!qo zW1Mfyhxmu_vWVpen$i4cm}04s!#oVHmyH=0&psaBn5OI} zFu6?v-*J)rLGUxLBsl(XC;b(>kBUJ|I5@jTxHzZ(N|!s#8g6Oj0H!QyxEp>#liF|6 zGsXPvPJO)Oz0d8!N){qDetS5|x=kmA{H}U?~|s$>QBI`&rK)u+Q7YSwOU zMOMvLGnYn;*BosT&Zw8$fxOdfp<2ZAzuWZNe7R3nF+G-1{?9rZytK;71h$Xqv zUDSHPe(3_o*65DXvEJTl%c0!GzFW3#d?jmhR2w2TYD&wl(Rb5h9FKgzw;Vwi?K0oq zN+`{1d8Qwd?k*i<@OsOkyX)X;3o!$$)B6n6%@$penjTbeGb6J}*Y4$(dm^&EsHe@m z%!2pdccGSB=#IY>htSrFJy-3uhEasnwg_krm*i==poF zf{atu2R0}eAhxT{d=3|hy?Tfp~tRCC#`3%YP|ldM`k1v$?v!dck;fH9Jx>8Z(JrTJK^+iN33 zkBP4We_Pt6ZjwgZYWyzriRXn+x}`U(1H-b5&n!B0rBW?0?~zq2n51@g@owUI*C!Ws z#p#u5utsum*cc5~&fMzEeoaFqvqa=Azt*L@K(UAC9c-KiU7+3e3Tn>GsVEb+&JEm) zK6j&i$Sq&FV5lj*o9+IDNREgQ!$}591}=&~q9???W!%RbImq~PRWaI6qT1Z@W3*@f zElL54!{;U?XOaRR7^xORi+*_J8!S8gOEiJ!qF#Hby1)(2Rrfzm2ukYgdrJ22|WBX@3jM;s132I%_{_@}7=Nl2K<A%UVg;0(3kp7*GO)c@q;~wOz7LR08 zT^D#aiM$cAibY+JP13zw#=vnn?pRU4FB|R}orX5kPSchJ*Pfz#Z*ywTZ!E2-i*b{1 zkG%S_VAuJD^LAZ=JQsg_8XV2kp}C@oGxn76eu3wb_{3eN$0Sqo=a!(x_fDkstSy<< z$3Ck|>vdi-I>E8APjh%Si7F}OqUw_20iFxur77_MWhtV-losa4Zz@B*wvk1ZA2NRm zW#z@d+FXUY`<_94+U!03qc5=W+V!oasTIiP8JX);JujWk-no8$k?oGM;w_i#>oPZt zlQ^CTPWSE#jfII%_qj1pO*cto-j(9&l^kq}3*EgS8%8xf>UPmMEE^?c9IE)BG{E=e zzDekzf?!YNCfn$B@t$a>7nD6gB3G&sH-T7ga7@CtfV>Wu(v? z)E0V&c&J&2Q?0Dt6X0}yR9Uy@`Xyy(4|TL{#0?uuDF217kj-;4%C0?OP8=^Y1Dx1_ zU)naWp!4j0da5Q=eY(L-d@NLV+FCjkI{hrcb~c6a7#id|*|sYp8|pgU;U=2g+~6im znL7x-h`P|*BoMj&S1iV}iF8EWwKmK(wf=T%Jgnp4v?|+!Iq2RKpVYO5;p3xv-OVSm zUC_;)vyD`Z_($OhCJX2H5H%Tg3%q+*SQj9B!=zKL)%f8gKYxdD@2PAz@t*&Yi~laY zXWeGQ!DYE_s!e8ZMU(FHd-5h-<2R|*7bxTA$V{5EQD*NM?V9sYA}q}zsNpx0Ho^FX znSp=hVRvO<{mvrp&bRtll(iTAT5}@mfppj-l=*=RtbF~Uml2mcROIgf_(+M37)Yfq z-}gyNSs>mEuSqLfp!H4_T(CR;7*avJS>7SINqZ`BI6b9+=SB z8{Jx=<{8bc%Mi(3wpeuG&Bxp?!=bwIdMCAqZ0GWB@Tu?|iY?tXFwxg;wl%gk5faYH zZBLXgx*)uup(kROz~7o!nQ3apm$@5TnRTZX!yS!ZnRRPCfj)Nouuk}pK3u~c ze#^wFBN_;0R&{F(?_zok5XwQl8SQVj&3Q0BGM*K&joV^$9ML|BTRe;*Pcd$XVcibH zx*evZ$YG3Z1Kg$u-A=~3-4D2Z4c_bfotA~%foF?z`ZfzWD3Yc2Lhj~pzOFkmCnt1x z8GYuq4@(z)HwDd{{g9qkjOx)h<`xKes^Ov0ch8eZo158kWiZ^2A>-`Fy|>JS&MKz{ z-AXM|6>`}VJNp?#xScIgK{Kj1*$kqH(hp(h6%u={Y)cPwcPU!4OLe+1IB~5c-gYky zFyo10vD_N`?8oyeAivs>M$bY=iF%umj?g9i)U2MV@WjM`#%Dr0;+x^jvj(Q56H^iz ztAsHG@NnAMjqn09sSiJe!q}u z`3mU3iE_!CQJr{(xUAujS$$KRiOF(7N`2FYI_hw$*2+4ux>i&w46=*|J6V;w3|S^y zX5wu{0nP*%DoXec)Z|K4etMH(2wBE8Vj^y>u1l`#c$n@*HvrkSH{$BV^TelW@qXBf zCqjA-Z$bzR9wivO2@*{3TwxT$Bb@c~ zk5&?|rg=&TINd{JAb{YNTOy{7jOtMe`cMfXJxP`*TZEQh*wo1=Z-f@&rG=6todku1 zgjkd#q8AZqajk+*0>4~>GRhNi5s^53UMvn{69?BmUM!we%TotF`_uOJFs^yLSp4%X;ST)vg!T`axOVV#@x)u6 zeAl1gnP_;JCJiy7kY?Ixx<*$nv`*4OY;|XX!F1M5qm&SiEB4e-V;k^hX@sX9)v&EL z+(i*iF={m7GBGotSxC5wBM^>1YdmptVopL+7BWKUB_R-X4^f5o)y)#Yh<^=JC_7-G ztkalg?2@$B)LjF8-K7VOW5vYIqop6&WXtCD#=AFiL9FG;s{Vvl-J|Kt?kqy<))SNT z$G4wKTNuUdYmuYNW$84=MA!VYbyra&tw-U`m~xqBUIK+m^*_Xz=$cPk*Yq%TWKHip zCWP-TUSbQ7LTY5Yga_(-i#cCwayK<^P4Avx^t8etogP6Pr3ej>5+%?~J#sK5O<+p& z@W7OCfGI(q1XB`&PKkLWAsx90AT1xlho8?x)mmCdVe{oR+cMNw>$Ve+U~xJ2_r2ZD~+@6>KjrZf?0K+-=s4^U_?wzjI9-Q6p163>YY*I zCGuqwlun)qeyp@pplzj?a(PB5Mox~A2E$4d0Hi?xX@#J)WvsN-Ish6*e?y}j%>(O3 z2Wr*b%s}x)5xV57Vx%o&rLosteTdF(8YqnkD{T^##)Jjha}a0}WFXM4VSx4tkC-S1 z12nkatP6E%NUb$lB~y0l5+n%&+&6XBbsyfOB|(xXlbEDhOX^Nzk_t&89br1(dJpl| zkE$i;JD}k!F`d`b3@3!+Q-)K_{sR)hws6`> zN0j)=JZ@ROJz@mj;?rV2|EGA zEDqJf5;F%#%z9X2R>cxC0NrvyF@4hy^0XLYz5o()KHzj7K+O5r{5}Bln~%xw7QoXX z!{uhC`&kJf6`1maOqGveDgj77{Q`zX^@u?hRr3oorv)IZ210fK3)v0~$ViS@OF^PC zRRxI(h9RnXz!}Oi?}lAt+wm_*fxzj2LIETN(m|SQ7_SOv10ewLXcfq#NJfyVsz4q^ z5`#SI3FgF95VUR?V;whSnLZ9<-2leA6+jI`2|LL?m0XtwNCFaA`x>w;k4^De5VrPM zN(sln_5~p&IUfdSOjw|C13)7KfR+maEeQj(A3)3^4X@D`eXF%5sst!+`2P58BU+G0zAvuQNqug+r;7=W)ILxaMP8p|Lmk zUn+LX)2Hy?U-E4;yvI%wGNK>~?5Vqv_ml3QLlpDdLy(#y!1Q3x3s!#_I6c@)fzyL4 z7MtfmY_4LlISOD?4%1=6(b)8aQRIzK)=SX4t3{-?p=g}E5fNbG*0IBlES5OVgH^hF z4wNU0?O5snIuFAYXIP}fZal_FTn4+r>YE6lqn_p3m)X|D;2luKIKoh0KHzcPn`v}r zpu50x8Ei2-17M38u}HyK=@{Y7;3mL;-_>X|18^9LqzxA09 z><}2e5CEp)-@wG!1b|7VG}sw_%FM{BHVeK$)DjFAKw`7(iJcL#S>DEGc?_Lp2`dCM z{{J+EVHlVaOPKbUjt?ZraD=Fys`RVKiP1TUZW#y@)?4%l=3|fUHUA4dRn#ql{F{Vr zT=Ce(1x|>7FU)Y1wrF9oNpGVQKNG8yGr|$1%5s7ME&+hg%drD&8#ut0V|kJntiWbM0X}cBvpi3MZWb2si{wz}Q(a1WUjKAOWjl378us zU_LYf2dL5M38kXpQ4Nfgtt)JRrmxzBcfxOXZT)9}5cXq8?rog`X7HrbV|0^PC9dK_ zn#)5m&Fd1_ykJ1{N(6!k!=U#ekRxELpw}HN%9RAS3K+I#Vz65UcGxjQv&;l~4xDYkdm;oBoR**yFz&4KA;p0afa<2csT|c! zOwIhCC$Ync7oISZSYW3>mjVNJr^p5vkQ+!vHg>0A0DECJcBdc$Q*jSFpYVaHNW!GT zkWNDQUuQ7@rRbfaywyjo4ZBk~fICGYcBfDQsmcfo-aIsT*Pjy#kh_5ejcwFrfN}hQ zab;NJu#LJ5W85fEYExp=KFI2b2v2}3&;Ml@TYV$CY(KnKN}xL^ zXl>pQ1xUP8-QteP?h4C12~tzqzj%C_2}921Es~gq?H=KXVT2`?d9aveK3~VUyd#l~ z8D~ePlK>E-2mo|2k>`Nu_>4gZ;Fg|6=@sg2S1$#nZs+h*qyKq{e_MA8ThKs5S|v{8 zLz@0?rZJ%Zh*dZTK8!w0c#vwyL|j>2mjD*D9(GN(K^L?sdQJI%7{~tV9>3_|>t^jL zP|)Zt-iaNc7-xhn$fyH^16(cuqYj(`KN1)P8Fhde{766s`;h=G_>q7ocJj1CGip+C zT{x~5dJ6>@`!;-jlq{y3R}ZC;c5lDMKQ)UTAq{dqW_@nUY(smwBi*1o)00Z%vAEHJDS!<4$5vOpwNfdye9ZkeHa6u)n|b z$x}SE+)w>4(-P|QJ;Z%ZqRgV8(nRr!OfyiAp!-a!-bk0UeA5|*XFbaHq?rt_cpjS3 z^kzo*JQ|C?INx5qGqO>8ao%I^J92I-o3Ve$R_yNBoX0*N z!??dkR|P9nPMvkNYiVn}B_i4z&Q=)^bzqR)>)o{&qnGLO{DpYcY`%s_dHlqx=R9La zvpVagZ`!u{?KHw2mmS?MRZ<7_* zCgE*!YRn!?T`rfHi8EW;^N5~1cO!y%`qeYROuzSPrE_yNPpq$5$lFJiqr3pCCPx1Bg1!Cm5%PqNf;JVZ_(Ggs(4Y@A#hxbA_0=MHQTj z4N~XYI=pi)bv;aX zGJmRzfhXM0J>!34?7{KL3#g7CIz4MCvNTdtCUwaQXM+i0BU3F2gUdRv1m}7=`8p2T zmEPSNawsHnwU~GtR#>&!qiR?e5x2W`9vMtUw3RJqFVN&4dAYVHG}7}cQq$R5_rO2$ zq%i))OmUKgGj^Ayif05U^gk!7*Cn@>XhvrX3~_PpH0e5t75J#;iW-N)y8@Mx0`mP| zr{6S+3+EEyt>Jq|chNO+vBKu__hPN2ZvXn|LSg*-=i5bsqb%E3UxxGzvZQSKJaZdK z&b29mPap$A9={EIq4q>|&VtFXYOgwCQta|be0r6dfVGBl;YVa`e~WY6_g>34Vw*_$ zX2q^2y7`ZsM+zp^`O5QtFx1lolt#zb?ujG^f4f1oD5K;xMsZmScCpR9kG#DrxqD{% zFzIsVbLlaYGcTxz&QWdGW;G!S49j%FLqp3|x#c1fZiw5Blp`9S>%^PVoQhB%iOP8x zFn3v3`;PNF-;t8|jLtra`t6ZH(u{{hxq~Nn_cX@HdUeTUsgu{+M*jXsY2atWt+z&Tsyyl`EZu9pt)pr@} zc0|Iry~3>Gy9>@_72!Ku1o+oxHr$UizvuPZUcqnR-%K;{_T5$Sdj(N$ORxRNZeSfQ z;cl_wf7?WI`jpp!4V{v548dAF4UfH=w8c4@2gyw`CsNpBYwt}T!IYUVS6LS+tprLJ zG0zgaoJo)VoQ_~uWp~eNnW@Q)DU%)jnngCQjI1Hu@VEK?ZX-FIj2RVBQ1Ut`>*i}* zGvdx@+DjSnto9Av?dpifE(t`Zu6$x(`<$TG1R0ZYW2BNfV)mA$-?^eBsxk0kQnS%H zFTt!S3wjovY@OVsp2?(&By)7BIDEtDI;x* z6Sy(DHy7O`c^`#cm3_lh_L@HQ?gR^ibh7!}88Z1X=FB1KwyTY;Oq!UN14C%&b% zJ4!^yadPA+=CwG91yS3``DzaVbdi{Z%4P^7EZbMUa*9V@)% zSor+ZVH$682t__q`4suggfsJ-3xq;-2m9}OiMEJ7ei*LKS1a!{)-)`6@r7qOb!vs! z+L_2%bjC*6Ig9b$p8wkTBPf)MpC-slhF#|?{z0Wr11wV^eBs5dLGfmJ-^YtBMDJzj zCgjN%1onNIPY{oE#I8A&)nu|8eh{X9_6~LreiOc`5E<$21q+qCMbET&R*mLhIuwQ2 zI|`^`4NzWE9^MPN)qtNye5BpYxVrM-tybXMDUTGbcXyvA5(*bKpGb~h9lZW|$!xTf zC$XMqs;YOWRfe13ES!=*e{#KEPiR6S`Kv+GtyiNZUt?lT_w{4$MreP}@FbceTCFZj znBjg*X_uZ*|8%0cM_gm=yVT)itipzow~w0R%ZLO1CiOM;*M&9|WJ|;r(CCRnN#pIj zty0CAqs=d=+zR%=c>3~>-C%LaF7 zmF{9mbZjFVqwK7h`8%a|`#)&Tzw3FBGZGU2W~ulGd(K+0cyHKQZqt=^2Mg8xai;co zI$=>1VcaWL(J=Ty5+2OGd(DMk?h8K8&9h~Cv^-~&yC_fBAt;-GDPmOjUHTr4B)q!W~J(cIH{isnj8bw=~_K1_fS=K*es-eB9LGB*o9JODWae ztP)x$ph#wi@C3O#d^CDKqeUuCw?Pp!6wLED(v+lqZQ8U9s>dU1$?_nhM^Tkj$Z6DX z^J$Im&_zMdK>e!tg}&WK@-Cm#mWS{4ku%=Sa9+|6SW0qw(K0E{;*=30I5%l4oGrc> z=EwA{BL4mslL?Fpk}MS^(s(UScmMIhrm?+cHSMLGThFDHR2KeSK>kyirjfqt6#cbB_U68a>7UP-zy=K;yfr(3eiWbPzM)x6 z(=<3bgvSBJ4K+?JH{~R?g;wMbI-9ew=?vUbP(Cz&zHIXA!j}v%G_?-Nb94bykSlOU zj}|x$746_oR&Xa1ZFhSs$2$UUwy>aQ!zztJ)WK^z+?V06)NWHhFZG<9B<&}r@3CgQ z!O0#kurw?+cq))^%VAE=Ykg;5YyI2figM+E8e6G?XRstD{s14j_o5LVa;tj{_v+Id zRjs;s9X&2&4V=P{65~9lITweIOmY_{T_)zczgoHaVL&;wk>V?*%&PXW|3z4G-_rF! zh-8MKfs9FhwAg*+Pf`%RO35ClChMBh1?M`Giz~I^jj0`iq15L$kLBytQHLk}N>B6I z>CfGtDJ1kgbAliEu=^YJ_oDc*q(@A(I6ngbIQ!SsNCX7H#K8*o`z1#7Gd48x$%DZE zB>_P~-*yC_5kNorN}~fEoEjiD0y6Q}%h=AS?VRx^7QDr3dZR~V;NV$ix}BYql2NS8 zij}EPP3`IJH8_XeB`e1F_obQ*)2qo_JBZvNZ?tCjtjHwWgFa2vAQ#F`TMgb)(=4fCanqfbgV`JJX+pL2s9TFGpb;)s z-H9gnRRM^$7XkZ%4(lRy-H|PGv>K|ocyjpv)BWIcKorm~YQH)K^aa6 zYCxMUfQQlW^V;ek!tZw3V9eK|3c#3;eg8{13C=$+xBe8)=JyVv`={_yp;L78X|%}e6aZAism1xE~Fo0RJc6iS4FGDzW=2P2j`zV z)K69DaMiQ@wo&~q+7C{$gz*A87>H4Ueg8`|7_2|{uAidO!CL%X^dDQ;?|N{s(fXNh5kG>R0+|HhC>GYX#no@v+$wc{TF2O B3Df`p literal 0 HcmV?d00001 diff --git a/tests/src/Mod/Mesh/App/CMakeLists.txt b/tests/src/Mod/Mesh/App/CMakeLists.txt index a0ede073d621..038682f4bbcb 100644 --- a/tests/src/Mod/Mesh/App/CMakeLists.txt +++ b/tests/src/Mod/Mesh/App/CMakeLists.txt @@ -1,8 +1,11 @@ +target_compile_definitions(Mesh_tests_run PRIVATE DATADIR="${CMAKE_SOURCE_DIR}/data") + target_sources( Mesh_tests_run PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Core/KDTree.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Exporter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Importer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Mesh.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MeshFeature.cpp ) diff --git a/tests/src/Mod/Mesh/App/Importer.cpp b/tests/src/Mod/Mesh/App/Importer.cpp new file mode 100644 index 000000000000..fe6db6055948 --- /dev/null +++ b/tests/src/Mod/Mesh/App/Importer.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +// NOLINTBEGIN(cppcoreguidelines-*,readability-*) +TEST(ImporterTest, Test3MF) +{ + std::string file(DATADIR); + file.append("/tests/mesh.3mf"); + + MeshCore::Reader3MF reader(file); + EXPECT_EQ(reader.Load(), true); + + std::vector ids = reader.GetMeshIds(); + std::sort(ids.begin(), ids.end()); + + EXPECT_EQ(ids.size(), 2); + + const MeshCore::MeshKernel& mesh1 = reader.GetMesh(ids[0]); + EXPECT_EQ(mesh1.CountPoints(), 8); + EXPECT_EQ(mesh1.CountEdges(), 18); + EXPECT_EQ(mesh1.CountFacets(), 12); + + const MeshCore::MeshKernel& mesh2 = reader.GetMesh(ids[1]); + EXPECT_EQ(mesh2.CountPoints(), 652); + EXPECT_EQ(mesh2.CountEdges(), 1950); + EXPECT_EQ(mesh2.CountFacets(), 1300); +} +// NOLINTEND(cppcoreguidelines-*,readability-*) From 238390127be12933a8b3abf4888a152d364b99b6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 27 Nov 2024 19:52:00 +0100 Subject: [PATCH 126/161] Gui: Allow to override onBeforeChange in view objects --- src/Gui/ViewProviderFeaturePython.cpp | 32 +++++++++++++++++++++++++++ src/Gui/ViewProviderFeaturePython.h | 7 ++++++ 2 files changed, 39 insertions(+) diff --git a/src/Gui/ViewProviderFeaturePython.cpp b/src/Gui/ViewProviderFeaturePython.cpp index 6e8499791341..8996bfe23c85 100644 --- a/src/Gui/ViewProviderFeaturePython.cpp +++ b/src/Gui/ViewProviderFeaturePython.cpp @@ -638,6 +638,38 @@ void ViewProviderFeaturePythonImp::onChanged(const App::Property* prop) } } +void ViewProviderFeaturePythonImp::onBeforeChange(const App::Property* prop) +{ + if(py_onBeforeChange.isNone()) + return; + + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + if (has__object__) { + Py::Tuple args(1); + const char* prop_name = object->getPropertyName(prop); + if (prop_name) { + args.setItem(0, Py::String(prop_name)); + Base::pyCall(py_onBeforeChange.ptr(),args.ptr()); + } + } + else { + Py::Tuple args(2); + args.setItem(0, Py::Object(object->getPyObject(), true)); + const char* prop_name = object->getPropertyName(prop); + if (prop_name) { + args.setItem(1, Py::String(prop_name)); + Base::pyCall(py_onBeforeChange.ptr(),args.ptr()); + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + void ViewProviderFeaturePythonImp::startRestoring() { } diff --git a/src/Gui/ViewProviderFeaturePython.h b/src/Gui/ViewProviderFeaturePython.h index 413302205058..023247019ed8 100644 --- a/src/Gui/ViewProviderFeaturePython.h +++ b/src/Gui/ViewProviderFeaturePython.h @@ -72,6 +72,7 @@ class GuiExport ViewProviderFeaturePythonImp void attach(App::DocumentObject *pcObject); void updateData(const App::Property*); void onChanged(const App::Property* prop); + void onBeforeChange(const App::Property* prop); void startRestoring(); void finishRestoring(); ValueT onDelete(const std::vector & sub); @@ -149,6 +150,7 @@ class GuiExport ViewProviderFeaturePythonImp FC_PY_ELEMENT(attach) \ FC_PY_ELEMENT(updateData) \ FC_PY_ELEMENT(onChanged) \ + FC_PY_ELEMENT(onBeforeChange) \ FC_PY_ELEMENT(startRestoring) \ FC_PY_ELEMENT(finishRestoring) \ FC_PY_ELEMENT(onDelete) \ @@ -518,6 +520,11 @@ class ViewProviderFeaturePythonT : public ViewProviderT imp->onChanged(prop); ViewProviderT::onChanged(prop); } + void onBeforeChange(const App::Property* prop) override + { + imp->onBeforeChange(prop); + ViewProviderT::onBeforeChange(prop); + } /// is called by the document when the provider goes in edit mode bool setEdit(int ModNum) override { From b9cc17b2fddd48c83ef55b667ef34788977790dd Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 28 Nov 2024 11:00:55 +0100 Subject: [PATCH 127/161] Gui: Add a new display mode for image without shading --- src/Gui/ViewProviderImagePlane.cpp | 44 ++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/Gui/ViewProviderImagePlane.cpp b/src/Gui/ViewProviderImagePlane.cpp index 0362a73253b4..2039eefc172b 100644 --- a/src/Gui/ViewProviderImagePlane.cpp +++ b/src/Gui/ViewProviderImagePlane.cpp @@ -31,6 +31,7 @@ # include # include # include +# include # include # include # include @@ -71,6 +72,8 @@ ViewProviderImagePlane::ViewProviderImagePlane() shapeHints->ref(); sPixmap = "image-plane"; + + ShapeAppearance.setDiffuseColor(1.0F, 1.0F, 1.0F); } ViewProviderImagePlane::~ViewProviderImagePlane() @@ -87,22 +90,22 @@ void ViewProviderImagePlane::attach(App::DocumentObject *pcObj) // NOTE: SoFCSelection node has beem removed because it led to // problems using the image as a construction plane with the // draft commands - SoSeparator* planesep = new SoSeparator; - planesep->addChild(pcCoords); + SoSeparator* shading = new SoSeparator; + shading->addChild(pcCoords); SoTextureCoordinate2 *textCoord = new SoTextureCoordinate2; textCoord->point.set1Value(0,0,0); textCoord->point.set1Value(1,1,0); textCoord->point.set1Value(2,1,1); textCoord->point.set1Value(3,0,1); - planesep->addChild(textCoord); + shading->addChild(textCoord); // texture texture->model = SoTexture2::MODULATE; - planesep->addChild(texture); + shading->addChild(texture); - planesep->addChild(shapeHints); - planesep->addChild(pcShapeMaterial); + shading->addChild(shapeHints); + shading->addChild(pcShapeMaterial); // plane pcCoords->point.set1Value(0,0,0,0); @@ -111,22 +114,41 @@ void ViewProviderImagePlane::attach(App::DocumentObject *pcObj) pcCoords->point.set1Value(3,0,1,0); SoFaceSet *faceset = new SoFaceSet; faceset->numVertices.set1Value(0,4); - planesep->addChild(faceset); + shading->addChild(faceset); + + addDisplayMaskMode(shading, "Shading"); + + SoLightModel* lightmodel = new SoLightModel; + lightmodel->model = SoLightModel::BASE_COLOR; - addDisplayMaskMode(planesep, "ImagePlane"); + SoSeparator* noshading = new SoSeparator; + noshading->addChild(pcCoords); + noshading->addChild(textCoord); + noshading->addChild(texture); + noshading->addChild(shapeHints); + noshading->addChild(pcShapeMaterial); + noshading->addChild(lightmodel); + noshading->addChild(faceset); + + addDisplayMaskMode(noshading, "No shading"); } void ViewProviderImagePlane::setDisplayMode(const char* ModeName) { - if (strcmp("ImagePlane",ModeName) == 0) - setDisplayMaskMode("ImagePlane"); + if (strcmp("Shading", ModeName) == 0) { + setDisplayMaskMode("Shading"); + } + else if (strcmp("No shading", ModeName) == 0) { + setDisplayMaskMode("No shading"); + } ViewProviderGeometryObject::setDisplayMode(ModeName); } std::vector ViewProviderImagePlane::getDisplayModes() const { std::vector StrList; - StrList.emplace_back("ImagePlane"); + StrList.emplace_back("Shading"); + StrList.emplace_back("No shading"); return StrList; } From a372678e987a6522e3de4afc7e981ee67cc5cd34 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 28 Nov 2024 15:41:11 +0100 Subject: [PATCH 128/161] Gui: Support of converting 64-bit images --- src/Gui/BitmapFactory.cpp | 92 ++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/src/Gui/BitmapFactory.cpp b/src/Gui/BitmapFactory.cpp index cd15e586303b..73056f6825c0 100644 --- a/src/Gui/BitmapFactory.cpp +++ b/src/Gui/BitmapFactory.cpp @@ -539,58 +539,82 @@ void BitmapFactoryInst::convert(const QImage& p, SoSFImage& img) const QVector table = p.colorTable(); if (!table.isEmpty()) { if (p.hasAlphaChannel()) { - if (p.allGray()) + if (p.allGray()) { numcomponents = 2; - else + } + else { numcomponents = 4; + } } else { - if (p.allGray()) + if (p.allGray()) { numcomponents = 1; - else + } + else { numcomponents = 3; + } } } else { numcomponents = buffersize / (size[0] * size[1]); } + int depth = numcomponents; + + // Coin3D only supports up to 32-bit images + if (numcomponents == 8) { + numcomponents = 4; + } + // allocate image data img.setValue(size, numcomponents, nullptr); - unsigned char * bytes = img.startEditing(size, numcomponents); + unsigned char* bytes = img.startEditing(size, numcomponents); - int width = (int)size[0]; + int width = (int)size[0]; int height = (int)size[1]; - for (int y = 0; y < height; y++) - { - unsigned char * line = &bytes[width*numcomponents*(height-(y+1))]; - for (int x = 0; x < width; x++) - { - QRgb rgb = p.pixel(x,y); - switch (numcomponents) - { - default: - break; - case 1: - line[0] = qGray( rgb ); - break; - case 2: - line[0] = qGray( rgb ); - line[1] = qAlpha( rgb ); - break; - case 3: - line[0] = qRed( rgb ); - line[1] = qGreen( rgb ); - line[2] = qBlue( rgb ); - break; - case 4: - line[0] = qRed( rgb ); - line[1] = qGreen( rgb ); - line[2] = qBlue( rgb ); - line[3] = qAlpha( rgb ); - break; + for (int y = 0; y < height; y++) { + unsigned char* line = &bytes[width * numcomponents * (height - (y + 1))]; + for (int x = 0; x < width; x++) { + QColor col = p.pixelColor(x,y); + switch (depth) { + default: + break; + case 1: + { + QRgb rgb = col.rgb(); + line[0] = qGray(rgb); + } break; + case 2: + { + QRgb rgb = col.rgb(); + line[0] = qGray(rgb); + line[1] = qAlpha(rgb); + } break; + case 3: + { + QRgb rgb = col.rgb(); + line[0] = qRed(rgb); + line[1] = qGreen(rgb); + line[2] = qBlue(rgb); + } break; + case 4: + { + QRgb rgb = col.rgb(); + line[0] = qRed(rgb); + line[1] = qGreen(rgb); + line[2] = qBlue(rgb); + line[3] = qAlpha(rgb); + } break; + case 8: + { + QRgba64 rgb = col.rgba64(); + line[0] = qRed(rgb); + line[1] = qGreen(rgb); + line[2] = qBlue(rgb); + line[3] = qAlpha(rgb); + } break; } line += numcomponents; From 53d39c6c9169b7f8f927ccd05af0a18393ddf8d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 28 Nov 2024 23:03:39 +0100 Subject: [PATCH 129/161] App: Apply clang format (part 3) --- src/App/Application.h | 7 +++-- src/App/DynamicProperty.h | 1 + src/App/Expression.h | 4 +++ src/App/Extension.cpp | 23 ++++----------- src/App/Extension.h | 4 +++ src/App/PropertyContainer.h | 56 ++++++++++++++++++++----------------- 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/App/Application.h b/src/App/Application.h index 95ec7c2c16ad..e2a32adefe2d 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -78,7 +78,6 @@ class AppExport Application { public: - //--------------------------------------------------------------------- // exported functions go here +++++++++++++++++++++++++++++++++++++++++ //--------------------------------------------------------------------- @@ -205,6 +204,8 @@ class AppExport Application void closeActiveTransaction(bool abort=false, int id=0); //@} + // NOLINTBEGIN + // clang-format off /** @name Signals of the Application */ //@{ /// signal on new Document @@ -311,7 +312,9 @@ class AppExport Application boost::signals2::signal signalBeforeAddingDynamicExtension; /// signal after the extension was added boost::signals2::signal signalAddedDynamicExtension; - //@} + //@} + // clang-format off + // NOLINTEND /** @name methods for parameter handling */ diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index 6a2caf1d1198..29936fa66563 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace Base diff --git a/src/App/Expression.h b/src/App/Expression.h index 78f1edb1c58c..7ff8352d0c12 100644 --- a/src/App/Expression.h +++ b/src/App/Expression.h @@ -50,8 +50,10 @@ using ExpressionPtr = std::unique_ptr; AppExport bool isAnyEqual(const App::any &v1, const App::any &v2); AppExport Base::Quantity anyToQuantity(const App::any &value, const char *errmsg = nullptr); +// clang-format off // Map of depending objects to a map of depending property name to the full referencing object identifier using ExpressionDeps = std::map > >; +// clang-format on class AppExport ExpressionVisitor { public: @@ -212,12 +214,14 @@ class AppExport Expression : public Base::BaseClass { virtual void _visit(ExpressionVisitor &) {} protected: + // clang-format off App::DocumentObject * owner; /**< The document object used to access unqualified variables (i.e local scope) */ ComponentList components; public: std::string comment; + // clang-format on }; } diff --git a/src/App/Extension.cpp b/src/App/Extension.cpp index 51ba5fff7cb1..c84e613de49d 100644 --- a/src/App/Extension.cpp +++ b/src/App/Extension.cpp @@ -39,18 +39,21 @@ * PropertyData in the extension chain, there is no parent property data. */ EXTENSION_TYPESYSTEM_SOURCE_P(App::Extension) + const App::PropertyData* App::Extension::extensionGetPropertyDataPtr() { return &propertyData; } + const App::PropertyData& App::Extension::extensionGetPropertyData() const { return propertyData; } + App::PropertyData App::Extension::propertyData; + void App::Extension::init() { - assert(Extension::classTypeId == Base::Type::badType() && "don't init() twice!"); /* Set up entry in the type system. */ @@ -76,7 +79,6 @@ Extension::~Extension() void Extension::initExtensionType(Base::Type type) { - m_extensionType = type; if (m_extensionType.isBad()) { throw Base::RuntimeError("Extension: Extension type not set"); @@ -104,7 +106,6 @@ void Extension::initExtension(ExtensionContainer* obj) PyObject* Extension::getExtensionPyObject() { - if (ExtensionPythonObject.is(Py::_None())) { // ref counter is set to 1 auto grp = new ExtensionPy(this); @@ -115,7 +116,6 @@ PyObject* Extension::getExtensionPyObject() std::string Extension::name() const { - if (m_extensionType.isBad()) { throw Base::RuntimeError("Extension::name: Extension type not set"); } @@ -131,50 +131,42 @@ std::string Extension::name() const Property* Extension::extensionGetPropertyByName(const char* name) const { - return extensionGetPropertyData().getPropertyByName(this, name); } short int Extension::extensionGetPropertyType(const Property* prop) const { - return extensionGetPropertyData().getType(this, prop); } short int Extension::extensionGetPropertyType(const char* name) const { - return extensionGetPropertyData().getType(this, name); } const char* Extension::extensionGetPropertyName(const Property* prop) const { - return extensionGetPropertyData().getName(this, prop); } const char* Extension::extensionGetPropertyGroup(const Property* prop) const { - return extensionGetPropertyData().getGroup(this, prop); } const char* Extension::extensionGetPropertyGroup(const char* name) const { - return extensionGetPropertyData().getGroup(this, name); } const char* Extension::extensionGetPropertyDocumentation(const Property* prop) const { - return extensionGetPropertyData().getDocumentation(this, prop); } const char* Extension::extensionGetPropertyDocumentation(const char* name) const { - return extensionGetPropertyData().getDocumentation(this, name); } @@ -186,7 +178,6 @@ void Extension::extensionGetPropertyList(std::vector& List) const void Extension::extensionGetPropertyMap(std::map& Map) const { - extensionGetPropertyData().getPropertyMap(this, Map); } @@ -195,7 +186,6 @@ void Extension::initExtensionSubclass(Base::Type& toInit, const char* ParentName, Base::Type::instantiationMethod method) { - // don't init twice! assert(toInit == Base::Type::badType()); // get the parent class @@ -207,7 +197,6 @@ void Extension::initExtensionSubclass(Base::Type& toInit, toInit = Base::Type::createType(parentType, ClassName, method); } - bool Extension::extensionHandleChangedPropertyName(Base::XMLReader& reader, const char* TypeName, const char* PropName) @@ -217,7 +206,7 @@ bool Extension::extensionHandleChangedPropertyName(Base::XMLReader& reader, (void)PropName; return false; -}; +} bool Extension::extensionHandleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, @@ -228,7 +217,7 @@ bool Extension::extensionHandleChangedPropertyType(Base::XMLReader& reader, (void)prop; return false; -}; +} namespace App { diff --git a/src/App/Extension.h b/src/App/Extension.h index 10e54e435523..7c1545435e3b 100644 --- a/src/App/Extension.h +++ b/src/App/Extension.h @@ -31,6 +31,7 @@ namespace App { class ExtensionContainer; +// clang-format off /// define Extension types #define EXTENSION_TYPESYSTEM_HEADER() \ public: \ @@ -119,6 +120,7 @@ template<> void _class_::init(void){\ initExtensionSubclass(_class_::classTypeId, #_class_ , #_parentclass_, &(_class_::create) ); \ _class_::propertyData.parentPropertyData = _parentclass_::extensionGetPropertyDataPtr();\ } +// clang-format on /** * @brief Base class for all extension that can be added to a DocumentObject @@ -302,6 +304,7 @@ class AppExport Extension App::ExtensionContainer* m_base = nullptr; }; +// clang-format off // Property define #define _EXTENSION_ADD_PROPERTY(_name, _prop_, _defaultval_) \ do { \ @@ -321,6 +324,7 @@ class AppExport Extension #define EXTENSION_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_,_type_,_Docu_) \ _EXTENSION_ADD_PROPERTY_TYPE(#_prop_, _prop_, _defaultval_, _group_,_type_,_Docu_) +// clang-format on } //App diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index 9f50ce9aa8a5..b8b5ac91ae1d 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -45,13 +45,13 @@ class Extension; // clang-format off enum PropertyType { - Prop_None = 0, /*!< No special property type */ - Prop_ReadOnly = 1, /*!< Property is read-only in the editor */ - Prop_Transient = 2, /*!< Property content won't be saved to file, but still saves name, type and status */ - Prop_Hidden = 4, /*!< Property won't appear in the editor */ - Prop_Output = 8, /*!< Modified property doesn't touch its parent container */ - Prop_NoRecompute = 16,/*!< Modified property doesn't touch its container for recompute */ - Prop_NoPersist = 32,/*!< Property won't be saved to file at all */ + Prop_None = 0, /*!< No special property type */ + Prop_ReadOnly = 1, /*!< Property is read-only in the editor */ + Prop_Transient = 2, /*!< Property content won't be saved to file, but still saves name, type and status */ + Prop_Hidden = 4, /*!< Property won't appear in the editor */ + Prop_Output = 8, /*!< Modified property doesn't touch its parent container */ + Prop_NoRecompute = 16,/*!< Modified property doesn't touch its container for recompute */ + Prop_NoPersist = 32,/*!< Property won't be saved to file at all */ }; // clang-format on @@ -91,25 +91,27 @@ struct AppExport PropertyData const void* m_container; }; - // A multi index container for holding the property spec, with the following - // index, - // * a sequence, to preserve creation order - // * hash index on property name - // * hash index on property pointer offset - mutable bmi::multi_index_container< - PropertySpec, - bmi::indexed_by< - bmi::sequenced<>, - bmi::hashed_unique< - bmi::member, - CStringHasher, - CStringHasher - >, - bmi::hashed_unique< - bmi::member - > - > - > propertyData; + // clang-format off + // A multi index container for holding the property spec, with the following + // index, + // * a sequence, to preserve creation order + // * hash index on property name + // * hash index on property pointer offset + mutable bmi::multi_index_container< + PropertySpec, + bmi::indexed_by< + bmi::sequenced<>, + bmi::hashed_unique< + bmi::member, + CStringHasher, + CStringHasher + >, + bmi::hashed_unique< + bmi::member + > + > + > propertyData; + // clang-format on mutable bool parentMerged = false; @@ -269,6 +271,7 @@ class AppExport PropertyContainer: public Base::Persistence static PropertyData propertyData; }; +// clang-format off /// Property define #define _ADD_PROPERTY(_name,_prop_, _defaultval_) \ do { \ @@ -345,6 +348,7 @@ template<> void _class_::init(void){\ initSubclass(_class_::classTypeId, #_class_ , #_parentclass_, &(_class_::create) ); \ _class_::propertyData.parentPropertyData = _parentclass_::getPropertyDataPtr(); \ } +// clang-format on } // namespace App From a4357203637643cd0c4e6a7ebb1e97d2813464e4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 29 Nov 2024 07:37:02 +0100 Subject: [PATCH 130/161] pre-commit: Exclude 3rd party code from auto-formatting --- .pre-commit-config.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e5c733241a78..b5500f1ecd06 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,6 +42,9 @@ exclude: | src/App/ExpressionParser.tab.h| src/App/ExpressionParser.y| src/App/lex.ExpressionParser.c| + src/Gui/3Dconnexion/navlib| + src/Gui/QSint| + src/Gui/Quarter| src/Mod/Import/App/SCL| src/Mod/Import/App/SCL_output| src/Mod/Mesh/App/TestData| From d973e3428f16e7fa44c9a1ffa6d145132a4e66c6 Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Fri, 22 Nov 2024 12:20:57 +0800 Subject: [PATCH 131/161] [ArchWall] Variant PropertrySet Support in ArchSketch Now, user can create : - Variant Layout / combination of ArchWall, CurtainWall, Slab based on same ArchSketch, with another PropertySet - Variant Properties / layer of ArchWall on same ArchSketch with different Width, Offset, Material, Height etc. to create Layers, Composite walls etc. (Layout, Layer, Combination, Composite, Elemented etc.) FreeCAD Forum Discussion: - https://forum.freecad.org/viewtopic.php?p=784622#p784622 - https://forum.freecad.org/viewtopic.php?p=785583#p785583 --- src/Mod/BIM/ArchWall.py | 111 ++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index c0d617cc2940..49bc4cb9d2a3 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -212,10 +212,23 @@ def setProperties(self, obj): obj.ArchSketchData = True if not "ArchSketchEdges" in lp: obj.addProperty("App::PropertyStringList","ArchSketchEdges","Wall",QT_TRANSLATE_NOOP("App::Property","Selected edges (or group of edges) of the base Sketch/ArchSketch, to use in creating the shape of this Arch Wall (instead of using all the Base Sketch/ArchSketch's edges by default). Input are index numbers of edges or groups. Disabled and ignored if Base object (ArchSketch) provides selected edges (as Wall Axis) information, with getWallBaseShapeEdgesInfo() method. [ENHANCEMENT by ArchSketch] GUI 'Edit Wall Segment' Tool is provided in external SketchArch Add-on to let users to (de)select the edges interactively. 'Toponaming-Tolerant' if ArchSketch is used in Base (and SketchArch Add-on is installed). Warning : Not 'Toponaming-Tolerant' if just Sketch is used.")) - + if not hasattr(obj,"ArchSketchPropertySet"): + obj.addProperty("App::PropertyEnumeration","ArchSketchPropertySet","Wall",QT_TRANSLATE_NOOP("App::Property","Select User Defined PropertySet to use in creating variant shape, layers of the Arch Wall with same ArchSketch ")) + obj.ArchSketchPropertySet = ['Default'] + if not hasattr(self,"ArchSkPropSetPickedUuid"): # 'obj.Proxy', 'self' not works ? + self.ArchSkPropSetPickedUuid = '' + if not hasattr(self,"ArchSkPropSetListPrev"): + self.ArchSkPropSetListPrev = [] self.connectEdges = [] self.Type = "Wall" + def dumps(self): # Supercede Arch.Component.dumps() + return self.ArchSkPropSetPickedUuid, self.ArchSkPropSetListPrev + + def loads(self,state): + self.ArchSkPropSetPickedUuid = state[0] + self.ArchSkPropSetListPrev = state[1] + def onDocumentRestored(self,obj): """Method run when the document is restored. Re-adds the Arch component, and Arch wall properties.""" @@ -246,7 +259,7 @@ def onDocumentRestored(self,obj): ) if hasattr(obj,"ArchSketchData") and obj.ArchSketchData and Draft.getType(obj.Base) == "ArchSketch": - if hasattr(obj,"Width"): + if hasattr(obj,"Width"): # TODO need test? obj.setEditorMode("Width", ["ReadOnly"]) if hasattr(obj,"Align"): obj.setEditorMode("Align", ["ReadOnly"]) @@ -260,7 +273,8 @@ def onDocumentRestored(self,obj): obj.setEditorMode("OverrideOffset", ["ReadOnly"]) if hasattr(obj,"ArchSketchEdges"): obj.setEditorMode("ArchSketchEdges", ["ReadOnly"]) - + if hasattr(obj,"ArchSketchPropertySet"): + obj.setEditorMode("ArchSketchPropertySet", 0) else: if hasattr(obj,"Width"): obj.setEditorMode("Width", 0) @@ -276,6 +290,8 @@ def onDocumentRestored(self,obj): obj.setEditorMode("OverrideOffset", 0) if hasattr(obj,"ArchSketchEdges"): obj.setEditorMode("ArchSketchEdges", 0) + if hasattr(obj,"ArchSketchPropertySet"): + obj.setEditorMode("ArchSketchPropertySet", ["ReadOnly"]) def execute(self,obj): """Method run when the object is recomputed. @@ -294,6 +310,39 @@ def execute(self,obj): import DraftGeomUtils base = None pl = obj.Placement + + # PropertySet support + propSetPickedUuidPrev = self.ArchSkPropSetPickedUuid + propSetListPrev = self.ArchSkPropSetListPrev + propSetSelectedNamePrev = obj.ArchSketchPropertySet + propSetSelectedNameCur = None + propSetListCur = None + if Draft.getType(obj.Base) == "ArchSketch": + baseProxy = obj.Base.Proxy + if hasattr(baseProxy,"getPropertySet"): + # get full list of PropertySet + propSetListCur = baseProxy.getPropertySet(obj.Base) + # get updated name (if any) of the selected PropertySet + propSetSelectedNameCur = baseProxy.getPropertySet(obj.Base, + propSetUuid=propSetPickedUuidPrev) + if propSetSelectedNameCur: # True if selection is not deleted + if propSetListPrev != propSetListCur: + obj.ArchSketchPropertySet = propSetListCur + obj.ArchSketchPropertySet = propSetSelectedNameCur + self.ArchSkPropSetListPrev = propSetListCur + #elif propSetListPrev == propSetListCur: + #pass #nothing to do in this case + # but if below, though (propSetListPrev == propSetListCur) + elif propSetSelectedNamePrev != propSetSelectedNameCur: + obj.ArchSketchPropertySet = propSetSelectedNameCur + else: # True if selection is deleted + if propSetListCur: + if propSetListPrev != propSetListCur: + obj.ArchSketchPropertySet = propSetListCur + obj.ArchSketchPropertySet = 'Default' + #else: # Seems no need ... + #obj.PropertySet = 'Default' + extdata = self.getExtrusionData(obj) if extdata: bplates = extdata[0] @@ -366,7 +415,6 @@ def execute(self,obj): for edge in baseEdges: while offset < (edge.Length-obj.Joint.Value): - #print i," Edge ",edge," : ",edge.Length," - ",offset if offset: t = edge.tangentAt(offset) p = t.cross(n) @@ -484,6 +532,7 @@ def execute(self,obj): if obj.Length.Value != l: obj.Length = l self.oldLength = None # delete the stored value to prevent triggering base change below + # set the Area property obj.Area = obj.Length.Value * obj.Height.Value @@ -527,7 +576,6 @@ def onChanged(self, obj, prop): if (obj.Base and obj.Length.Value and hasattr(self,"oldLength") and (self.oldLength is not None) and (self.oldLength != obj.Length.Value)): - if hasattr(obj.Base,'Shape'): if len(obj.Base.Shape.Edges) == 1: import DraftGeomUtils @@ -550,7 +598,15 @@ def onChanged(self, obj, prop): else: FreeCAD.Console.PrintError(translate("Arch","Error: Unable to modify the base object of this wall")+"\n") - if hasattr(obj,"ArchSketchData") and obj.ArchSketchData and Draft.getType(obj.Base) == "ArchSketch": + if (prop == "ArchSketchPropertySet" + and Draft.getType(obj.Base) == "ArchSketch"): + baseProxy = obj.Base.Proxy + if hasattr(baseProxy,"getPropertySet"): + uuid = baseProxy.getPropertySet(obj, + propSetName=obj.ArchSketchPropertySet) + self.ArchSkPropSetPickedUuid = uuid + if (hasattr(obj,"ArchSketchData") and obj.ArchSketchData + and Draft.getType(obj.Base) == "ArchSketch"): if hasattr(obj,"Width"): obj.setEditorMode("Width", ["ReadOnly"]) if hasattr(obj,"Align"): @@ -565,7 +621,8 @@ def onChanged(self, obj, prop): obj.setEditorMode("OverrideOffset", ["ReadOnly"]) if hasattr(obj,"ArchSketchEdges"): obj.setEditorMode("ArchSketchEdges", ["ReadOnly"]) - + if hasattr(obj,"ArchSketchPropertySet"): + obj.setEditorMode("ArchSketchPropertySet", 0) else: if hasattr(obj,"Width"): obj.setEditorMode("Width", 0) @@ -581,6 +638,8 @@ def onChanged(self, obj, prop): obj.setEditorMode("OverrideOffset", 0) if hasattr(obj,"ArchSketchEdges"): obj.setEditorMode("ArchSketchEdges", 0) + if hasattr(obj,"ArchSketchPropertySet"): + obj.setEditorMode("ArchSketchPropertySet", ["ReadOnly"]) self.hideSubobjects(obj,prop) ArchComponent.Component.onChanged(self,obj,prop) @@ -603,6 +662,7 @@ def getFootprint(self,obj): return faces def getExtrusionData(self,obj): + """Get data needed to extrude the wall from a base object. take the Base object, and find a base face to extrude @@ -625,6 +685,8 @@ def getExtrusionData(self,obj): import DraftGeomUtils import ArchSketchObject + propSetUuid = self.ArchSkPropSetPickedUuid + # If ArchComponent.Component.getExtrusionData() can successfully get # extrusion data, just use that. data = ArchComponent.Component.getExtrusionData(self,obj) @@ -633,20 +695,18 @@ def getExtrusionData(self,obj): # multifuses not considered here return data length = obj.Length.Value - # TODO currently layers were not supported when len(basewires) > 0 ##( or 1 ? ) width = 0 - # Get width of each edge segment from Base Objects if they store it # (Adding support in SketchFeaturePython, DWire...) widths = [] # [] or None are both False if hasattr(obj,"ArchSketchData") and obj.ArchSketchData and Draft.getType(obj.Base) == "ArchSketch": - if hasattr(obj.Base, 'Proxy'): + if hasattr(obj.Base, 'Proxy'): # TODO Any need to test ? if hasattr(obj.Base.Proxy, 'getWidths'): # Return a list of Width corresponding to indexes of sorted # edges of Sketch. - widths = obj.Base.Proxy.getWidths(obj.Base) - + widths = obj.Base.Proxy.getWidths(obj.Base, + propSetUuid=propSetUuid) # Get width of each edge/wall segment from ArchWall.OverrideWidth if # Base Object does not provide it if not widths: @@ -689,7 +749,8 @@ def getExtrusionData(self,obj): if hasattr(obj.Base.Proxy, 'getAligns'): # Return a list of Align corresponds to indexes of sorted # edges of Sketch. - aligns = obj.Base.Proxy.getAligns(obj.Base) + aligns = obj.Base.Proxy.getAligns(obj.Base, + propSetUuid=propSetUuid) # Get align of each edge/wall segment from ArchWall.OverrideAlign if # Base Object does not provide it if not aligns: @@ -722,12 +783,12 @@ def getExtrusionData(self,obj): # (Adding support in SketchFeaturePython, DWire...) offsets = [] # [] or None are both False if hasattr(obj,"ArchSketchData") and obj.ArchSketchData and Draft.getType(obj.Base) == "ArchSketch": - if hasattr(obj.Base, 'Proxy'): if hasattr(obj.Base.Proxy, 'getOffsets'): # Return a list of Offset corresponding to indexes of sorted # edges of Sketch. - offsets = obj.Base.Proxy.getOffsets(obj.Base) + offsets = obj.Base.Proxy.getOffsets(obj.Base, + propSetUuid=propSetUuid) # Get offset of each edge/wall segment from ArchWall.OverrideOffset if # Base Object does not provide it if not offsets: @@ -826,8 +887,8 @@ def getExtrusionData(self,obj): elif hasattr(obj.Base, 'Proxy') and obj.ArchSketchData and \ hasattr(obj.Base.Proxy, 'getWallBaseShapeEdgesInfo'): - - wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base) + wallBaseShapeEdgesInfo = obj.Base.Proxy.getWallBaseShapeEdgesInfo(obj.Base, + propSetUuid=propSetUuid) #get wall edges (not wires); use original edges if getWallBaseShapeEdgesInfo() provided none if wallBaseShapeEdgesInfo: self.basewires = wallBaseShapeEdgesInfo.get('wallAxis') # 'wallEdges' # widths, aligns, offsets? @@ -843,10 +904,18 @@ def getExtrusionData(self,obj): # Get ArchSketch edges to construct ArchWall # No need to test obj.ArchSketchData ... for ig, geom in enumerate(skGeom): - if not geom.Construction and (not obj.ArchSketchEdges or str(ig) in obj.ArchSketchEdges): - # support Line, Arc, Circle, Ellipse for Sketch as Base at the moment - if isinstance(geom.Geometry, (Part.LineSegment, Part.Circle, Part.ArcOfCircle, Part.Ellipse)): + # Construction mode edges should be ignored if + # ArchSketchEdges, otherwise, ArchSketchEdges data + # needs to take out those in Construction before + # using as parameters. + if (not obj.ArchSketchEdges and not geom.Construction) or str(ig) in obj.ArchSketchEdges: + # support Line, Arc, Circle, Ellipse for Sketch + # as Base at the moment + if isinstance(geom.Geometry, (Part.LineSegment, + Part.Circle, Part.ArcOfCircle, + Part.Ellipse)): skGeomEdgesI = geom.Geometry.toShape() + skGeomEdges.append(skGeomEdgesI) for cluster in Part.getSortedClusters(skGeomEdges): clusterTransformed = [] @@ -903,7 +972,6 @@ def getExtrusionData(self,obj): self.basewires = [self.basewires[0] for l in layers] layeroffset = 0 baseface = None - self.connectEdges = [] for i,wire in enumerate(self.basewires): @@ -983,7 +1051,6 @@ def getExtrusionData(self,obj): # Get the 'offseted' wire taking into account # of Width and Align of each edge, and overall # Offset - wNe2 = DraftGeomUtils.offsetWire(wire, dvec, bind=False, occ=False, From dbb412ff47b1b73d6edd957e6e46b3f7d47a572f Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Thu, 28 Nov 2024 23:26:31 +0800 Subject: [PATCH 132/161] [ArchWall] loads() dumps() to call parent methods --- src/Mod/BIM/ArchWall.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index 49bc4cb9d2a3..ab0c930a1f4a 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -222,12 +222,22 @@ def setProperties(self, obj): self.connectEdges = [] self.Type = "Wall" - def dumps(self): # Supercede Arch.Component.dumps() + def dumps(self): + super().dumps() return self.ArchSkPropSetPickedUuid, self.ArchSkPropSetListPrev def loads(self,state): - self.ArchSkPropSetPickedUuid = state[0] - self.ArchSkPropSetListPrev = state[1] + super().loads(state) # do nothing as of 2024.11.28 + if state == None: + return + elif state[0] == 'W': # state[1] == 'a', behaviour before 2024.11.28 + return + elif state[0] == 'Wall': + self.ArchSkPropSetPickedUuid = state[1] + self.ArchSkPropSetListPrev = state[2] + elif state[0] != 'Wall': # model before merging super.dumps/loads() + self.ArchSkPropSetPickedUuid = state[0] + self.ArchSkPropSetListPrev = state[1] def onDocumentRestored(self,obj): """Method run when the document is restored. Re-adds the Arch component, and Arch wall properties.""" From bc5bf9bbdc475b16a762e0348684ae697ab407af Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Thu, 28 Nov 2024 17:46:33 +0100 Subject: [PATCH 133/161] Draft: Sort AutoGroup dropdown menu alphabetically Fixes #16191. --- src/Mod/Draft/draftguitools/gui_groups.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_groups.py b/src/Mod/Draft/draftguitools/gui_groups.py index 959a13c09cf5..7ac686efa770 100644 --- a/src/Mod/Draft/draftguitools/gui_groups.py +++ b/src/Mod/Draft/draftguitools/gui_groups.py @@ -235,18 +235,16 @@ def Activated(self): # Otherwise it builds a list of layers, with names and icons, # including the options "None" and "Add new layer". - self.groups = [translate("draft", "None")] - gn = [o.Name for o in self.doc.Objects if utils.get_type(o) == "Layer"] + grps = [o for o in self.doc.Objects if utils.get_type(o) == "Layer"] if params.get_param("AutogroupAddGroups"): - gn.extend(groups.get_group_names()) - self.groups.extend(gn) + grps.extend([o for o in self.doc.Objects if groups.is_group(o)]) + grps.sort(key=lambda grp: grp.Label) + self.groups = [translate("draft", "None")] + [o.Name for o in grps] self.labels = [translate("draft", "None")] self.icons = [self.ui.getIcon(":/icons/button_invalid.svg")] - for g in gn: - o = self.doc.getObject(g) - if o: - self.labels.append(o.Label) - self.icons.append(o.ViewObject.Icon) + for grp in grps: + self.labels.append(grp.Label) + self.icons.append(grp.ViewObject.Icon) self.labels.append(translate("draft", "Add new Layer")) self.icons.append(self.ui.getIcon(":/icons/document-new.svg")) From 42d09e08d55c7732608d883345c1ba00232438e9 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Thu, 28 Nov 2024 22:38:07 +0100 Subject: [PATCH 134/161] Draft: fix handling of Links in TD DraftViews Forum topic: https://forum.freecad.org/viewtopic.php?t=92476 For LinkGroups and Links to Std_Groups that do not have a default placement, a temporary hidden document is used to handle the placement of their children. This is a bit of a hack of course. --- src/Mod/Draft/draftfunctions/svg.py | 161 ++++++++++++++++++---------- 1 file changed, 105 insertions(+), 56 deletions(-) diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index 2b30ccb55bb5..c2137cf1a34d 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -103,8 +103,9 @@ def get_arrow(obj, arrowtype, point, arrowsize, color, linewidth, angle=0): """Get the SVG representation from an arrow.""" svg = "" + vobj = _get_view_object(obj) - if not App.GuiUp or not obj.ViewObject: + if not App.GuiUp or vobj is None: return svg _cx_cy_r = 'cx="{}" cy="{}" r="{}"'.format(point.x, point.y, arrowsize) @@ -114,7 +115,7 @@ def get_arrow(obj, _scale = 'scale({size},{size})'.format(size=arrowsize) _style = 'style="stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:square"' - if obj.ViewObject.ArrowType == "Circle": + if vobj.ArrowType == "Circle": svg += '
diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index e53c08095f6f..67550b5cb5cc 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -557,19 +557,35 @@ PyObject* SketchObjectPy::addExternal(PyObject* args) { char* ObjectName; char* SubName; - PyObject* defining; // this is an optional argument default false + PyObject* defining; // this is an optional argument default false + PyObject* intersection; // this is an optional argument default false bool isDefining; - if (!PyArg_ParseTuple(args, "ssO!", &ObjectName, &SubName, &PyBool_Type, &defining)) { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "ss", &ObjectName, &SubName)) { - return nullptr; + bool isIntersection; + if (!PyArg_ParseTuple(args, + "ssO!O!", + &ObjectName, + &SubName, + &PyBool_Type, + &defining, + &PyBool_Type, + &intersection)) { + if (!PyArg_ParseTuple(args, "ssO!", &ObjectName, &SubName, &PyBool_Type, &defining)) { + PyErr_Clear(); + if (!PyArg_ParseTuple(args, "ss", &ObjectName, &SubName)) { + return nullptr; + } + else { + isDefining = false; + } } else { - isDefining = false; + isDefining = Base::asBoolean(defining); } + isIntersection = false; } else { isDefining = Base::asBoolean(defining); + isIntersection = Base::asBoolean(intersection); } // get the target object for the external link @@ -590,7 +606,7 @@ PyObject* SketchObjectPy::addExternal(PyObject* args) } // add the external - if (skObj->addExternal(Obj, SubName, isDefining) < 0) { + if (skObj->addExternal(Obj, SubName, isDefining, isIntersection) < 0) { std::stringstream str; str << "Not able to add external shape element " << SubName; PyErr_SetString(PyExc_ValueError, str.str().c_str()); diff --git a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp index 72db9b24d7c9..2a0c880c3162 100644 --- a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp +++ b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp @@ -115,7 +115,9 @@ CmdSketcherToggleConstruction::CmdSketcherToggleConstruction() rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CreatePeriodicBSplineByInterpolation"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CompCreateBSpline"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CarbonCopy"); + rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CompExternal"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_External"); + rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_Intersection"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_ToggleConstruction"); } diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 9f9986080a75..c7d464909821 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1434,7 +1434,63 @@ class CmdSketcherCompCurveEdition: public Gui::GroupCommand } }; -// ====================================================================================== +// Group for external tools ============================================= + +class CmdSketcherCompExternal: public Gui::GroupCommand +{ +public: + CmdSketcherCompExternal() + : GroupCommand("Sketcher_CompExternal") + { + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Create external"); + sToolTipText = QT_TR_NOOP("Create external edges linked to external geometries."); + sWhatsThis = "Sketcher_CompExternal"; + sStatusTip = sToolTipText; + eType = ForEdit; + + setCheckable(false); + + addCommand("Sketcher_External"); + addCommand("Sketcher_Intersection"); + } + + void updateAction(int mode) override + { + Gui::ActionGroup* pcAction = qobject_cast(getAction()); + if (!pcAction) { + return; + } + + QList al = pcAction->actions(); + int index = pcAction->property("defaultAction").toInt(); + switch (static_cast(mode)) { + case GeometryCreationMode::Normal: + al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_External")); + al[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Intersection")); + getAction()->setIcon(al[index]->icon()); + break; + case GeometryCreationMode::Construction: + al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_External_Constr")); + al[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Intersection_Constr")); + getAction()->setIcon(al[index]->icon()); + break; + } + } + + const char* className() const override + { + return "CmdSketcherCompExternal"; + } + + bool isActive() override + { + return isCommandActive(getActiveGuiDocument()); + } +}; + +// Externals - Projection ================================================================== DEF_STD_CMD_AU(CmdSketcherExternal) @@ -1443,8 +1499,10 @@ CmdSketcherExternal::CmdSketcherExternal() { sAppModule = "Sketcher"; sGroup = "Sketcher"; - sMenuText = QT_TR_NOOP("Create external geometry"); - sToolTipText = QT_TR_NOOP("Create an edge linked to an external geometry"); + sMenuText = QT_TR_NOOP("Create external projection geometry"); + sToolTipText = QT_TR_NOOP("Create the projection edges of an external geometry.\n" + "External edges can be either defining or construction geometries.\n" + "You can use the toggle construction tool."); sWhatsThis = "Sketcher_External"; sStatusTip = sToolTipText; sPixmap = "Sketcher_External"; @@ -1465,6 +1523,39 @@ bool CmdSketcherExternal::isActive() return isCommandActive(getActiveGuiDocument()); } +// Externals - Intersection ================================================================== + +DEF_STD_CMD_AU(CmdSketcherIntersection) + +CmdSketcherIntersection::CmdSketcherIntersection() + : Command("Sketcher_Intersection") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Create external intersection geometry"); + sToolTipText = + QT_TR_NOOP("Create the intersection edges of an external geometry with the sketch plane.\n" + "External edges can be either defining or construction geometries.\n" + "You can use the toggle construction tool."); + sWhatsThis = "Sketcher_Intersection"; + sStatusTip = sToolTipText; + sPixmap = "Sketcher_Intersection"; + sAccel = "G, I"; + eType = ForEdit; +} + +CONSTRUCTION_UPDATE_ACTION(CmdSketcherIntersection, "Sketcher_Intersection") + +void CmdSketcherIntersection::activated(int iMsg) +{ + ActivateHandler(getActiveGuiDocument(), std::make_unique(true)); +} + +bool CmdSketcherIntersection::isActive(void) +{ + return isCommandActive(getActiveGuiDocument()); +} + // ====================================================================================== DEF_STD_CMD_AU(CmdSketcherCarbonCopy) @@ -2069,6 +2160,8 @@ void CreateSketcherCommandsCreateGeo() rcCmdMgr.addCommand(new CmdSketcherSplit()); rcCmdMgr.addCommand(new CmdSketcherCompCurveEdition()); rcCmdMgr.addCommand(new CmdSketcherExternal()); + rcCmdMgr.addCommand(new CmdSketcherIntersection()); + rcCmdMgr.addCommand(new CmdSketcherCompExternal()); rcCmdMgr.addCommand(new CmdSketcherCarbonCopy()); rcCmdMgr.addCommand(new CmdSketcherCompLine()); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h index cc57af0df5f9..5c0613a1f807 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h @@ -116,7 +116,9 @@ class ExternalSelection: public Gui::SelectionFilterGate class DrawSketchHandlerExternal: public DrawSketchHandler { public: - DrawSketchHandlerExternal() = default; + DrawSketchHandlerExternal(bool intersection = false) + : intersection(intersection) + {} ~DrawSketchHandlerExternal() override { Gui::Selection().rmvSelectionGate(); @@ -163,10 +165,11 @@ class DrawSketchHandlerExternal: public DrawSketchHandler Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add external geometry")); Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addExternal(\"%s\",\"%s\", %s)", + "addExternal(\"%s\",\"%s\", %s, %s)", msg.pObjectName, msg.pSubName, - isConstructionMode() ? "False" : "True"); + isConstructionMode() ? "False" : "True", + intersection ? "True" : "False"); Gui::Command::commitCommand(); @@ -214,6 +217,10 @@ class DrawSketchHandlerExternal: public DrawSketchHandler QString getCrosshairCursorSVGName() const override { + if (intersection) { + return QString::fromLatin1("Sketcher_Pointer_External_Intersection"); + } + return QString::fromLatin1("Sketcher_Pointer_External"); } @@ -222,6 +229,8 @@ class DrawSketchHandlerExternal: public DrawSketchHandler Q_UNUSED(sketchgui); setAxisPickStyle(true); } + + bool intersection; }; diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index 037df4136568..90bbeaa2965f 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -200,6 +200,8 @@ icons/geometry/Sketcher_Extend.svg icons/geometry/Sketcher_External.svg icons/geometry/Sketcher_External_Constr.svg + icons/geometry/Sketcher_Intersection.svg + icons/geometry/Sketcher_Intersection_Constr.svg icons/geometry/Sketcher_Split.svg icons/geometry/Sketcher_ToggleConstruction.svg icons/geometry/Sketcher_ToggleConstruction_Constr.svg @@ -251,6 +253,7 @@ icons/pointers/Sketcher_Pointer_Create_Symmetry.svg icons/pointers/Sketcher_Pointer_Extension.svg icons/pointers/Sketcher_Pointer_External.svg + icons/pointers/Sketcher_Pointer_External_Intersection.svg icons/pointers/Sketcher_Pointer_Heptagon.svg icons/pointers/Sketcher_Pointer_Hexagon.svg icons/pointers/Sketcher_Pointer_InsertKnot.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg new file mode 100644 index 000000000000..b3f6c993ae13 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [maxwxyz] + + + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + + + FreeCAD LGPL2+ + + + 2023-12-19 + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg new file mode 100644 index 000000000000..29e130e4cabb --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [maxwxyz] + + + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + + + FreeCAD LGPL2+ + + + 2023-12-19 + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg new file mode 100644 index 000000000000..b7124ee89320 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg @@ -0,0 +1,101 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index d5fa37c59cc1..e02ccb236040 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -538,6 +538,7 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel) SketcherAddWorkspaceFillets(consaccel); SketcherAddWorkspaceCurveEdition(consaccel); consaccel << "Sketcher_External" + << "Sketcher_Intersection" << "Sketcher_CarbonCopy" << "Separator" << "Sketcher_SelectOrigin" @@ -564,7 +565,7 @@ inline void SketcherAddWorkbenchTools(Gui::ToolBarItem& consac { SketcherAddWorkspaceFillets(consaccel); SketcherAddWorkspaceCurveEdition(consaccel); - consaccel << "Sketcher_External" + consaccel << "Sketcher_CompExternal" << "Sketcher_CarbonCopy" << "Separator" << "Sketcher_Translate" From ac788df6084f5e31d7c8e0eee51b7afec445f17f Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 12 Nov 2024 10:33:23 +0100 Subject: [PATCH 139/161] Sketcher: Rename External to Projection --- src/Gui/PreferencePackTemplates/Shortcuts.cfg | 3 +- src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp | 2 +- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 24 +-- src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 4 +- ...r_External.svg => Sketcher_Projection.svg} | 67 +++--- ...str.svg => Sketcher_Projection_Constr.svg} | 193 ++++++++++-------- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 3 +- src/Mod/Sketcher/Gui/Workbench.cpp | 2 +- 8 files changed, 173 insertions(+), 125 deletions(-) rename src/Mod/Sketcher/Gui/Resources/icons/geometry/{Sketcher_External.svg => Sketcher_Projection.svg} (85%) rename src/Mod/Sketcher/Gui/Resources/icons/geometry/{Sketcher_External_Constr.svg => Sketcher_Projection_Constr.svg} (58%) diff --git a/src/Gui/PreferencePackTemplates/Shortcuts.cfg b/src/Gui/PreferencePackTemplates/Shortcuts.cfg index 6dc7c24db765..63db87461b06 100644 --- a/src/Gui/PreferencePackTemplates/Shortcuts.cfg +++ b/src/Gui/PreferencePackTemplates/Shortcuts.cfg @@ -555,8 +555,8 @@ D G, Q - G, X + G, I @@ -565,6 +565,7 @@ Z, M + G, X Z, A Z, R diff --git a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp index 2a0c880c3162..0cc93aea498b 100644 --- a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp +++ b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp @@ -116,7 +116,7 @@ CmdSketcherToggleConstruction::CmdSketcherToggleConstruction() rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CompCreateBSpline"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CarbonCopy"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CompExternal"); - rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_External"); + rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_Projection"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_Intersection"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_ToggleConstruction"); } diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index c7d464909821..97b57910c920 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1452,7 +1452,7 @@ class CmdSketcherCompExternal: public Gui::GroupCommand setCheckable(false); - addCommand("Sketcher_External"); + addCommand("Sketcher_Projection"); addCommand("Sketcher_Intersection"); } @@ -1467,12 +1467,12 @@ class CmdSketcherCompExternal: public Gui::GroupCommand int index = pcAction->property("defaultAction").toInt(); switch (static_cast(mode)) { case GeometryCreationMode::Normal: - al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_External")); + al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Projection")); al[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Intersection")); getAction()->setIcon(al[index]->icon()); break; case GeometryCreationMode::Construction: - al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_External_Constr")); + al[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Projection_Constr")); al[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Intersection_Constr")); getAction()->setIcon(al[index]->icon()); break; @@ -1492,10 +1492,10 @@ class CmdSketcherCompExternal: public Gui::GroupCommand // Externals - Projection ================================================================== -DEF_STD_CMD_AU(CmdSketcherExternal) +DEF_STD_CMD_AU(CmdSketcherProjection) -CmdSketcherExternal::CmdSketcherExternal() - : Command("Sketcher_External") +CmdSketcherProjection::CmdSketcherProjection() + : Command("Sketcher_Projection") { sAppModule = "Sketcher"; sGroup = "Sketcher"; @@ -1503,22 +1503,22 @@ CmdSketcherExternal::CmdSketcherExternal() sToolTipText = QT_TR_NOOP("Create the projection edges of an external geometry.\n" "External edges can be either defining or construction geometries.\n" "You can use the toggle construction tool."); - sWhatsThis = "Sketcher_External"; + sWhatsThis = "Sketcher_Projection"; sStatusTip = sToolTipText; - sPixmap = "Sketcher_External"; + sPixmap = "Sketcher_Projection"; sAccel = "G, X"; eType = ForEdit; } -CONSTRUCTION_UPDATE_ACTION(CmdSketcherExternal, "Sketcher_External") +CONSTRUCTION_UPDATE_ACTION(CmdSketcherProjection, "Sketcher_Projection") -void CmdSketcherExternal::activated(int iMsg) +void CmdSketcherProjection::activated(int iMsg) { Q_UNUSED(iMsg); ActivateHandler(getActiveGuiDocument(), std::make_unique()); } -bool CmdSketcherExternal::isActive() +bool CmdSketcherProjection::isActive() { return isCommandActive(getActiveGuiDocument()); } @@ -2159,7 +2159,7 @@ void CreateSketcherCommandsCreateGeo() rcCmdMgr.addCommand(new CmdSketcherExtend()); rcCmdMgr.addCommand(new CmdSketcherSplit()); rcCmdMgr.addCommand(new CmdSketcherCompCurveEdition()); - rcCmdMgr.addCommand(new CmdSketcherExternal()); + rcCmdMgr.addCommand(new CmdSketcherProjection()); rcCmdMgr.addCommand(new CmdSketcherIntersection()); rcCmdMgr.addCommand(new CmdSketcherCompExternal()); rcCmdMgr.addCommand(new CmdSketcherCarbonCopy()); diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index 90bbeaa2965f..f20664b78a85 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -198,8 +198,8 @@ icons/geometry/Sketcher_CreateTriangle.svg icons/geometry/Sketcher_CreateTriangle_Constr.svg icons/geometry/Sketcher_Extend.svg - icons/geometry/Sketcher_External.svg - icons/geometry/Sketcher_External_Constr.svg + icons/geometry/Sketcher_Projection.svg + icons/geometry/Sketcher_Projection_Constr.svg icons/geometry/Sketcher_Intersection.svg icons/geometry/Sketcher_Intersection_Constr.svg icons/geometry/Sketcher_Split.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg similarity index 85% rename from src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg rename to src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg index da8bb967f279..1343f13b1bd2 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg @@ -262,7 +262,7 @@ y1="37" x2="-19" y2="37" - gradientTransform="rotate(15,69.468151,244.38323)" /> + gradientTransform="rotate(15,-47.524311,105.68178)" /> + @@ -304,50 +314,49 @@ + transform="translate(-50.14077,-31.192563)"> + d="m 95,61 13.71049,-6.770252 v -20 L 95,41 Z" + style="fill:url(#linearGradient3858);fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" + sodipodi:nodetypes="ccccc" /> + d="M 63,39 79.090305,32.739708 108.71049,34.229748 95,41 Z" + style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" + sodipodi:nodetypes="ccccc" /> + d="m 97.000001,57.8 9.710489,-4.803252 v -15.567 L 97,42 Z" + style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + sodipodi:nodetypes="ccccc" /> + - - - + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg similarity index 58% rename from src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg rename to src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg index a7aa4227c612..fdee350e24a4 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg @@ -1,18 +1,41 @@ - - + + gradientTransform="rotate(15,-47.524311,105.68178)" /> + @@ -280,84 +313,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + id="g3849" + transform="translate(-50.14077,-31.192563)"> + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 55a91adafa71..4f1938f61e58 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -4337,7 +4337,8 @@ void ViewProviderSketch::generateContextMenu() << "Sketcher_Trimming" << "Sketcher_Extend" << "Separator" - << "Sketcher_External" + << "Sketcher_Projection" + << "Sketcher_Intersection" << "Separator" << "Sketcher_CompDimensionTools" << "Sketcher_CompConstrainTools" diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index e02ccb236040..67a96bad027f 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -537,7 +537,7 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel) { SketcherAddWorkspaceFillets(consaccel); SketcherAddWorkspaceCurveEdition(consaccel); - consaccel << "Sketcher_External" + consaccel << "Sketcher_Projection" << "Sketcher_Intersection" << "Sketcher_CarbonCopy" << "Separator" From 63414bf06b44b188ab6d7bf96b262a4c657512fb Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 12 Nov 2024 10:34:31 +0100 Subject: [PATCH 140/161] Sketcher: Hide External BSpline overlay informations. --- .../Sketcher/Gui/EditModeInformationOverlayCoinConverter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/EditModeInformationOverlayCoinConverter.cpp b/src/Mod/Sketcher/Gui/EditModeInformationOverlayCoinConverter.cpp index 37b475b7e689..b4ed4468d829 100644 --- a/src/Mod/Sketcher/Gui/EditModeInformationOverlayCoinConverter.cpp +++ b/src/Mod/Sketcher/Gui/EditModeInformationOverlayCoinConverter.cpp @@ -61,7 +61,9 @@ void EditModeInformationOverlayCoinConverter::convert(const Part::Geometry* geom { if (geometry->is()) { - // at this point all calculations relate to BSplineCurves + if (geoid < 0) { + return; + } calculate(geometry, geoid); calculate(geometry, geoid); calculate(geometry, geoid); From e2f998f3016c9c334e529be8462944ce2bd323d0 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 12 Nov 2024 11:38:35 +0100 Subject: [PATCH 141/161] Sketcher: External: Change style to : defining are solid lines. Non-defining dashed. Both use external color. --- src/Mod/Sketcher/Gui/EditModeCoinManager.cpp | 2 +- .../Gui/EditModeCoinManagerParameters.cpp | 23 +++++++++++++++++++ .../Gui/EditModeCoinManagerParameters.h | 14 ++--------- .../Gui/EditModeGeometryCoinManager.cpp | 6 ++--- src/Mod/Sketcher/Gui/SketcherSettings.cpp | 2 +- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp index 28660f5b64d8..98b81d062383 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp @@ -175,7 +175,7 @@ void EditModeCoinManager::ParameterObserver::initParameters() }}, {"ExternalPattern", [this, &drawingParameters = Client.drawingParameters](const std::string& param) { - updatePattern(drawingParameters.ExternalPattern, param, 0b1110010011100100); + updatePattern(drawingParameters.ExternalPattern, param, 0b1111110011111100); }}, {"CreateLineColor", [this, drawingParameters = Client.drawingParameters](const std::string& param) { diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.cpp index 70c7bb1690f0..7f044b589fb7 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.cpp @@ -22,11 +22,34 @@ #include "PreCompiled.h" +#include "Mod/Sketcher/App/ExternalGeometryFacade.h" + #include "EditModeCoinManagerParameters.h" using namespace SketcherGui; +int GeometryLayerParameters::getSubLayerIndex(const int geoId, + const Sketcher::GeometryFacade* geom) const +{ + bool isConstruction = geom->getConstruction(); + bool isInternal = geom->isInternalAligned(); + bool isExternal = geoId <= Sketcher::GeoEnum::RefExt; + if (isExternal) { + auto egf = Sketcher::ExternalGeometryFacade::getFacade(geom->clone()); + if (egf->testFlag(Sketcher::ExternalGeometryExtension::Defining)) { + // Defining external are added to the Normal sublayers because they + // share the same line style. + return static_cast(SubLayer::Normal); + } + } + + return static_cast(isExternal ? SubLayer::External + : isInternal ? SubLayer::Internal + : isConstruction ? SubLayer::Construction + : SubLayer::Normal); +} + SbColor DrawingParameters::InformationColor(0.0f, 1.0f, 0.0f); // #00FF00 -> ( 0,255, 0) SbColor DrawingParameters::CreateCurveColor(0.5f, 0.5f, 0.5f); // ##7f7f7f -> (127,127,127) SbColor DrawingParameters::CrossColorH(0.8f, 0.4f, 0.4f); // #CC6666 -> (204,102,102) diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h index bff79da43950..877144c0504b 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h +++ b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h @@ -145,7 +145,7 @@ struct DrawingParameters unsigned int CurvePattern = 0b1111111111111111; // pattern of normal edges unsigned int ConstructionPattern = 0b1111110011111100; // pattern of construction edges unsigned int InternalPattern = 0b1111110011111100; // pattern of internal edges - unsigned int ExternalPattern = 0b1110010011100100; // pattern of external edges + unsigned int ExternalPattern = 0b1111110011111100; // pattern of external edges //@} }; @@ -304,17 +304,7 @@ class GeometryLayerParameters return SubLayers; } - int inline getSubLayerIndex(const int geoId, const Sketcher::GeometryFacade* geom) const - { - bool isConstruction = geom->getConstruction(); - bool isInternal = geom->isInternalAligned(); - bool isExternal = geoId <= Sketcher::GeoEnum::RefExt; - - return static_cast(isExternal ? SubLayer::External - : isInternal ? SubLayer::Internal - : isConstruction ? SubLayer::Construction - : SubLayer::Normal); - } + int getSubLayerIndex(const int geoId, const Sketcher::GeometryFacade* geom) const; bool isNormalSubLayer(int t) const { diff --git a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp index afcd044ccf91..b215874e0d03 100644 --- a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp @@ -402,6 +402,7 @@ void EditModeGeometryCoinManager::updateGeometryColor(const GeoListFacade& geoli ViewProviderSketchCoinAttorney::isCurveSelected(viewProvider, GeoId); bool preselected = (preselectcurve == GeoId); bool constrainedElement = isFullyConstraintElement(GeoId); + bool isExternal = GeoId < -1; if (selected || preselected) { color[i] = selected ? (preselected ? drawingParameters.PreselectSelectedColor @@ -414,16 +415,13 @@ void EditModeGeometryCoinManager::updateGeometryColor(const GeoListFacade& geoli SbVec3f(x, y, viewOrientationFactor * drawingParameters.zHighLine); } } - else if (geometryLayerParameters.isExternalSubLayer(t)) { + else if (isExternal) { auto geom = geolistfacade.getGeometryFacadeFromGeoId(GeoId); auto egf = ExternalGeometryFacade::getFacade(geom->clone()); auto ref = egf->getRef(); if (egf->testFlag(ExternalGeometryExtension::Missing)) { color[i] = drawingParameters.InvalidSketchColor; } - else if (egf->testFlag(ExternalGeometryExtension::Defining)) { - color[i] = drawingParameters.CurveColor; - } else { color[i] = drawingParameters.CurveExternalColor; } diff --git a/src/Mod/Sketcher/Gui/SketcherSettings.cpp b/src/Mod/Sketcher/Gui/SketcherSettings.cpp index 5ddf09677026..c74c9e32f802 100644 --- a/src/Mod/Sketcher/Gui/SketcherSettings.cpp +++ b/src/Mod/Sketcher/Gui/SketcherSettings.cpp @@ -644,7 +644,7 @@ void SketcherSettingsAppearance::loadSettings() } ui->InternalPattern->setCurrentIndex(index); - pattern = hGrp->GetInt("ExternalPattern", 0b1110010011100100); + pattern = hGrp->GetInt("ExternalPattern", 0b1111110011111100); index = ui->ExternalPattern->findData(QVariant(pattern)); if (index < 0) { index = 0; From 9410a5e982d6f2e8a2cc611088a110d73eb1a5fc Mon Sep 17 00:00:00 2001 From: bdieterm <119257544+bdieterm@users.noreply.github.com> Date: Sun, 17 Nov 2024 11:04:40 +0100 Subject: [PATCH 142/161] Gui: use utf-8 encoding for saving recorded macros FCMacros always have the header "# -*- coding: utf-8 -*". But the QTextStream class in Qt5 does not always use utf-8 for saving the text file. --- src/Gui/Macro.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Gui/Macro.cpp b/src/Gui/Macro.cpp index 7b6ca9200584..32549ca763f3 100644 --- a/src/Gui/Macro.cpp +++ b/src/Gui/Macro.cpp @@ -80,6 +80,9 @@ bool MacroFile::commit() // sort import lines and avoid duplicates QTextStream str(&file); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + str.setCodec("UTF-8"); +#endif QStringList import; import << QString::fromLatin1("import FreeCAD"); QStringList body; From 374c5713b29dc9700c8654b00a7c6f6681d0d3a7 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Thu, 21 Nov 2024 15:05:40 +0100 Subject: [PATCH 143/161] PartDesign: Fix newSketch not working when editing a body from an external file. --- src/Mod/PartDesign/Gui/SketchWorkflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp index 2c623678e84c..379c313539f4 100644 --- a/src/Mod/PartDesign/Gui/SketchWorkflow.cpp +++ b/src/Mod/PartDesign/Gui/SketchWorkflow.cpp @@ -247,7 +247,7 @@ class SketchPreselection guidocument->openCommand(QT_TRANSLATE_NOOP("Command", "Create a Sketch on Face")); FCMD_OBJ_CMD(activeBody, "newObject('Sketcher::SketchObject','" << FeatName << "')"); - auto Feat = appdocument->getObject(FeatName.c_str()); + auto Feat = activeBody->getDocument()->getObject(FeatName.c_str()); FCMD_OBJ_CMD(Feat, "AttachmentSupport = " << supportString); FCMD_OBJ_CMD(Feat, "MapMode = '" << Attacher::AttachEngine::getModeName(Attacher::mmFlatFace)<<"'"); Gui::Command::updateActive(); From ef3445e9e16c04ec87d25c08300966a52721be3b Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Wed, 20 Nov 2024 11:17:26 +0100 Subject: [PATCH 144/161] Core / Assembly: Add a way for vp edit modes to be restored. --- src/Gui/Document.cpp | 30 ++++++++++++++++++- src/Gui/Document.h | 2 ++ src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 3 ++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 3223e1a13a13..d75604d5b098 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -84,8 +84,12 @@ struct DocumentP bool _isModified; bool _isTransacting; bool _changeViewTouchDocument; + bool _editWantsRestore; + bool _editWantsRestorePrevious; int _editMode; + int _editModePrevious; ViewProvider* _editViewProvider; + ViewProvider* _editViewProviderPrevious; App::DocumentObject* _editingObject; ViewProviderDocumentObject* _editViewProviderParent; std::string _editSubname; @@ -426,10 +430,14 @@ Document::Document(App::Document* pcDocument,Application * app) d->_pcAppWnd = app; d->_pcDocument = pcDocument; d->_editViewProvider = nullptr; + d->_editViewProviderPrevious = nullptr; d->_editingObject = nullptr; d->_editViewProviderParent = nullptr; d->_editingViewer = nullptr; d->_editMode = 0; + d->_editModePrevious = 0; + d->_editWantsRestore = false; + d->_editWantsRestorePrevious = false; //NOLINTBEGIN // Setup the connections @@ -654,7 +662,16 @@ void Document::setEditingTransform(const Base::Matrix4D &mat) { } void Document::resetEdit() { + bool vpIsNotNull = d->_editViewProvider != nullptr; + int modeToRestore = d->_editModePrevious; + Gui::ViewProvider* vpToRestore = d->_editViewProviderPrevious; + bool shouldRestorePrevious = d->_editWantsRestorePrevious; + Application::Instance->setEditDocument(nullptr); + + if (vpIsNotNull && shouldRestorePrevious) { + setEdit(vpToRestore, modeToRestore); + } } void Document::_resetEdit() @@ -669,6 +686,11 @@ void Document::_resetEdit() d->_editViewProvider->finishEditing(); + d->_editViewProviderPrevious = d->_editViewProvider; + d->_editModePrevious = d->_editMode; + d->_editWantsRestorePrevious = d->_editWantsRestore; + d->_editWantsRestore = false; + // Have to check d->_editViewProvider below, because there is a chance // the editing object gets deleted inside the above call to // 'finishEditing()', which will trigger our slotDeletedObject(), which @@ -690,8 +712,9 @@ void Document::_resetEdit() d->_editingViewer = nullptr; d->_editObjs.clear(); d->_editingObject = nullptr; - if(Application::Instance->editDocument() == this) + if (Application::Instance->editDocument() == this) { Application::Instance->setEditDocument(nullptr); + } } ViewProvider *Document::getInEdit(ViewProviderDocumentObject **parentVp, @@ -739,6 +762,11 @@ void Document::setAnnotationViewProvider(const char* name, ViewProvider *pcProvi } } +void Document::setEditRestore(bool askRestore) +{ + d->_editWantsRestore = askRestore; +} + ViewProvider * Document::getAnnotationViewProvider(const char* name) const { std::map::const_iterator it = d->_ViewProviderMapAnnotation.find(name); diff --git a/src/Gui/Document.h b/src/Gui/Document.h index 6b0a1786bc6d..147412b1309e 100644 --- a/src/Gui/Document.h +++ b/src/Gui/Document.h @@ -256,6 +256,8 @@ class GuiExport Document : public Base::Persistence void resetEdit(); /// reset edit of this document void _resetEdit(); + /// set if the edit asks for restore or not. + void setEditRestore(bool val); /// get the in edit ViewProvider or NULL ViewProvider *getInEdit(ViewProviderDocumentObject **parentVp=nullptr, std::string *subname=nullptr, int *mode=nullptr, std::string *subElement=nullptr) const; diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index 5eeae897761e..67de217b8cf0 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -221,6 +221,9 @@ bool ViewProviderAssembly::canDragObjectToTarget(App::DocumentObject* obj, bool ViewProviderAssembly::setEdit(int mode) { if (mode == ViewProvider::Default) { + // Ask that this edit mode be restored. For example if it is quit to edit a sketch. + getDocument()->setEditRestore(true); + // Set the part as 'Activated' ie bold in the tree. Gui::Command::doCommand(Gui::Command::Gui, "appDoc = App.getDocument('%s')\n" From 45a95599a08abf23c65d08fd1a024ce7363a5b36 Mon Sep 17 00:00:00 2001 From: Max Wilfinger Date: Fri, 15 Nov 2024 20:13:21 +0100 Subject: [PATCH 145/161] remove .xpm icons --- src/Gui/CMakeLists.txt | 4 +- src/Gui/Icons/LinkArrayOverlay.xpm | 13 - src/Gui/Icons/LinkSubElement.xpm | 15 -- src/Gui/Icons/LinkSubOverlay.xpm | 15 -- src/Gui/Icons/bulb.xpm | 414 ----------------------------- src/Gui/Icons/button_down.xpm | 112 -------- src/Gui/Icons/button_left.xpm | 118 -------- src/Gui/Icons/button_right.xpm | 118 -------- src/Gui/Icons/button_up.xpm | 112 -------- src/Gui/Icons/freecad.xpm | 67 ----- src/Gui/Icons/resource.qrc | 3 - 11 files changed, 2 insertions(+), 989 deletions(-) delete mode 100644 src/Gui/Icons/LinkArrayOverlay.xpm delete mode 100644 src/Gui/Icons/LinkSubElement.xpm delete mode 100644 src/Gui/Icons/LinkSubOverlay.xpm delete mode 100644 src/Gui/Icons/bulb.xpm delete mode 100644 src/Gui/Icons/button_down.xpm delete mode 100644 src/Gui/Icons/button_left.xpm delete mode 100644 src/Gui/Icons/button_right.xpm delete mode 100644 src/Gui/Icons/button_up.xpm delete mode 100644 src/Gui/Icons/freecad.xpm diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 2bf2d8428609..475ae351b4ef 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1398,7 +1398,7 @@ else(WIN32) INSTALL(TARGETS FreeCADGui LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) - #INSTALL(FILES Icons/freecad.xpm + #INSTALL(FILES # Icons/freecad-icon-16.png # Icons/freecad-icon-32.png # Icons/freecad-icon-48.png @@ -1412,7 +1412,7 @@ else(WIN32) INSTALL(FILES Icons/freecad-icon-48.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps RENAME org.freecad.FreeCAD.png) INSTALL(FILES Icons/freecad-icon-64.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps RENAME org.freecad.FreeCAD.png) INSTALL(FILES Icons/freecad.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps RENAME org.freecad.FreeCAD.svg) - INSTALL(FILES Icons/freecad.xpm DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps) + INSTALL(FILES Icons/freecad.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps) INSTALL(FILES Icons/freecad-doc.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/mimetypes RENAME application-x-extension-fcstd.svg) endif(WIN32) diff --git a/src/Gui/Icons/LinkArrayOverlay.xpm b/src/Gui/Icons/LinkArrayOverlay.xpm deleted file mode 100644 index 866912a7c465..000000000000 --- a/src/Gui/Icons/LinkArrayOverlay.xpm +++ /dev/null @@ -1,13 +0,0 @@ -/* XPM */ -const char *xpm_link[] = { -"6 6 3 1", -" c None", -"# c #000000", -"a c #8ae234", -"######", -"aaaaa#", -"##aaa#", -"#aa#a#", -"aa##a#", -"##..##"}; - diff --git a/src/Gui/Icons/LinkSubElement.xpm b/src/Gui/Icons/LinkSubElement.xpm deleted file mode 100644 index a5e957580e99..000000000000 --- a/src/Gui/Icons/LinkSubElement.xpm +++ /dev/null @@ -1,15 +0,0 @@ -/* XPM */ -static char *xpm_linksubelement[] = { -"8 8 3 1", -". c None", -"# c #000000", -"a c #33ffff", -".#######", -".#aaaaa#", -"######a#", -"aaaaa#a#", -"##aaa#a#", -"#aa#a#a#", -"aa##a###", -"##..##.."}; - diff --git a/src/Gui/Icons/LinkSubOverlay.xpm b/src/Gui/Icons/LinkSubOverlay.xpm deleted file mode 100644 index 8ab22dddaa19..000000000000 --- a/src/Gui/Icons/LinkSubOverlay.xpm +++ /dev/null @@ -1,15 +0,0 @@ -/* XPM */ -static char *xpm_linksub[] = { -"8 8 3 1", -". c None", -"# c #000000", -"a c #ffffff", -".#######", -".#aaaaa#", -"######a#", -"aaaaa#a#", -"##aaa#a#", -"#aa#a#a#", -"aa##a###", -"##..##.."}; - diff --git a/src/Gui/Icons/bulb.xpm b/src/Gui/Icons/bulb.xpm deleted file mode 100644 index 41645af99728..000000000000 --- a/src/Gui/Icons/bulb.xpm +++ /dev/null @@ -1,414 +0,0 @@ -/* XPM */ -static char * bulb_xpm[] = { -"32 32 379 2", -" c None", -". c #3B3503", -"+ c #3C3502", -"@ c #342E01", -"# c #3B3502", -"$ c #3C3702", -"% c #6A6214", -"& c #D3C339", -"* c #F6E349", -"= c #FBE84E", -"- c #D3C338", -"; c #696113", -"> c #3C3501", -", c #3C3604", -"' c #D8C73A", -") c #FBE84D", -"! c #FAE644", -"~ c #A79A2A", -"{ c #171505", -"] c #181605", -"^ c #A79926", -"/ c #F9E43D", -"( c #FBE84C", -"_ c #D6C536", -": c #3E3803", -"< c #3E3704", -"[ c #EDDB45", -"} c #FBE747", -"| c #F9E43E", -"1 c #F9E541", -"2 c #181606", -"3 c #000000", -"4 c #191705", -"5 c #F6E02D", -"6 c #F5DF28", -"7 c #F9E43F", -"8 c #ECD93F", -"9 c #3D3703", -"0 c #3D3602", -"a c #F9E53F", -"b c #FAE645", -"c c #FBE748", -"d c #161406", -"e c #151304", -"f c #F5DF2B", -"g c #F4DE24", -"h c #F2DC1D", -"i c #F8E43C", -"j c #D4C331", -"k c #3B3500", -"l c #6B6214", -"m c #FBE84B", -"n c #564F17", -"o c #574F11", -"p c #F3DD20", -"q c #F2DB19", -"r c #F1DA15", -"s c #FAE749", -"t c #675F0F", -"u c #D4C439", -"v c #F9E540", -"w c #FAE646", -"x c #9E9128", -"y c #9D8F1B", -"z c #F4DD23", -"A c #F2DB1C", -"B c #F1D915", -"C c #F0D80E", -"D c #F5DF2A", -"E c #CFBE2C", -"F c #F6E449", -"G c #F8E43D", -"H c #F9E53E", -"I c #E1CE33", -"J c #010100", -"K c #DCC820", -"L c #F3DC1E", -"M c #F1DA17", -"N c #F0D810", -"O c #EFD609", -"P c #EFD810", -"Q c #F4E141", -"R c #342F01", -"S c #F7E338", -"T c #F8E33A", -"U c #F8E43B", -"V c #F8E339", -"W c #F7E235", -"X c #F6E130", -"Y c #231F06", -"Z c #252206", -"` c #F1DA18", -" . c #F0D811", -".. c #EFD70A", -"+. c #EED503", -"@. c #EED504", -"#. c #FBE74B", -"$. c #342F00", -"%. c #F7E234", -"&. c #F6E131", -"*. c #F6E02E", -"=. c #F5DF29", -"-. c #463F0A", -";. c #484209", -">. c #F0D911", -",. c #EFD70B", -"'. c #EDD400", -"). c #FAE74B", -"!. c #352F00", -"~. c #F5E348", -"{. c #F5E02C", -"]. c #F4DE26", -"^. c #F3DD21", -"/. c #675E0C", -"(. c #695F0A", -"_. c #EFD80F", -":. c #F5E142", -"<. c #293413", -"[. c #D3C337", -"}. c #F8E33B", -"|. c #F4DE25", -"1. c #F3DD22", -"2. c #F2DB1A", -"3. c #F0D80F", -"4. c #EFD709", -"5. c #F5DE27", -"6. c #323408", -"7. c #093B3B", -"8. c #36A89E", -"9. c #69651A", -"0. c #F4DD21", -"a. c #F1DA16", -"b. c #EED712", -"c. c #9D8D09", -"d. c #9C8C05", -"e. c #EBD302", -"f. c #EED605", -"g. c #FAE748", -"h. c #646116", -"i. c #154034", -"j. c #063030", -"k. c #0B4343", -"l. c #3CDBDD", -"m. c #77E9EA", -"n. c #615C33", -"o. c #D6C535", -"p. c #F0D912", -"q. c #807405", -"r. c #7D7000", -"s. c #EDD401", -"t. c #F7E236", -"u. c #D3C12E", -"v. c #4D5B30", -"w. c #3BDFE1", -"x. c #136262", -"y. c #063434", -"z. c #063232", -"A. c #0F5252", -"B. c #3BDFE0", -"C. c #85EAEC", -"D. c #F8F9F8", -"E. c #DBDAD3", -"F. c #46400F", -"G. c #ECD93D", -"H. c #F0D80D", -"I. c #EED607", -"J. c #5C5301", -"K. c #574E00", -"L. c #EBD83A", -"M. c #45400F", -"N. c #CFD1C6", -"O. c #AAE6E4", -"P. c #3CE0E1", -"Q. c #1D8787", -"R. c #063333", -"S. c #136566", -"T. c #A5EEEE", -"U. c #F7F8F6", -"V. c #F6F7F5", -"W. c #F5F6F4", -"X. c #C5C3B8", -"Y. c #464110", -"Z. c #D3C231", -"`. c #CAB70D", -" + c #332E01", -".+ c #353001", -"++ c #CAB60D", -"@+ c #45400E", -"#+ c #BBBBAE", -"$+ c #E6E8E4", -"%+ c #E5E7E3", -"&+ c #BDE4E2", -"*+ c #40E0E2", -"=+ c #2BB0B1", -"-+ c #073333", -";+ c #187778", -">+ c #3CE1E2", -",+ c #B9F0F0", -"'+ c #F6F6F5", -")+ c #F4F5F3", -"!+ c #F3F4F1", -"~+ c #F2F3F0", -"{+ c #D5D5CC", -"]+ c #3B370D", -"^+ c #665D10", -"/+ c #D0BF2C", -"(+ c #685F12", -"_+ c #CCCDC3", -":+ c #E4E7E2", -"<+ c #E3E6E1", -"[+ c #E2E5E0", -"}+ c #E1E4DF", -"|+ c #CBE2DE", -"1+ c #3AE0E2", -"2+ c #23A1A2", -"3+ c #063031", -"4+ c #146465", -"5+ c #3BE0E2", -"6+ c #A0ECEC", -"7+ c #F3F4F2", -"8+ c #F2F3F1", -"9+ c #F1F2F0", -"0+ c #F0F1EF", -"a+ c #EFF1EE", -"b+ c #EEF0ED", -"c+ c #494F50", -"d+ c #494A3F", -"e+ c #393716", -"f+ c #3E3909", -"g+ c #363003", -"h+ c #363103", -"i+ c #433E0E", -"j+ c #575431", -"k+ c #646558", -"l+ c #494E4F", -"m+ c #E3E5E0", -"n+ c #E2E5DF", -"o+ c #E1E4DE", -"p+ c #E0E3DD", -"q+ c #DDE2DC", -"r+ c #70E0DF", -"s+ c #3AD8DA", -"t+ c #0A3C3C", -"u+ c #0D4B4B", -"v+ c #3BDBDE", -"w+ c #79E6E7", -"x+ c #ECF0ED", -"y+ c #EFF0ED", -"z+ c #EEEFEC", -"A+ c #EDEEEB", -"B+ c #ECEDEA", -"C+ c #5F6464", -"D+ c #646865", -"E+ c #7E807C", -"F+ c #626563", -"G+ c #484D4D", -"H+ c #3D4242", -"I+ c #32393A", -"J+ c #2E3436", -"K+ c #5D6362", -"L+ c #E0E3DE", -"M+ c #DFE2DD", -"N+ c #DEE1DB", -"O+ c #DBE0DA", -"P+ c #6CE0DF", -"Q+ c #39D7D8", -"R+ c #083C3C", -"S+ c #083B3B", -"T+ c #38D2D3", -"U+ c #5DE3E4", -"V+ c #DFEDE9", -"W+ c #EBEDE9", -"X+ c #EAECE8", -"Y+ c #E9EBE7", -"Z+ c #6D7372", -"`+ c #33393A", -" @ c #5A5E5D", -".@ c #888A85", -"+@ c #626664", -"@@ c #747977", -"#@ c #DDE0DA", -"$@ c #D8DFD9", -"%@ c #63DFDF", -"&@ c #38D5D6", -"*@ c #093939", -"=@ c #083434", -"-@ c #2EB7B9", -";@ c #46E1E2", -">@ c #CCE9E5", -",@ c #E7EAE5", -"'@ c #E6E9E4", -")@ c #8D9290", -"!@ c #555A59", -"~@ c #525756", -"{@ c #363C3C", -"]@ c #3F4345", -"^@ c #4C5151", -"/@ c #565A58", -"(@ c #585C5B", -"_@ c #434848", -":@ c #8A8F8C", -"<@ c #DBDFD8", -"[@ c #D5DED7", -"}@ c #60DFDF", -"|@ c #37D2D5", -"1@ c #073737", -"2@ c #249D9E", -"3@ c #3CE0E2", -"4@ c #B7E5E2", -"5@ c #E4E6E1", -"6@ c #A2A5A2", -"7@ c #4E5252", -"8@ c #878984", -"9@ c #767874", -"0@ c #696C6A", -"a@ c #606463", -"b@ c #5E6260", -"c@ c #414647", -"d@ c #9CA19D", -"e@ c #D2DDD6", -"f@ c #59DFDF", -"g@ c #36D0D1", -"h@ c #073636", -"i@ c #197677", -"j@ c #3BE0E1", -"k@ c #97E2E0", -"l@ c #ADB1AE", -"m@ c #313738", -"n@ c #555A58", -"o@ c #7C7F7A", -"p@ c #484D4E", -"q@ c #A8B3B0", -"r@ c #52DFE0", -"s@ c #34CCCD", -"t@ c #053232", -"u@ c #115858", -"v@ c #3ADDDF", -"w@ c #6BCBCC", -"x@ c #3B4142", -"y@ c #565A59", -"z@ c #363D3E", -"A@ c #3D4243", -"B@ c #4C5150", -"C@ c #555958", -"D@ c #353A3C", -"E@ c #4CCBCB", -"F@ c #33C9CA", -"G@ c #0A3C3E", -"H@ c #38D3D5", -"I@ c #323E40", -"J@ c #797B77", -"K@ c #757875", -"L@ c #696D69", -"M@ c #585D5B", -"N@ c #30393B", -"O@ c #31C1C3", -"P@ c #073232", -"Q@ c #32B5B9", -"R@ c #3D8586", -"S@ c #3E4546", -"T@ c #343A3B", -"U@ c #3E4446", -"V@ c #3C8586", -"W@ c #30B6BA", -"X@ c #27A9AA", -"Y@ c #3DE0E1", -"Z@ c #A6D1CD", -"`@ c #B8D0CA", -" # c #44DFE0", -".# c #2CB9BB", -"+# c #063131", -"@# c #1D8788", -"## c #3ADFE1", -"$# c #3FDFE1", -"%# c #2AB4B6", -"&# c #146567", -"*# c #23A1A1", -"=# c #063233", -"-# c #053133", -" ", -" . + @ @ # . ", -" $ % & * = = * - ; > ", -" , ' ) ! ~ { ] ^ / ( _ : ", -" < [ } | 1 2 3 3 4 5 6 7 8 9 ", -" 0 ' } a b c d 3 3 e f g h i j k ", -" l ( | ! m m n 3 3 o 6 p q r s t ", -" . u ! v w c b x 3 3 y z A B C D E k ", -" + F G H 1 1 / I J J K L M N O P Q k ", -" R ) S T U V W X Y Z L ` ...+.@.#.$. ", -" R ) %.%.%.&.*.=.-.;.` >.,.@.'.@.).!. ", -" . ~.%.5 {.D ].^./.(. ...@.'.'._.:.k ", -" <.[.}.].|.1.L 2.B 3.4.@.'.'.'.5.E 6. ", -" 7.8.9.m 0.h 2.a.b.c.d.e.'.'.'.f.g.h.i.j. ", -" k.l.m.n.o.i r p.C q.3 3 r.'.'.s.t.u.v.w.x.y. ", -" z.A.B.C.D.E.F.G.V H.I.J.3 3 K.'.f.t.L.M.N.O.P.Q.y. ", -" R.S.P.T.U.V.W.X.Y.Z.g.5.`. +.+++5.g.u.@+#+$+%+&+*+=+z. ", -" -+;+>+,+'+W.)+!+~+{+]+^+/+Q m m Q E (+]+_+:+<+[+}+|+1+2+3+ ", -" R.4+5+6+7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+ ", -" u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+J+J+K+L+M+N+O+P+Q+R+ ", -" S+T+U+V+W+X+Y+Z+`+ @E+.@.@.@.@+@@@N+#@$@%@&@*@ ", -" =@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@ ", -" y.2@3@4@5@6@7@.@8@9@0@a@b@c@d@e@f@g@h@ ", -" -+i@j@k@l@m@n@o@.@.@.@.@p@q@r@s@y. ", -" t@u@v@w@x@y@z@A@B@C@(@D@E@F@R. ", -" G@H@I@y@J@K@L@M@_@N@O@z. ", -" P@Q@R@S@T@T@U@V@W@z. ", -" t@X@Y@Z@`@ #.#+# ", -" R.@###$#%#P@ ", -" -+&#*#=# ", -" -#+# ", -" "}; diff --git a/src/Gui/Icons/button_down.xpm b/src/Gui/Icons/button_down.xpm deleted file mode 100644 index ee5a47d7a0ca..000000000000 --- a/src/Gui/Icons/button_down.xpm +++ /dev/null @@ -1,112 +0,0 @@ -/* XPM */ -static char * button_down_xpm[] = { -"16 16 93 2", -" c None", -". c #203042", -"+ c #233548", -"@ c #567BA1", -"# c #729FCF", -"$ c #729FCE", -"% c #557AA1", -"& c #557AA0", -"* c #6D9ACB", -"= c #6C99CA", -"- c #6B97C9", -"; c #6996C7", -"> c #54799F", -", c #6693C4", -"' c #6591C3", -") c #6390C2", -"! c #628FC1", -"~ c #53779E", -"{ c #53769E", -"] c #5F8BBE", -"^ c #5E8ABD", -"/ c #5C88BC", -"( c #5B87BB", -"_ c #51759D", -": c #5884B8", -"< c #5682B7", -"[ c #5581B6", -"} c #5480B4", -"| c #50749C", -"1 c #507CB1", -"2 c #4F7BB0", -"3 c #4E79AF", -"4 c #4D78AE", -"5 c #4F729B", -"6 c #2F4661", -"7 c #4B6D95", -"8 c #4B6D94", -"9 c #648FBD", -"0 c #4975AB", -"a c #4873AA", -"b c #4772A9", -"c c #4571A8", -"d c #638DBC", -"e c #496B92", -"f c #2D4561", -"g c #21354B", -"h c #5B86B6", -"i c #4471A7", -"j c #436EA6", -"k c #426DA5", -"l c #416CA4", -"m c #3F6AA3", -"n c #3E69A1", -"o c #3D68A0", -"p c #3C679F", -"q c #5480B2", -"r c #21364F", -"s c #2C4562", -"t c #527DB2", -"u c #3C67A0", -"v c #3B669E", -"w c #39649D", -"x c #38639C", -"y c #37629B", -"z c #36609A", -"A c #4D78AD", -"B c #304969", -"C c #3E5E83", -"D c #4670A8", -"E c #335E98", -"F c #325D97", -"G c #315C96", -"H c #305A95", -"I c #3D68A1", -"J c #3F6187", -"K c #4B739F", -"L c #345E99", -"M c #2B5591", -"N c #2A548F", -"O c #2D5893", -"P c #4C72A0", -"Q c #16283D", -"R c #5078A9", -"S c #26508C", -"T c #234D8A", -"U c #4E77AA", -"V c #192E44", -"W c #1F364F", -"X c #4872A7", -"Y c #466FA5", -"Z c #243D59", -"` c #304C6E", -" . c #385579", -" . + + + + . ", -" @ # # # $ % ", -" & * = - ; > ", -" > , ' ) ! ~ ", -" { ] ^ / ( _ ", -" _ : < [ } | ", -" | 1 2 3 4 5 ", -" 6 7 8 9 0 a b c d e e f ", -" g h i j k l m n o p q r ", -" s t u v w x y z A B ", -" C D E F G H I J ", -" K L M N O P ", -" Q R S T U V ", -" W X Y Z ", -" ` . ", -" "}; diff --git a/src/Gui/Icons/button_left.xpm b/src/Gui/Icons/button_left.xpm deleted file mode 100644 index ade43766108a..000000000000 --- a/src/Gui/Icons/button_left.xpm +++ /dev/null @@ -1,118 +0,0 @@ -/* XPM */ -static char * button_left_xpm[] = { -"16 16 99 2", -" c None", -". c #293E53", -"+ c #374F6B", -"@ c #37516B", -"# c #6B98C4", -"$ c #567BA1", -"% c #4A698C", -"& c #709DCC", -"* c #729FCF", -"= c #24344A", -"- c #5E85AF", -"; c #6F9CCC", -"> c #6C99CA", -", c #6A96C8", -"' c #6994C2", -") c #507398", -"! c #4F7298", -"~ c #4F7198", -"{ c #4F7197", -"] c #4E7197", -"^ c #4E6F96", -"/ c #17263B", -"( c #2C435B", -"_ c #6690BD", -": c #6894C6", -"< c #6491C3", -"[ c #628EC1", -"} c #608CBF", -"| c #5E8ABD", -"1 c #5B88BB", -"2 c #5985B9", -"3 c #5783B7", -"4 c #5581B5", -"5 c #537EB3", -"6 c #618EC1", -"7 c #1A293E", -"8 c #3E5A7A", -"9 c #6692C2", -"0 c #5D89BC", -"a c #5A87BA", -"b c #5884B8", -"c c #5682B6", -"d c #5480B5", -"e c #527DB3", -"f c #4F7BB1", -"g c #4D79AF", -"h c #4B77AD", -"i c #4974AB", -"j c #5C89BC", -"k c #16283D", -"l c #426081", -"m c #618CBC", -"n c #5581B7", -"o c #537FB4", -"p c #517CB2", -"q c #4E7AB0", -"r c #4C78AE", -"s c #4A76AC", -"t c #4873AA", -"u c #4671A8", -"v c #436FA6", -"w c #416CA4", -"x c #3F6AA2", -"y c #5784B8", -"z c #15263B", -"A c #2C435E", -"B c #5C86B3", -"C c #4C78AF", -"D c #4772A9", -"E c #4570A7", -"F c #426EA5", -"G c #406BA3", -"H c #3E69A1", -"I c #3C67A0", -"J c #3A659E", -"K c #38629C", -"L c #35609A", -"M c #527FB4", -"N c #132339", -"O c #1E3047", -"P c #537AA5", -"Q c #3B669F", -"R c #39649D", -"S c #638EBD", -"T c #4E739B", -"U c #4E729B", -"V c #4D729A", -"W c #4C729A", -"X c #4C7199", -"Y c #101F32", -"Z c #405F85", -"` c #4D78AD", -" . c #2F5A94", -".. c #496C94", -"+. c #2A4663", -"@. c #4E77AB", -"#. c #466B93", -"$. c #1B2F48", -"%. c #2C4563", -" ", -" ", -" . + ", -" @ # $ ", -" % & * $ ", -" = - ; > , ' ) ! ~ { ] ^ / ", -" ( _ : < [ } | 1 2 3 4 5 6 7 ", -" 8 9 } 0 a b c d e f g h i j k ", -" l m n o p q r s t u v w x y z ", -" A B C D E F G H I J K L M N ", -" O P i Q R S T U V V W X Y ", -" Z ` ... ", -" +.@.#. ", -" $.%. ", -" ", -" "}; diff --git a/src/Gui/Icons/button_right.xpm b/src/Gui/Icons/button_right.xpm deleted file mode 100644 index 4c85d5fa9d00..000000000000 --- a/src/Gui/Icons/button_right.xpm +++ /dev/null @@ -1,118 +0,0 @@ -/* XPM */ -static char * button_right_xpm[] = { -"16 16 99 2", -" c None", -". c #37506B", -"+ c #2A4055", -"@ c #567BA1", -"# c #6D98C6", -"$ c #39516D", -"% c #557AA0", -"& c #6995C7", -"* c #6996C6", -"= c #4B6C92", -"- c #1C2B3E", -"; c #53759A", -"> c #51759A", -", c #51749A", -"' c #507499", -") c #507399", -"! c #507298", -"~ c #6893C1", -"{ c #5F8CBF", -"] c #5D89BC", -"^ c #608DC0", -"/ c #577EA8", -"( c #213145", -"_ c #1E3043", -": c #6D9BCB", -"< c #6693C5", -"[ c #6490C2", -"} c #618DC0", -"| c #5E8ABD", -"1 c #5B87BB", -"2 c #5985B9", -"3 c #5682B6", -"4 c #537FB4", -"5 c #507CB1", -"6 c #527DB2", -"7 c #5D87B6", -"8 c #28405A", -"9 c #1D2E41", -"0 c #6996C7", -"a c #5A86BA", -"b c #5783B8", -"c c #5580B5", -"d c #527EB3", -"e c #4F7BB0", -"f c #4C78AE", -"g c #4A75AC", -"h c #4772A9", -"i c #446FA7", -"j c #426EA5", -"k c #5682B4", -"l c #375273", -"m c #1B2B40", -"n c #6491C3", -"o c #517CB2", -"p c #4E7AAF", -"q c #4B77AD", -"r c #4874AA", -"s c #4671A8", -"t c #436EA6", -"u c #406BA3", -"v c #3D68A1", -"w c #3B669E", -"x c #39639D", -"y c #507BAE", -"z c #3B587C", -"A c #1A293E", -"B c #4773A9", -"C c #4470A7", -"D c #426DA5", -"E c #3F6AA2", -"F c #3C67A0", -"G c #39649D", -"H c #37619B", -"I c #345F98", -"J c #35619A", -"K c #527AAD", -"L c #283F5C", -"M c #152438", -"N c #50769E", -"O c #50759E", -"P c #50759C", -"Q c #4F749C", -"R c #4F749B", -"S c #4E739B", -"T c #628DBC", -"U c #305A95", -"V c #2D5893", -"W c #3A659D", -"X c #4E75A0", -"Y c #1B2D46", -"Z c #476C94", -"` c #26518D", -" . c #426CA3", -".. c #41638D", -"+. c #466A92", -"@. c #4C76A9", -"#. c #294463", -"$. c #2C4664", -"%. c #1B2F4A", -" ", -" ", -" . + ", -" @ # $ ", -" % & * = ", -"- ; > , ' ) ! ~ { ] ^ / ( ", -"_ : < [ } | 1 2 3 4 5 6 7 8 ", -"9 0 ] a b c d e f g h i j k l ", -"m n 4 o p q r s t u v w x y z ", -"A { g B C D E F G H I J K L ", -"M N O P Q R S T U V W X Y ", -" Z ` ... ", -" +.@.#. ", -" $.%. ", -" ", -" "}; diff --git a/src/Gui/Icons/button_up.xpm b/src/Gui/Icons/button_up.xpm deleted file mode 100644 index a1030160d44b..000000000000 --- a/src/Gui/Icons/button_up.xpm +++ /dev/null @@ -1,112 +0,0 @@ -/* XPM */ -static char * button_up_xpm[] = { -"16 16 93 2", -" c None", -". c #415E7E", -"+ c #476587", -"@ c #2E475D", -"# c #6D9AC8", -"$ c #6E99C7", -"% c #354F6A", -"& c #223448", -"* c #6792BE", -"= c #6B98C9", -"- c #6A97C8", -"; c #6691BF", -"> c #273D50", -", c #5C83AD", -"' c #6894C5", -") c #6591C3", -"! c #6490C2", -"~ c #6390C2", -"{ c #5D85B0", -"] c #4A6B8E", -"^ c #6692C4", -"/ c #608CBF", -"( c #5E8BBE", -"_ c #5D89BD", -": c #5C88BC", -"< c #4A6B8F", -"[ c #324C69", -"} c #6490C1", -"| c #5B87BA", -"1 c #5985B9", -"2 c #5884B8", -"3 c #5783B7", -"4 c #5682B6", -"5 c #5480B5", -"6 c #5E8BBC", -"7 c #364F6E", -"8 c #24374E", -"9 c #618DBC", -"0 c #5581B6", -"a c #537FB4", -"b c #527EB3", -"c c #517CB2", -"d c #4F7BB1", -"e c #4E7AB0", -"f c #4D79AE", -"g c #5D88B9", -"h c #253B53", -"i c #36506D", -"j c #5479A1", -"k c #5478A0", -"l c #6792C0", -"m c #4D78AE", -"n c #4C77AD", -"o c #4A76AC", -"p c #4975AB", -"q c #6590BF", -"r c #51779F", -"s c #51769F", -"t c #35506E", -"u c #4E729A", -"v c #4672A9", -"w c #4571A8", -"x c #446FA7", -"y c #436EA5", -"z c #4D7199", -"A c #406BA3", -"B c #3F6AA2", -"C c #3E69A1", -"D c #3C67A0", -"E c #4C6F98", -"F c #3A659E", -"G c #39639D", -"H c #37629B", -"I c #36619A", -"J c #4B6E96", -"K c #335E98", -"L c #325D97", -"M c #315C96", -"N c #305A95", -"O c #496D95", -"P c #2D5893", -"Q c #2C5691", -"R c #2B5590", -"S c #29548F", -"T c #476C94", -"U c #476B94", -"V c #4A75AC", -"W c #4975AC", -"X c #4874AB", -"Y c #4873AB", -"Z c #466A93", -"` c #0F1E32", -" . c #0F1E35", -" ", -" . + ", -" @ # $ % ", -" & * = - ; > ", -" , ' ) ! ~ { ", -" ] ^ / ( _ : / < ", -" [ } | 1 2 3 4 5 6 7 ", -" 8 9 0 5 a b c d e f g h ", -" i j k l m n o p q r s t ", -" u v w x y z ", -" z A B C D E ", -" E F G H I J ", -" J K L M N O ", -" O P Q R S T ", -" U V W X Y Z ", -" ` . . . .` "}; diff --git a/src/Gui/Icons/freecad.xpm b/src/Gui/Icons/freecad.xpm deleted file mode 100644 index d2334e921942..000000000000 --- a/src/Gui/Icons/freecad.xpm +++ /dev/null @@ -1,67 +0,0 @@ -/* XPM */ -static char *b2877f70bb2b4697e4de66cf1b8d3a67GbKalYwBddLgmyqY[] = { -/* columns rows colors chars-per-pixel */ -"32 32 29 1 ", -" c None", -". c #CB333B", -"X c #CB343C", -"o c #CF353E", -"O c #DC3F47", -"+ c #FC555B", -"@ c #FE575E", -"# c #FF585D", -"$ c #C06B88", -"% c #7480BB", -"& c #418FDD", -"* c #428FDD", -"= c #418EDE", -"- c #418FDE", -"; c #418EDF", -": c #418FDF", -"> c #428FDE", -", c #4190DE", -"< c #4290DE", -"1 c #73ADE6", -"2 c #7FABE0", -"3 c #93BFED", -"4 c #CBE0F4", -"5 c #F6E2E3", -"6 c #F7E3E4", -"7 c #FEE7E7", -"8 c #E3EEF9", -"9 c #F2F7FB", -"0 c #FEFEFE", -/* pixels */ -" X...............O##### ", -" X...............O###### ", -" X...............O####### ", -" X...............O######## ", -" X...............O######### ", -" .....5555555555677777####@ ", -" .....0000000000000000###@% ", -" .....0000000000000000##@%- ", -" .....0000000000000000#@%-- ", -" .....0000000000000000@%--- ", -" .....0000098888888888%---- ", -" .....000003--------------- ", -" .....000003-------------- ", -" .....000003------------ ", -" .....00000433331------- ", -" .....00000000008------- ", -" .....00000000008-------- ", -" .....00000000008--------- ", -" .....00000000008---------- ", -" .....00000000008---------- ", -" .....000003-------------- ", -" ....o000003-------------, ", -" ...o+000003--------- ", -" ..o+#000003--------- ", -" .o+##000003--------, ", -" o+###000003--------- ", -" +####777772---------, ", -" #########$----------, ", -" ########$--- --- ", -" #######$---- - ", -" ######$----- ", -" #####$----- " -}; diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc index 34bd914d37df..0cc5702e6f68 100644 --- a/src/Gui/Icons/resource.qrc +++ b/src/Gui/Icons/resource.qrc @@ -272,9 +272,6 @@ LinkArrayOverlay.svg LinkSubOverlay.svg LinkSubElement.svg - LinkArrayOverlay.xpm - LinkSubOverlay.xpm - LinkSubElement.xpm LinkSub.svg LinkReplace.svg LinkImport.svg From cafefafdf137c1e05b475ea0b8be3dea505f0ecd Mon Sep 17 00:00:00 2001 From: Max Wilfinger Date: Fri, 22 Nov 2024 07:58:51 +0100 Subject: [PATCH 146/161] replaced .xpm with .svg --- src/Tools/plugins/widget/customwidgets.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp index 36c829add39a..24028a5228ee 100644 --- a/src/Tools/plugins/widget/customwidgets.cpp +++ b/src/Tools/plugins/widget/customwidgets.cpp @@ -371,7 +371,7 @@ ActionSelector::ActionSelector(QWidget* parent) addButton = new QPushButton(this); addButton->setMinimumSize(QSize(30, 30)); QIcon icon; - icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), QSize(), QIcon::Normal, QIcon::Off); + icon.addFile(QString::fromUtf8(":/icons/button_right.svg"), QSize(), QIcon::Normal, QIcon::Off); addButton->setIcon(icon); gridLayout = new QGridLayout(this); gridLayout->addWidget(addButton, 1, 1, 1, 1); @@ -384,7 +384,7 @@ ActionSelector::ActionSelector(QWidget* parent) removeButton = new QPushButton(this); removeButton->setMinimumSize(QSize(30, 30)); QIcon icon1; - icon1.addFile(QString::fromUtf8(":/icons/button_left.xpm"), QSize(), QIcon::Normal, QIcon::Off); + icon1.addFile(QString::fromUtf8(":/icons/button_left.svg"), QSize(), QIcon::Normal, QIcon::Off); removeButton->setIcon(icon1); removeButton->setAutoDefault(true); removeButton->setDefault(false); @@ -394,7 +394,7 @@ ActionSelector::ActionSelector(QWidget* parent) upButton = new QPushButton(this); upButton->setMinimumSize(QSize(30, 30)); QIcon icon3; - icon3.addFile(QString::fromUtf8(":/icons/button_up.xpm"), QSize(), QIcon::Normal, QIcon::Off); + icon3.addFile(QString::fromUtf8(":/icons/button_up.svg"), QSize(), QIcon::Normal, QIcon::Off); upButton->setIcon(icon3); gridLayout->addWidget(upButton, 3, 1, 1, 1); @@ -402,7 +402,7 @@ ActionSelector::ActionSelector(QWidget* parent) downButton = new QPushButton(this); downButton->setMinimumSize(QSize(30, 30)); QIcon icon2; - icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); + icon2.addFile(QString::fromUtf8(":/icons/button_down.svg"), QSize(), QIcon::Normal, QIcon::Off); downButton->setIcon(icon2); downButton->setAutoDefault(true); From 7c15b3d2409e6e0a1685aa16fbc1e7b1cd7b0f01 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Fri, 29 Nov 2024 18:12:48 +0100 Subject: [PATCH 147/161] Sketcher: OVP were drawn at wrong position when editing a sketch from link (#18060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Sketcher: OVP were drawn at wrong position when editing a sketch from a link. * Update src/Mod/Sketcher/Gui/DrawSketchController.h Co-authored-by: Adrián Insaurralde Avalos <36372335+adrianinsaval@users.noreply.github.com> --------- Co-authored-by: Adrián Insaurralde Avalos <36372335+adrianinsaval@users.noreply.github.com> --- src/Mod/Sketcher/Gui/DrawSketchController.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchController.h b/src/Mod/Sketcher/Gui/DrawSketchController.h index 714a6bda879d..819e8ebf0e0e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchController.h @@ -583,7 +583,9 @@ class DrawSketchController void initNOnViewParameters(int n) { Gui::View3DInventorViewer* viewer = handler->getViewer(); - Base::Placement placement = handler->sketchgui->getSketchObject()->globalPlacement(); + + auto doc = Gui::Application::Instance->editDocument(); + auto placement = Base::Placement(doc->getEditingTransform()); onViewParameters.clear(); From 1ef62a1de82af3a89d5441d0e4e41130644787f8 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 19 Nov 2024 17:52:34 -0500 Subject: [PATCH 148/161] [TD]add preference for auto workbench switch --- src/Mod/TechDraw/App/Preferences.cpp | 5 + src/Mod/TechDraw/App/Preferences.h | 2 + .../TechDraw/Gui/DlgPrefsTechDrawAdvanced.ui | 379 +++++++++--------- .../Gui/DlgPrefsTechDrawAdvancedImp.cpp | 4 + 4 files changed, 210 insertions(+), 180 deletions(-) diff --git a/src/Mod/TechDraw/App/Preferences.cpp b/src/Mod/TechDraw/App/Preferences.cpp index 56cf903583b4..8db68f852b1c 100644 --- a/src/Mod/TechDraw/App/Preferences.cpp +++ b/src/Mod/TechDraw/App/Preferences.cpp @@ -651,3 +651,8 @@ void Preferences::setBalloonDragModifiers(Qt::KeyboardModifiers newModifiers) } +//! if true, automatically switch to TD workbench when a Page is set in edit (double click) +bool Preferences::switchOnClick() +{ + return getPreferenceGroup("General")->GetBool("SwitchToWB", true); +} diff --git a/src/Mod/TechDraw/App/Preferences.h b/src/Mod/TechDraw/App/Preferences.h index 0d694bfd2c70..03558f052232 100644 --- a/src/Mod/TechDraw/App/Preferences.h +++ b/src/Mod/TechDraw/App/Preferences.h @@ -150,6 +150,8 @@ class TechDrawExport Preferences static Qt::KeyboardModifiers balloonDragModifiers(); static void setBalloonDragModifiers(Qt::KeyboardModifiers newModifiers); + + static bool switchOnClick(); }; diff --git a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvanced.ui b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvanced.ui index c5b74fc30049..2594f96f3100 100644 --- a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvanced.ui +++ b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvanced.ui @@ -28,35 +28,20 @@ - - - - - 0 - 0 - - + + true - - Perform a fuse operation on input shape(s) before Section view processing - - Fuse Before Section - - - SectionFuseFirst - - - Mod/TechDraw/General + Overlap Edges Scrub Passes - - + + 0 @@ -64,21 +49,51 @@ - Dump intermediate results during Section view processing + Include edges with unexpected geometry (zero length etc.) in results - Debug Section + Allow Crazy Edges - debugSection + allowCrazyEdge Mod/TechDraw/debug - - + + + + Limit of 64x64 pixel SVG tiles used to hatch a single face. +For large scalings you might get an error about too many SVG tiles. +Then you need to increase the tile limit. + + + Qt::AlignmentFlag::AlignRight + + + 1 + + + 1000000 + + + 100 + + + 10000 + + + MaxSVGTile + + + Mod/TechDraw/Decorations + + + + + 0 @@ -92,35 +107,28 @@ - Size of selection area around edges + Selection area around center marks Each unit is approx. 0.1 mm wide - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter - 10.000000000000000 + 5.000000000000000 - EdgeFuzz + MarkFuzz Mod/TechDraw/General - - - - Edge Fuzz - - - - - + + 0 @@ -128,59 +136,42 @@ Each unit is approx. 0.1 mm wide - Include edges with unexpected geometry (zero length etc.) in results + Dump intermediate results during Section view processing - Allow Crazy Edges + Debug Section - allowCrazyEdge + debugSection Mod/TechDraw/debug - - + + - Maximum hatch line segments to use -when hatching a face with a PAT pattern - - - Qt::AlignRight - - - 1 - - - 1000000 + If checked, FreeCAD will use the new face finder algorithm. If not checked, FreeCAD will use the original face finder. - - 100 + + Use New Face Finder Algorithm - - 10000 + + true - MaxSeg + NewFaceFinder - Mod/TechDraw/PAT - - - - - - - Mark Fuzz + Mod/TechDraw/General - + - Qt::Horizontal + Qt::Orientation::Horizontal @@ -190,57 +181,76 @@ when hatching a face with a PAT pattern - - + + + + Max SVG Hatch Tiles + + + + + + + Issue progress messages while building View geometry + + + Report Progress + + + ReportProgress + + + /Mod/TechDraw/General + + + + + + + Edge Fuzz + + + + + + + Mark Fuzz + + + + + 0 0 - - - 174 - 0 - - - Selection area around center marks -Each unit is approx. 0.1 mm wide - - - + Highlights border of section cut in section views - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + Show Section Edges - - 5.000000000000000 + + true - MarkFuzz + ShowSectionEdges - Mod/TechDraw/General - - - - - - - Max SVG Hatch Tiles + /Mod/TechDraw/General - - + + - Limit of 64x64 pixel SVG tiles used to hatch a single face. -For large scalings you might get an error about too many SVG tiles. -Then you need to increase the tile limit. + Maximum hatch line segments to use +when hatching a face with a PAT pattern - Qt::AlignRight + Qt::AlignmentFlag::AlignRight 1 @@ -255,114 +265,119 @@ Then you need to increase the tile limit. 10000 - MaxSVGTile + MaxSeg - Mod/TechDraw/Decorations + Mod/TechDraw/PAT - - - - - 0 - 0 - - + + - Dump intermediate results during Detail view processing + If checked, system will attempt to automatically correct dimension references when the model changes. + + + - Debug Detail + Auto Correct Dimension Refs + + + true - debugDetail + AutoCorrectRefs - Mod/TechDraw/debug + Mod/TechDraw/Dimensions - - + + 0 0 + + + 174 + 0 + + - Highlights border of section cut in section views + Size of selection area around edges +Each unit is approx. 0.1 mm wide - - Show Section Edges + + - - true + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + 10.000000000000000 - ShowSectionEdges + EdgeFuzz - /Mod/TechDraw/General + Mod/TechDraw/General - - - - Issue progress messages while building View geometry - - - Report Progress - - - ReportProgress + + + + + 0 + 0 + - - /Mod/TechDraw/General + + + true + - - - - - If checked, FreeCAD will use the new face finder algorithm. If not checked, FreeCAD will use the original face finder. + Perform a fuse operation on input shape(s) before Section view processing - Use New Face Finder Algorithm - - - true + Fuse Before Section - NewFaceFinder + SectionFuseFirst Mod/TechDraw/General - - + + - If checked, system will attempt to automatically correct dimension references when the model changes. + The number of times FreeCAD should try to remove overlapping edges returned by the Hidden Line Removal algorithm. A value of 0 indicates no scrubbing, 1 indicates a single pass and 2 indicates a second pass should be performed. Values above 2 are generally not productive. Each pass adds to the time required to produce the drawing. - + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + - - Auto Correct Dimension Refs + + - - true + + 1 - AutoCorrectRefs + ScrubCount - Mod/TechDraw/Dimensions + Mod/TechDraw/General @@ -394,44 +409,48 @@ can be a performance penalty in complex models. - - - - - true - + + + + + 0 + 0 + + + + Dump intermediate results during Detail view processing - Overlap Edges Scrub Passes + Debug Detail + + + debugDetail + + + Mod/TechDraw/debug - + Max PAT Hatch Segments - - + + - The number of times FreeCAD should try to remove overlapping edges returned by the Hidden Line Removal algorithm. A value of 0 indicates no scrubbing, 1 indicates a single pass and 2 indicates a second pass should be performed. Values above 2 are generally not productive. Each pass adds to the time required to produce the drawing. - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + If this box is checked, double clicking on a page in the tree will automatically switch to TechDraw and the page will be made visible. - - - - - + + Switch Workbench on Click - - 1 + + true - ScrubCount + SwitchToWB Mod/TechDraw/General @@ -538,7 +557,7 @@ can be a performance penalty in complex models. <html><head/><body><p><span style=" font-weight:600;">Note:</span> Items in <span style=" font-style:italic;">italics</span> are default values for new objects. They have no effect on existing objects.</p></body></html> - Qt::RichText + Qt::TextFormat::RichText true @@ -548,7 +567,7 @@ can be a performance penalty in complex models. - Qt::Vertical + Qt::Orientation::Vertical diff --git a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvancedImp.cpp b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvancedImp.cpp index b686b14aca75..ef987f8e8f3d 100644 --- a/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvancedImp.cpp +++ b/src/Mod/TechDraw/Gui/DlgPrefsTechDrawAdvancedImp.cpp @@ -64,6 +64,8 @@ void DlgPrefsTechDrawAdvancedImp::saveSettings() ui->sbScrubCount->onSave(); saveBalloonOverride(); + + ui->cbSwitchWB->onSave(); } @@ -114,6 +116,8 @@ void DlgPrefsTechDrawAdvancedImp::loadSettings() ui->sbScrubCount->onRestore(); loadBalloonOverride(); + + ui->cbSwitchWB->onRestore(); } void DlgPrefsTechDrawAdvancedImp::loadBalloonOverride() From 2e82c330d473d8137fc80af1ec7fc290e5ce975b Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 19 Nov 2024 17:56:11 -0500 Subject: [PATCH 149/161] [TD]prevent fail on auto switch to hidden tab --- src/Mod/TechDraw/Gui/ViewProviderPage.cpp | 38 +++++++++++++---------- src/Mod/TechDraw/Gui/ViewProviderPage.h | 5 +-- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp index 4a7a26133061..15949599864b 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp @@ -263,20 +263,11 @@ void ViewProviderPage::unsetEdit(int ModNum) bool ViewProviderPage::doubleClicked(void) { - // assure the TechDraw workbench - if (App::GetApplication() - .GetUserParameter() - .GetGroup("BaseApp") - ->GetGroup("Preferences") - ->GetGroup("Mod/TechDraw") - ->GetBool("SwitchToWB", true)) { + if (Preferences::switchOnClick()) { Gui::Command::assureWorkbench("TechDrawWorkbench"); + show(); } - show(); - if (m_mdiView) { - switchToMdiViewPage(); - } return true; } @@ -289,7 +280,7 @@ void ViewProviderPage::show(void) void ViewProviderPage::hide(void) { if (getMDIView()) { - getMDIView()->hide();//this doesn't remove the mdiViewPage from the mainWindow + getMDIView()->hide(); // this doesn't remove the mdiViewPage from the mainWindow removeMDIView(); } ViewProviderDocumentObject::hide(); @@ -339,12 +330,11 @@ void ViewProviderPage::createMDIViewPage() m_mdiView->setWindowTitle(tabTitle + QString::fromLatin1("[*]")); m_mdiView->setWindowIcon(Gui::BitmapFactory().pixmap("TechDraw_TreePage")); Gui::getMainWindow()->addWindow(m_mdiView); - switchToMdiViewPage(); } void ViewProviderPage::switchToMdiViewPage() { - Gui::getMainWindow()->setActiveWindow(m_mdiView); + show(); m_graphicsView->setFocus(); } @@ -407,8 +397,10 @@ std::vector ViewProviderPage::claimChildren(void) const // Collect any child views // for Page, valid children are any View except: DrawViewDimension // DrawViewBalloon - // any FeatuerView in a DrawViewClip + // any FeatureView in a DrawViewClip // DrawHatch + // DrawGeomHatch + // ?? leaders? try { for (auto* obj : getDrawPage()->Views.getValues()) { @@ -422,11 +414,14 @@ std::vector ViewProviderPage::claimChildren(void) const // Don't collect if dimension, balloon, hatch or member of ClipGroup as these should be grouped elsewhere if (obj->isDerivedFrom() || obj->isDerivedFrom() + || obj->isDerivedFrom() || obj->isDerivedFrom() - || (featView && featView->isInClip())) + || (featView && featView->isInClip())) { continue; - else + } + else { temp.push_back(obj); + } } return temp; } @@ -579,3 +574,12 @@ void ViewProviderPage::fixSceneDependencies() } } + +//! convenient way to ask feature to redraw everything +void ViewProviderPage::redrawPage() const +{ + auto feature = getDrawPage(); + if (feature) { + feature->redrawCommand(); + } +} diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.h b/src/Mod/TechDraw/Gui/ViewProviderPage.h index b23d666c5fb7..fe5c9be69761 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.h +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.h @@ -120,8 +120,8 @@ class TechDrawGuiExport ViewProviderPage: public Gui::ViewProviderDocumentObject void setGrid(); - QGSPage* getQGSPage(void) { return m_graphicsScene; } - QGVPage* getQGVPage(void) { return m_graphicsView; } + QGSPage* getQGSPage(void) const { return m_graphicsScene; } + QGVPage* getQGVPage(void) const { return m_graphicsView; } ViewProviderPageExtension* getVPPExtension() const; @@ -129,6 +129,7 @@ class TechDrawGuiExport ViewProviderPage: public Gui::ViewProviderDocumentObject void fixSceneDependencies(); + void redrawPage() const; protected: bool setEdit(int ModNum) override; From 8581cd01e22c65fb45b46e704a57f34b06517642 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 19 Nov 2024 17:58:08 -0500 Subject: [PATCH 150/161] [TD]prevent crash on attempt to print hidden page --- src/Mod/TechDraw/Gui/MDIViewPage.cpp | 138 +++---------- src/Mod/TechDraw/Gui/MDIViewPage.h | 7 - src/Mod/TechDraw/Gui/PagePrinter.cpp | 291 ++++++++++++++------------- src/Mod/TechDraw/Gui/PagePrinter.h | 92 ++++----- 4 files changed, 224 insertions(+), 304 deletions(-) diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index e87c38a5a492..c485671e499c 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -119,14 +119,14 @@ MDIViewPage::MDIViewPage(ViewProviderPage* pageVp, Gui::Document* doc, QWidget* connectDeletedObject = appDoc->signalDeletedObject.connect(bnd); //NOLINTEND - m_pagePrinter = new PagePrinter(m_vpPage); - m_pagePrinter->setOwner(this); + // m_pagePrinter = new PagePrinter(m_vpPage); + // m_pagePrinter->setOwner(this); } MDIViewPage::~MDIViewPage() { connectDeletedObject.disconnect(); - delete m_pagePrinter; + // delete m_pagePrinter; } void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) @@ -134,9 +134,9 @@ void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) m_scene = scene; setCentralWidget(viewWidget);//this makes viewWidget a Qt child of MDIViewPage QObject::connect(scene, &QGSPage::selectionChanged, this, &MDIViewPage::sceneSelectionChanged); - if (m_pagePrinter) { - m_pagePrinter->setScene(m_scene); - } + // if (m_pagePrinter) { + // m_pagePrinter->setScene(m_scene); + // } } void MDIViewPage::setDocumentObject(const std::string& name) @@ -309,35 +309,6 @@ void MDIViewPage::fixSceneDependencies() /// as file name selection and error messages /// PagePrinter handles the actual printing mechanics. -/// save the page state so it can be restore after printing -void MDIViewPage::savePageExportState(ViewProviderPage* page) -{ - auto guiDoc = page->getDocument(); - if (!guiDoc) { - return; - } - m_docModStateBeforePrint = guiDoc->isModified(); -} -/// ensure that the page reverts to its normal state after any changes made for printing. -void MDIViewPage::resetPageExportState(ViewProviderPage* page) const -{ - auto pageFeature = page->getDrawPage(); - if (!pageFeature) { - // how did this happen? - return; - } - - auto guiDoc = page->getDocument(); - if (!guiDoc) { - return; - } - auto scene = page->getQGSPage(); - scene->setExportingPdf(false); - scene->setExportingSvg(false); - guiDoc->setModified(m_docModStateBeforePrint); - pageFeature->redrawCommand(); -} - /// overrides of MDIView print methods so that they print the QGraphicsScene instead /// of the COIN3d scenegraph. @@ -354,72 +325,46 @@ void MDIViewPage::printPdf() } Gui::WaitCursor wc; - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - - savePageExportState(vpp); std::string utf8Content = fn.toUtf8().constData(); - if (m_pagePrinter) { - m_pagePrinter->printPdf(utf8Content); - resetPageExportState(vpp); - } + PagePrinter::printPdf(getViewProviderPage(), utf8Content); } void MDIViewPage::print() { - if (!m_pagePrinter) { - return; - } - - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - - savePageExportState(vpp); - - m_pagePrinter->getPaperAttributes(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); QPrinter printer(QPrinter::HighResolution); printer.setFullPage(true); - if (m_pagePrinter->getPaperSize() == QPageSize::Custom) { - printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter)); + if (pageAttr.pageSize() == QPageSize::Custom) { + printer.setPageSize( + QPageSize(QSizeF(pageAttr.pageWidth(), pageAttr.pageHeight()), QPageSize::Millimeter)); } else { - printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize())); + printer.setPageSize(QPageSize(pageAttr.pageSize())); } - printer.setPageOrientation(m_pagePrinter->getOrientation()); + printer.setPageOrientation(pageAttr.orientation()); QPrintDialog dlg(&printer, this); if (dlg.exec() == QDialog::Accepted) { print(&printer); - resetPageExportState(vpp); } } void MDIViewPage::printPreview() { -// Base::Console().Message("MDIVP::printPreview()\n"); - - if (!m_pagePrinter) { - return; - } - m_pagePrinter->getPaperAttributes(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); QPrinter printer(QPrinter::HighResolution); printer.setFullPage(true); - if (m_pagePrinter->getPaperSize() == QPageSize::Custom) { - printer.setPageSize(QPageSize(QSizeF(m_pagePrinter->getPageWidth(), m_pagePrinter->getPageHeight()), QPageSize::Millimeter)); + if (pageAttr.pageSize() == QPageSize::Custom) { + printer.setPageSize( + QPageSize(QSizeF(pageAttr.pageWidth(), pageAttr.pageHeight()), QPageSize::Millimeter)); } else { - printer.setPageSize(QPageSize(m_pagePrinter->getPaperSize())); + printer.setPageSize(QPageSize(pageAttr.pageSize())); } - printer.setPageOrientation(m_pagePrinter->getOrientation()); + printer.setPageOrientation(pageAttr.orientation()); QPrintPreviewDialog dlg(&printer, this); connect(&dlg, &QPrintPreviewDialog::paintRequested, this, qOverload(&MDIViewPage::print)); @@ -429,18 +374,6 @@ void MDIViewPage::printPreview() void MDIViewPage::print(QPrinter* printer) { - // Base::Console().Message("MDIVP::print(printer)\n"); - if (!m_pagePrinter) { - return; - } - auto vpp = getViewProviderPage(); - if (!vpp) { - // how did this happen? - return; - } - savePageExportState(vpp); - - m_pagePrinter->getPaperAttributes(); // As size of the render area paperRect() should be used. When performing a real // print pageRect() may also work but the output is cropped at the bottom part. // So, independent whether pageRect() or paperRect() is used there is no scaling effect. @@ -452,7 +385,9 @@ void MDIViewPage::print(QPrinter* printer) // // When showing the preview of a print paperRect() must be used because with pageRect() // a certain scaling effect can be observed and the content becomes smaller. + QPaintEngine::Type paintType = printer->paintEngine()->type(); + auto pageAttr = PagePrinter::getPaperAttributes(getViewProviderPage()); if (printer->outputFormat() == QPrinter::NativeFormat) { QPageSize::PageSizeId psPrtSetting = printer->pageLayout().pageSize().id(); @@ -460,7 +395,7 @@ void MDIViewPage::print(QPrinter* printer) // care if it uses wrong printer settings bool doPrint = paintType != QPaintEngine::Picture; - if (doPrint && printer->pageLayout().orientation() != m_pagePrinter->getOrientation()) { + if (doPrint && printer->pageLayout().orientation() != pageAttr.orientation()) { int ret = QMessageBox::warning( this, tr("Different orientation"), tr("The printer uses a different orientation than the drawing.\n" @@ -470,7 +405,7 @@ void MDIViewPage::print(QPrinter* printer) return; } } - if (doPrint && psPrtSetting != m_pagePrinter->getPaperSize()) { + if (doPrint && psPrtSetting != pageAttr.pageSize()) { int ret = QMessageBox::warning( this, tr("Different paper size"), tr("The printer uses a different paper size than the drawing.\n" @@ -482,17 +417,12 @@ void MDIViewPage::print(QPrinter* printer) } } - if (m_pagePrinter) { - m_pagePrinter->print(printer); - resetPageExportState(vpp); - } - + PagePrinter::print(getViewProviderPage(), printer); } //static routine to print all pages in a document void MDIViewPage::printAll(QPrinter* printer, App::Document* doc) { - // Base::Console().Message("MDIVP::printAll()\n"); PagePrinter::printAll(printer, doc); } @@ -538,14 +468,9 @@ void MDIViewPage::saveSVG(std::string filename) { auto vpp = getViewProviderPage(); if (!vpp) { - // how did this happen? return; } - savePageExportState(vpp); - if (m_pagePrinter) { - m_pagePrinter->saveSVG(filename); - resetPageExportState(vpp); - } + PagePrinter::saveSVG(vpp, filename); } @@ -567,9 +492,7 @@ void MDIViewPage::saveSVG() void MDIViewPage::saveDXF(std::string filename) { - if (m_pagePrinter) { - m_pagePrinter->saveDXF(filename); - } + PagePrinter::saveDXF(getViewProviderPage(), filename); } void MDIViewPage::saveDXF() @@ -590,14 +513,9 @@ void MDIViewPage::savePDF(std::string filename) { auto vpp = getViewProviderPage(); if (!vpp) { - // how did this happen? return; } - savePageExportState(vpp); - if (m_pagePrinter) { - m_pagePrinter->savePDF(filename); - resetPageExportState(vpp); - } + PagePrinter::savePDF(vpp, filename); } void MDIViewPage::savePDF() @@ -614,7 +532,7 @@ void MDIViewPage::savePDF() savePDF(sFileName); } -/// a slot for printing all the pages +/// a slot for printing all the pages. just redirects to printAllPages void MDIViewPage::printAll() { MDIViewPage::printAllPages(); diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.h b/src/Mod/TechDraw/Gui/MDIViewPage.h index 67f90b8726b9..404347d12caa 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.h +++ b/src/Mod/TechDraw/Gui/MDIViewPage.h @@ -100,8 +100,6 @@ class TechDrawGuiExport MDIViewPage : public Gui::MDIView, public Gui::Selection PyObject* getPyObject() override; TechDraw::DrawPage * getPage() { return m_vpPage->getDrawPage(); } ViewProviderPage* getViewProviderPage() {return m_vpPage;} - void savePageExportState(ViewProviderPage* page); - void resetPageExportState(ViewProviderPage* page) const; void setTabText(std::string tabText); @@ -159,11 +157,6 @@ public Q_SLOTS: QList m_orderedSceneSelection; //items in selection order - void getPaperAttributes(); - PagePrinter* m_pagePrinter; - - bool m_docModStateBeforePrint{false}; - }; class MDIViewPagePy : public Py::PythonExtension diff --git a/src/Mod/TechDraw/Gui/PagePrinter.cpp b/src/Mod/TechDraw/Gui/PagePrinter.cpp index 33ea9b97b8c0..43ce9c894275 100644 --- a/src/Mod/TechDraw/Gui/PagePrinter.cpp +++ b/src/Mod/TechDraw/Gui/PagePrinter.cpp @@ -56,7 +56,6 @@ #include "QGSPage.h" #include "Rez.h" #include "ViewProviderPage.h" -#include "MDIViewPage.h" using namespace TechDrawGui; using namespace TechDraw; @@ -71,19 +70,6 @@ constexpr double mmPerInch = 25.4; //TYPESYSTEM_SOURCE_ABSTRACT(TechDrawGui::PagePrinter) -PagePrinter::PagePrinter(ViewProviderPage* pageVp) - : m_vpPage(pageVp), m_orientation(QPageLayout::Landscape), - m_paperSize(QPageSize::A4), m_pagewidth(0.0), m_pageheight(0.0) -{ -} - -void PagePrinter::setScene(QGSPage* scene) -{ - m_scene = scene; -} - -void PagePrinter::setDocumentName(const std::string& name) { m_documentName = name; } - //! retrieve the attributes of a DrawPage and its Template PaperAttributes PagePrinter::getPaperAttributes(TechDraw::DrawPage* dPage) @@ -99,144 +85,78 @@ PaperAttributes PagePrinter::getPaperAttributes(TechDraw::DrawPage* dPage) width = pageTemplate->Width.getValue(); height = pageTemplate->Height.getValue(); } - result.pagewidth = width; - result.pageheight = height; + // result.m_pagewidth = width; + // result.m_pageheight = height; //Qt's page size determination assumes Portrait orientation. To get the right paper size //we need to ask in the proper form. QPageSize::PageSizeId paperSizeID = QPageSize::id(QSizeF(std::min(width, height), std::max(width, height)), QPageSize::Millimeter, QPageSize::FuzzyOrientationMatch); - result.paperSize = paperSizeID; + auto paperSize = paperSizeID; - result.orientation = (QPageLayout::Orientation)dPage->getOrientation(); - if (result.paperSize == QPageSize::Ledger) { + auto orientation = (QPageLayout::Orientation)dPage->getOrientation(); + if (paperSize == QPageSize::Ledger) { // Ledger size paper orientation is reversed inside Qt - result.orientation =(QPageLayout::Orientation)(1 - result.orientation); + orientation = (QPageLayout::Orientation)(1 - orientation); } - return result; + return {orientation, paperSize, width, height}; } -void PagePrinter::getPaperAttributes() +//! retrieve the attributes of a DrawPage by its viewProvider +PaperAttributes PagePrinter::getPaperAttributes(ViewProviderPage* vpPage) { - PaperAttributes attr = getPaperAttributes(m_vpPage->getDrawPage()); - m_pagewidth = attr.pagewidth; - m_pageheight = attr.pageheight; - m_paperSize = attr.paperSize; - m_orientation = attr.orientation; + auto page = vpPage->getDrawPage(); + return getPaperAttributes(page); } + //! construct a page layout object that reflects the characteristics of a DrawPage -//static void PagePrinter::makePageLayout(TechDraw::DrawPage* dPage, QPageLayout& pageLayout, double& width, double& height) { PaperAttributes attr = getPaperAttributes(dPage); - width = attr.pagewidth; - height = attr.pageheight; - pageLayout.setPageSize(QPageSize(attr.paperSize)); - pageLayout.setOrientation(attr.orientation); + width = attr.pageWidth(); + height = attr.pageHeight(); + pageLayout.setPageSize(QPageSize(attr.pageSize())); + pageLayout.setOrientation(attr.orientation()); pageLayout.setMode(QPageLayout::FullPageMode); pageLayout.setMargins(QMarginsF()); } -/// print the Page associated with the parent MDIViewPage as a Pdf file -void PagePrinter::printPdf(std::string file) -{ - // Base::Console().Message("PP::printPdf(%s)\n", file.c_str()); - if (file.empty()) { - Base::Console().Warning("PagePrinter - no file specified\n"); - return; - } - - // set up the pdfwriter - auto filespec = Base::Tools::escapeEncodeFilename(file); - filespec = DU::cleanFilespecBackslash(filespec); - QString outputFile = Base::Tools::fromStdString(filespec); - QPdfWriter pdfWriter(outputFile); - QPageLayout pageLayout = pdfWriter.pageLayout(); - auto marginsdb = pageLayout.margins(QPageLayout::Millimeter); - QString documentName = QString::fromUtf8(m_vpPage->getDrawPage()->getNameInDocument()); - pdfWriter.setTitle(documentName); - // default pdfWriter dpi is 1200. - - // set up the page layout - auto dPage = m_vpPage->getDrawPage(); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 - double height = A4Widthmm; - makePageLayout(dPage, pageLayout, width, height); - pdfWriter.setPageLayout(pageLayout); - marginsdb = pageLayout.margins(QPageLayout::Millimeter); - - // first page does not respect page layout unless painter is created after - // pdfWriter layout is established. - QPainter painter(&pdfWriter); - - // render the page - m_scene->setExportingPdf(true); - QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); - double dpmm = pdfWriter.resolution() / mmPerInch; - int twide = int(std::round(width * dpmm)); - int thigh = int(std::round(height * dpmm)); - QRect targetRect(0, 0, twide, thigh); - renderPage(m_vpPage, painter, sourceRect, targetRect); - m_scene->setExportingPdf(false); -} - - -/// print the Page associated with the parent MDIViewPage -void PagePrinter::print(QPrinter* printer) -{ -// Base::Console().Message("PP::print(printer)\n"); - QPageLayout pageLayout = printer->pageLayout(); - - TechDraw::DrawPage* dp = m_vpPage->getDrawPage(); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 - double height = A4Widthmm; - makePageLayout(dp, pageLayout, width, height); - printer->setPageLayout(pageLayout); - QPainter painter(printer); - - QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); - QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); - renderPage(m_vpPage, painter, sourceRect, targetRect); -} - -//static routine to print all pages in a document +//! print all pages in a document void PagePrinter::printAll(QPrinter* printer, App::Document* doc) { - Base::Console().Message("PP::printAll()\n"); - QPageLayout pageLayout = printer->pageLayout(); std::vector docObjs = doc->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); auto firstPage = docObjs.front(); auto dPage = static_cast(firstPage); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 + double width = A4Heightmm; // default to A4 Landscape 297 x 210 double height = A4Widthmm; makePageLayout(dPage, pageLayout, width, height); printer->setPageLayout(pageLayout); QPainter painter(printer); + auto ourDoc = Gui::Application::Instance->getDocument(doc); + auto docModifiedState = ourDoc->isModified(); + bool firstTime = true; for (auto& obj : docObjs) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj); if (!vp) { - continue;// can't print this one + continue; // can't print this one } auto* vpp = dynamic_cast(vp); if (!vpp) { - continue;// can't print this one + continue; // can't print this one } - // is there always a mdi when printAll is called? - auto mdi = vpp->getMDIViewPage(); - mdi->savePageExportState(vpp); auto dPage = static_cast(obj); - double width = A4Heightmm;//default to A4 Landscape 297 x 210 + double width = A4Heightmm; // default to A4 Landscape 297 x 210 double height = A4Widthmm; makePageLayout(dPage, pageLayout, width, height); printer->setPageLayout(pageLayout); @@ -247,25 +167,27 @@ void PagePrinter::printAll(QPrinter* printer, App::Document* doc) firstTime = false; QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); - renderPage(vpp, painter, sourceRect, targetRect); - mdi->resetPageExportState(vpp); + dPage->redrawCommand(); } + + ourDoc->setModified(docModifiedState); } -//static routine to print all pages in a document to pdf +//! print all pages in a document to pdf void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) { - // Base::Console().Message("PP::printAllPdf()\n"); double dpmm = printer->resolution() / mmPerInch; QString outputFile = printer->outputFileName(); QString documentName = QString::fromUtf8(doc->getName()); QPdfWriter pdfWriter(outputFile); - // setPdfVersion sets the printed PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/ - // but this is not working as of Qt 5.12 - //printer->setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); - //pdfWriter.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + + // setPdfVersion sets the printed PDF Version to comply with PDF/A-1b, more details under: + // https://www.kdab.com/creating-pdfa-documents-qt/ but this is not working as of Qt 5.12 + // printer->setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + // pdfWriter.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); + pdfWriter.setTitle(documentName); pdfWriter.setResolution(printer->resolution()); QPageLayout pageLayout = printer->pageLayout(); @@ -285,6 +207,9 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) // start() or end() until all the pages are printed. QPainter painter(&pdfWriter); + auto ourDoc = Gui::Application::Instance->getDocument(doc); + auto docModifiedState = ourDoc->isModified(); + bool firstTime = true; for (auto& obj : docObjs) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj); @@ -295,12 +220,9 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) if (!vpp) { continue;// can't print this one } - // is there always a mdi when printAll is called? - auto mdi = vpp->getMDIViewPage(); - mdi->savePageExportState(vpp); - auto scene = vpp->getQGSPage(); - scene->setExportingPdf(true); + auto ourScene = vpp->getQGSPage(); + ourScene->setExportingPdf(true); auto dPage = static_cast(obj); double width{0}; @@ -315,13 +237,16 @@ void PagePrinter::printAllPdf(QPrinter* printer, App::Document* doc) QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); QRect targetRect(0, 0, width * dpmm, height * dpmm); renderPage(vpp, painter, sourceRect, targetRect); - mdi->resetPageExportState(vpp); + dPage->redrawCommand(); + ourScene->setExportingPdf(true); } + + ourDoc->setModified(docModifiedState); } -//static -//! we don't need the banner page any more + +//! we don't need the banner page any more, but it might become useful again in the future. void PagePrinter::printBannerPage(QPrinter* printer, QPainter& painter, QPageLayout& pageLayout, App::Document* doc, std::vector& docObjs) { @@ -353,11 +278,10 @@ void PagePrinter::printBannerPage(QPrinter* printer, QPainter& painter, QPageLay painter.setFont(savePainterFont);//restore the original font } -//static + void PagePrinter::renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& sourceRect, QRect& targetRect) { -// Base::Console().Message("PP::renderPage()\n"); //turn off view frames for print bool saveState = vpp->getFrameState(); vpp->setFrameState(false); @@ -381,7 +305,90 @@ void PagePrinter::renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& s vpp->getQGSPage()->refreshViews(); } -void PagePrinter::saveSVG(std::string file) + +/// print the Page associated with the view provider +void PagePrinter::print(ViewProviderPage* vpPage, QPrinter* printer) +{ + QPageLayout pageLayout = printer->pageLayout(); + + TechDraw::DrawPage* dPage = vpPage->getDrawPage(); + double width = A4Heightmm; // default to A4 Landscape 297 x 210 + double height = A4Widthmm; + makePageLayout(dPage, pageLayout, width, height); + printer->setPageLayout(pageLayout); + + QPainter painter(printer); + + auto ourScene = vpPage->getQGSPage(); + if (!printer->outputFileName().isEmpty()) { + ourScene->setExportingPdf(true); + } + auto ourDoc = Gui::Application::Instance->getDocument(dPage->getDocument()); + auto docModifiedState = ourDoc->isModified(); + + QRect targetRect = printer->pageLayout().fullRectPixels(printer->resolution()); + QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); + renderPage(vpPage, painter, sourceRect, targetRect); + + ourScene->setExportingPdf(false); // doesn't hurt if not pdf + ourDoc->setModified(docModifiedState); + dPage->redrawCommand(); +} + + +/// print the Page associated with the ViewProvider as a Pdf file +void PagePrinter::printPdf(ViewProviderPage* vpPage, const std::string& file) +{ + if (file.empty()) { + Base::Console().Warning("PagePrinter - no file specified\n"); + return; + } + + auto filespec = Base::Tools::escapeEncodeFilename(file); + filespec = DU::cleanFilespecBackslash(filespec); + + // set up the pdfwriter + QString outputFile = Base::Tools::fromStdString(filespec); + QPdfWriter pdfWriter(outputFile); + QPageLayout pageLayout = pdfWriter.pageLayout(); + auto marginsdb = pageLayout.margins(QPageLayout::Millimeter); + QString documentName = QString::fromUtf8(vpPage->getDrawPage()->getNameInDocument()); + pdfWriter.setTitle(documentName); + // default pdfWriter dpi is 1200. + + // set up the page layout + auto dPage = vpPage->getDrawPage(); + double width = A4Heightmm; // default to A4 Landscape 297 x 210 + double height = A4Widthmm; + makePageLayout(dPage, pageLayout, width, height); + pdfWriter.setPageLayout(pageLayout); + marginsdb = pageLayout.margins(QPageLayout::Millimeter); + + // first page does not respect page layout unless painter is created after + // pdfWriter layout is established. + QPainter painter(&pdfWriter); + + auto ourScene = vpPage->getQGSPage(); + ourScene->setExportingPdf(true); + auto ourDoc = Gui::Application::Instance->getDocument(dPage->getDocument()); + auto docModifiedState = ourDoc->isModified(); + + // render the page + QRectF sourceRect(0.0, Rez::guiX(-height), Rez::guiX(width), Rez::guiX(height)); + double dpmm = pdfWriter.resolution() / mmPerInch; + int twide = int(std::round(width * dpmm)); + int thigh = int(std::round(height * dpmm)); + QRect targetRect(0, 0, twide, thigh); + renderPage(vpPage, painter, sourceRect, targetRect); + + ourScene->setExportingPdf(false); + ourDoc->setModified(docModifiedState); + dPage->redrawCommand(); +} + + +//! save the page associated with the view provider as an svg file +void PagePrinter::saveSVG(ViewProviderPage* vpPage, const std::string& file) { if (file.empty()) { Base::Console().Warning("PagePrinter - no file specified\n"); @@ -390,14 +397,24 @@ void PagePrinter::saveSVG(std::string file) auto filespec = Base::Tools::escapeEncodeFilename(file); filespec = DU::cleanFilespecBackslash(file); QString filename = Base::Tools::fromStdString(filespec); - if (m_scene) { - m_scene->saveSvg(filename); - } + + auto ourScene = vpPage->getQGSPage(); + ourScene->setExportingSvg(true); + auto ourDoc = vpPage->getDocument(); + auto docModifiedState = ourDoc->isModified(); + + ourScene->saveSvg(filename); + + ourScene->setExportingSvg(false); + ourDoc->setModified(docModifiedState); } -void PagePrinter::saveDXF(std::string inFileName) + +//! save the page associated with the view provider as an svg file +// Note: the dxf exporter does not modify the page, so we do not need to reset the modified flag +void PagePrinter::saveDXF(ViewProviderPage* vpPage, const std::string& inFileName) { - TechDraw::DrawPage* page = m_vpPage->getDrawPage(); + TechDraw::DrawPage* page = vpPage->getDrawPage(); std::string PageName = page->getNameInDocument(); auto filespec = Base::Tools::escapeEncodeFilename(inFileName); filespec = DU::cleanFilespecBackslash(filespec); @@ -405,21 +422,23 @@ void PagePrinter::saveDXF(std::string inFileName) Gui::Command::doCommand(Gui::Command::Doc, "import TechDraw"); Gui::Command::doCommand(Gui::Command::Doc, "TechDraw.writeDXFPage(App.activeDocument().%s, u\"%s\")", - PageName.c_str(), filespec.c_str()); + PageName.c_str(), + filespec.c_str()); Gui::Command::commitCommand(); } -void PagePrinter::savePDF(std::string file) +// this one is somewhat superfluous (just a redirect). +void PagePrinter::savePDF(ViewProviderPage* vpPage, const std::string& file) { -// Base::Console().Message("PP::savePDF(%s)\n", file.c_str()); - printPdf(file); + printPdf(vpPage, file); } + PaperAttributes::PaperAttributes() { // set default values to A4 Landscape - orientation = QPageLayout::Orientation::Landscape; - paperSize = QPageSize::A4; - pagewidth = A4Heightmm; - pageheight = A4Widthmm; + m_orientation = QPageLayout::Orientation::Landscape; + m_paperSize = QPageSize::A4; + m_pagewidth = A4Heightmm; + m_pageheight = A4Widthmm; } diff --git a/src/Mod/TechDraw/Gui/PagePrinter.h b/src/Mod/TechDraw/Gui/PagePrinter.h index 720a9723a860..ea43e9409036 100644 --- a/src/Mod/TechDraw/Gui/PagePrinter.h +++ b/src/Mod/TechDraw/Gui/PagePrinter.h @@ -51,34 +51,49 @@ class TechDrawGuiExport PaperAttributes { public: PaperAttributes(); -// ~PaperAttributes() = default; + PaperAttributes(QPageLayout::Orientation orientation, + QPageSize::PageSizeId paperSize, + double pageWidth, + double pageHeight) + : m_orientation(orientation) + , m_paperSize(paperSize) + , m_pagewidth(pageWidth) + , m_pageheight(pageHeight) + {} + + QPageLayout::Orientation orientation() const + { + return m_orientation; + } + QPageSize::PageSizeId pageSize() const + { + return m_paperSize; + } + double pageWidth() const + { + return m_pagewidth; + } + double pageHeight() const + { + return m_pageheight; + } - QPageLayout::Orientation orientation; - QPageSize::PageSizeId paperSize; - double pagewidth; - double pageheight; +private: + QPageLayout::Orientation m_orientation; + QPageSize::PageSizeId m_paperSize; + double m_pagewidth; + double m_pageheight; }; class TechDrawGuiExport PagePrinter { public: - explicit PagePrinter(ViewProviderPage *page); - - void print(QPrinter* printer); - void printPdf(); - void printPdf(std::string file); - void printPreview(); - static void printAllPages(); - static void printAll(QPrinter* printer, - App::Document* doc); - static void printAllPdf(QPrinter* printer, - App::Document* doc); - // print banner page is no longer used static void printBannerPage(QPrinter* printer, QPainter& painter, QPageLayout& pageLayout, App::Document* doc, std::vector& docObjs); + static void renderPage(ViewProviderPage* vpp, QPainter& painter, QRectF& sourceRect, @@ -87,45 +102,20 @@ class TechDrawGuiExport PagePrinter QPageLayout& pageLayout, double& width, double& height); - void saveSVG(std::string file); - void saveDXF(std::string file); - void savePDF(std::string file); - - void setDocumentName(const std::string&); - void setScene(QGSPage* scene, QGVPage* view); - void setOwner(MDIViewPage* owner) { m_owner = owner; } - void setScene(QGSPage* scene); - - - TechDraw::DrawPage * getPage() { return m_vpPage->getDrawPage(); } - - ViewProviderPage* getViewProviderPage() {return m_vpPage;} - static PaperAttributes getPaperAttributes(TechDraw::DrawPage* pageObject); - void getPaperAttributes(); - QPageLayout::Orientation getOrientation() const { return m_orientation; } - QPageSize::PageSizeId getPaperSize() const { return m_paperSize; } - double getPageWidth() const { return m_pagewidth; } - double getPageHeight() const { return m_pageheight; } - -private: - std::string m_objectName; - std::string m_documentName; - QPointer m_scene; - - QString m_currentPath; - ViewProviderPage* m_vpPage; + static PaperAttributes getPaperAttributes(ViewProviderPage* vpPage); - QPageLayout::Orientation m_orientation; - QPageSize::PageSizeId m_paperSize; - double m_pagewidth, m_pageheight; - - MDIViewPage* m_owner; + static void print(ViewProviderPage* vpPage, QPrinter* printer); + static void printPdf(ViewProviderPage* vpPage, const std::string& file); + static void printAll(QPrinter* printer, App::Document* doc); + static void printAllPdf(QPrinter* printer, App::Document* doc); + static void saveSVG(ViewProviderPage* vpPage, const std::string& file); + static void saveDXF(ViewProviderPage* vpPage, const std::string& file); + static void savePDF(ViewProviderPage* vpPage, const std::string& file); }; - -} // namespace PagePrinterGui +} // namespace TechDrawGui #endif // TECHDRAWGUI_PAGEPRINTER_H From 797c1180b012a8aee1d67de62880df0f835a731e Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 19 Nov 2024 17:59:28 -0500 Subject: [PATCH 151/161] [TD]prevent use of non-exist/hidden tab in exports --- src/Mod/TechDraw/Gui/AppTechDrawGuiPy.cpp | 106 ++++++++++------------ src/Mod/TechDraw/Gui/Command.cpp | 14 +-- src/Mod/TechDraw/Gui/CommandDecorate.cpp | 29 +++--- src/Mod/TechDraw/Gui/MDIViewPage.cpp | 8 +- src/Mod/TechDraw/Gui/ViewProviderPage.cpp | 2 + 5 files changed, 76 insertions(+), 83 deletions(-) diff --git a/src/Mod/TechDraw/Gui/AppTechDrawGuiPy.cpp b/src/Mod/TechDraw/Gui/AppTechDrawGuiPy.cpp index ca183898b185..1939c15253cb 100644 --- a/src/Mod/TechDraw/Gui/AppTechDrawGuiPy.cpp +++ b/src/Mod/TechDraw/Gui/AppTechDrawGuiPy.cpp @@ -37,7 +37,6 @@ #include #include // generated from DrawViewPy.xml -#include "MDIViewPage.h" #include "QGIView.h" #include "QGSPage.h" #include "ViewProviderPage.h" @@ -131,25 +130,30 @@ class Module : public Py::ExtensionModule for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { PyObject* item = (*it).ptr(); if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); + App::DocumentObject* obj = + static_cast(item)->getDocumentObjectPtr(); if (obj->isDerivedFrom()) { page = static_cast(obj); - Gui::Document* activeGui = Gui::Application::Instance->getDocument(page->getDocument()); + Gui::Document* activeGui = + Gui::Application::Instance->getDocument(page->getDocument()); Gui::ViewProvider* vp = activeGui->getViewProvider(obj); - ViewProviderPage* dvp = dynamic_cast(vp); - if ( !(dvp && dvp->getMDIViewPage()) ) { + ViewProviderPage* vpPage = dynamic_cast(vp); + if (!vpPage) { throw Py::TypeError("TechDraw can not find Page"); } Base::FileInfo fi_out(EncodedName.c_str()); if (fi_out.hasExtension("svg")) { - dvp->getMDIViewPage()->saveSVG(EncodedName); - } else if (fi_out.hasExtension("dxf")) { - dvp->getMDIViewPage()->saveDXF(EncodedName); - } else if (fi_out.hasExtension("pdf")) { - dvp->getMDIViewPage()->savePDF(EncodedName); - } else { + PagePrinter::saveSVG(vpPage, EncodedName); + } + else if (fi_out.hasExtension("dxf")) { + PagePrinter::saveDXF(vpPage, EncodedName); + } + else if (fi_out.hasExtension("pdf")) { + PagePrinter::savePDF(vpPage, EncodedName); + } + else { throw Py::TypeError("TechDraw can not export this file format"); } } @@ -175,30 +179,22 @@ class Module : public Py::ExtensionModule PyMem_Free(name); try { - App::DocumentObject* obj = nullptr; - Gui::ViewProvider* vp = nullptr; - MDIViewPage* mdi = nullptr; - if (PyObject_TypeCheck(pageObj, &(App::DocumentObjectPy::Type))) { - obj = static_cast(pageObj)->getDocumentObjectPtr(); - vp = Gui::Application::Instance->getViewProvider(obj); - if (vp) { - TechDrawGui::ViewProviderPage* vpp = dynamic_cast(vp); - if (vpp) { - mdi = vpp->getMDIViewPage(); - if (mdi) { - mdi->savePDF(filePath); - } else { - vpp->showMDIViewPage(); - mdi = vpp->getMDIViewPage(); - if (mdi) { - mdi->savePDF(filePath); - } else { - throw Py::TypeError("Page not available! Is it Hidden?"); - } - } - } - } - } + App::DocumentObject* obj = nullptr; + Gui::ViewProvider* vp = nullptr; + if (PyObject_TypeCheck(pageObj, &(App::DocumentObjectPy::Type))) { + obj = static_cast(pageObj)->getDocumentObjectPtr(); + vp = Gui::Application::Instance->getViewProvider(obj); + if (vp) { + TechDrawGui::ViewProviderPage* vpPage = + dynamic_cast(vp); + if (vpPage) { + PagePrinter::savePDF(vpPage, filePath); + } + else { + throw Py::TypeError("Page not available! Is it Hidden?"); + } + } + } } catch (Base::Exception &e) { e.setPyException(); @@ -221,30 +217,22 @@ class Module : public Py::ExtensionModule PyMem_Free(name); try { - App::DocumentObject* obj = nullptr; - Gui::ViewProvider* vp = nullptr; - MDIViewPage* mdi = nullptr; - if (PyObject_TypeCheck(pageObj, &(App::DocumentObjectPy::Type))) { - obj = static_cast(pageObj)->getDocumentObjectPtr(); - vp = Gui::Application::Instance->getViewProvider(obj); - if (vp) { - TechDrawGui::ViewProviderPage* vpp = dynamic_cast(vp); - if (vpp) { - mdi = vpp->getMDIViewPage(); - if (mdi) { - mdi->saveSVG(filePath); - } else { - vpp->showMDIViewPage(); - mdi = vpp->getMDIViewPage(); - if (mdi) { - mdi->saveSVG(filePath); - } else { - throw Py::TypeError("Page not available! Is it Hidden?"); - } - } - } - } - } + App::DocumentObject* obj = nullptr; + Gui::ViewProvider* vp = nullptr; + if (PyObject_TypeCheck(pageObj, &(App::DocumentObjectPy::Type))) { + obj = static_cast(pageObj)->getDocumentObjectPtr(); + vp = Gui::Application::Instance->getViewProvider(obj); + if (vp) { + TechDrawGui::ViewProviderPage* vpPage = + dynamic_cast(vp); + if (vpPage) { + PagePrinter::saveSVG(vpPage, filePath); + } + else { + throw Py::TypeError("Page not available! Is it Hidden?"); + } + } + } } catch (Base::Exception &e) { e.setPyException(); diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index 358f10f024c9..9e02d9fb2db7 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -323,7 +323,7 @@ void CmdTechDrawView::activated(int iMsg) auto* vpp = dynamic_cast (Gui::Application::Instance->getViewProvider(page)); if (vpp) { - vpp->switchToMdiViewPage(); + vpp->show(); } @@ -1793,14 +1793,16 @@ void CmdTechDrawExportPageSVG::activated(int iMsg) Gui::Document* activeGui = Gui::Application::Instance->getDocument(page->getDocument()); Gui::ViewProvider* vp = activeGui->getViewProvider(page); - ViewProviderPage* dvp = dynamic_cast(vp); + ViewProviderPage* vpPage = dynamic_cast(vp); - if (dvp && dvp->getMDIViewPage()) { - dvp->getMDIViewPage()->saveSVG(); + if (vpPage) { + vpPage->show(); // make sure a mdi will be available + vpPage->getMDIViewPage()->saveSVG(); } else { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No Drawing View"), - QObject::tr("Open Drawing View before attempting export to SVG.")); + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("No Drawing Page"), + QObject::tr("FreeCAD could not find a page to export")); return; } } diff --git a/src/Mod/TechDraw/Gui/CommandDecorate.cpp b/src/Mod/TechDraw/Gui/CommandDecorate.cpp index f60c5bbd1d59..ed19c81a26f1 100644 --- a/src/Mod/TechDraw/Gui/CommandDecorate.cpp +++ b/src/Mod/TechDraw/Gui/CommandDecorate.cpp @@ -48,11 +48,11 @@ #include #include "DrawGuiUtil.h" -#include "MDIViewPage.h" #include "TaskGeomHatch.h" #include "TaskHatch.h" #include "ViewProviderGeomHatch.h" #include "ViewProviderPage.h" +#include "MDIViewPage.h" using namespace TechDrawGui; @@ -312,35 +312,42 @@ Gui::Action *CmdTechDrawToggleFrame::createAction() void CmdTechDrawToggleFrame::activated(int iMsg) { Q_UNUSED(iMsg); + TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); + if (!page) { + return; + } - auto mvp = dynamic_cast(Gui::getMainWindow()->activeWindow()); - if (!mvp) { + Gui::Document* activeGui = Gui::Application::Instance->getDocument(page->getDocument()); + Gui::ViewProvider* vp = activeGui->getViewProvider(page); + ViewProviderPage* vpPage = dynamic_cast(vp); + + if (!vpPage) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No TechDraw Page"), QObject::tr("Need a TechDraw Page for this command")); return; } - ViewProviderPage* vpp = mvp->getViewProviderPage(); - if (!vpp) { - return; - } - vpp->toggleFrameState(); + vpPage->toggleFrameState(); Gui::Action *action = this->getAction(); if (action) { - action->setChecked(!vpp->getFrameState(), true); + action->setChecked(!vpPage->getFrameState(), true); } } +//! true if the active tab is a TechDraw Page. +// There is an assumption here that you would only want to toggle the frames on a page when you are +// currently looking at that page bool CmdTechDrawToggleFrame::isActive() { - auto mvp = dynamic_cast(Gui::getMainWindow()->activeWindow()); + auto mvp = dynamic_cast(Gui::getMainWindow()->activeWindow()); if (!mvp) { return false; } ViewProviderPage* vpp = mvp->getViewProviderPage(); - Gui::Action *action = this->getAction(); + + Gui::Action* action = this->getAction(); if (action) { action->setChecked(vpp && !vpp->getFrameState(), true); } diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index c485671e499c..bc82c62d6ff0 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -119,14 +119,11 @@ MDIViewPage::MDIViewPage(ViewProviderPage* pageVp, Gui::Document* doc, QWidget* connectDeletedObject = appDoc->signalDeletedObject.connect(bnd); //NOLINTEND - // m_pagePrinter = new PagePrinter(m_vpPage); - // m_pagePrinter->setOwner(this); } MDIViewPage::~MDIViewPage() { connectDeletedObject.disconnect(); - // delete m_pagePrinter; } void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) @@ -134,9 +131,6 @@ void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget) m_scene = scene; setCentralWidget(viewWidget);//this makes viewWidget a Qt child of MDIViewPage QObject::connect(scene, &QGSPage::selectionChanged, this, &MDIViewPage::sceneSelectionChanged); - // if (m_pagePrinter) { - // m_pagePrinter->setScene(m_scene); - // } } void MDIViewPage::setDocumentObject(const std::string& name) @@ -420,7 +414,7 @@ void MDIViewPage::print(QPrinter* printer) PagePrinter::print(getViewProviderPage(), printer); } -//static routine to print all pages in a document +// static routine to print all pages in a document. Used by PrintAll command in Command.cpp void MDIViewPage::printAll(QPrinter* printer, App::Document* doc) { PagePrinter::printAll(printer, doc); diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp index 15949599864b..107a0e1ec03a 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include "ViewProviderPage.h" #include "MDIViewPage.h" From f0ba161bdf7c11e195a328ca4df5d69ba208fe1f Mon Sep 17 00:00:00 2001 From: Max Wilfinger Date: Fri, 29 Nov 2024 19:31:07 +0100 Subject: [PATCH 152/161] Update Sketcher external icons and cursors --- .../icons/geometry/Sketcher_Intersection.svg | 348 ++++++------------ .../geometry/Sketcher_Intersection_Constr.svg | 348 ++++++------------ .../icons/geometry/Sketcher_Projection.svg | 342 ++++++----------- .../geometry/Sketcher_Projection_Constr.svg | 342 ++++++----------- .../pointers/Sketcher_Pointer_External.svg | 123 ++----- ...Sketcher_Pointer_External_Intersection.svg | 107 ++---- 6 files changed, 541 insertions(+), 1069 deletions(-) diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg index b3f6c993ae13..4a31587c3752 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection.svg @@ -1,41 +1,18 @@ + + - - - - - - - - - - - - - - - - + id="linearGradient2"> + id="stop1" /> - - - - + id="stop2" /> + gradientTransform="translate(2.5714413,-4.9824956)" /> + gradientTransform="translate(2.5714413,-4.9824956)" /> - + gradientTransform="matrix(0.82607043,0,0,0.82533448,-4.0098079,1.346708)" + x1="-18" + y1="18" + x2="-22" + y2="5" /> + x1="-15" + y1="37" + x2="-19" + y2="37" + gradientTransform="rotate(15,69.468151,244.38323)" /> + id="linearGradient3012" + xlink:href="#linearGradient3895" /> + id="linearGradient3895"> + + + @@ -323,77 +191,95 @@ FreeCAD - FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + FreeCAD/src/ FreeCAD LGPL2+ - 2023-12-19 + 2024 - - - - - - - - + id="layer3" + style="display:inline"> + id="path23" + d="M 18.338483,34.745395 V 55.758543 L 44.46154,57.259858 V 36.24671 Z" + style="display:inline;fill:#204b88;fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> - - + id="path24" + d="m 44.46154,57.259858 7.076915,-7.506574 V 28.740136 L 44.46154,36.24671 Z" + style="display:inline;fill:#142e52;fill-opacity:1;stroke:#0b1622;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> + style="fill:#eeeeec;stroke:#0b1d23;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-opacity:1" + d="M 4,46.999999 H 60 L 56,20 H 8 Z" + id="path2" /> + style="fill:#babdb6;stroke:#eeeeec;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1" + d="m 9.734375,34.009766 h 44.53125 l 3.404297,22.980468 H 6.3300781 Z" + id="path22" + transform="translate(0,-12)" /> + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg index 29e130e4cabb..8e6945c90f22 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Intersection_Constr.svg @@ -1,41 +1,18 @@ + + - - - - - - - - - - - - - - - - + id="linearGradient2"> + id="stop1" /> - - - - + id="stop2" /> + gradientTransform="translate(2.5714413,-4.9824956)" /> + gradientTransform="translate(2.5714413,-4.9824956)" /> - + gradientTransform="matrix(0.82607043,0,0,0.82533448,-4.0098079,1.346708)" + x1="-18" + y1="18" + x2="-22" + y2="5" /> + x1="-15" + y1="37" + x2="-19" + y2="37" + gradientTransform="rotate(15,69.468151,244.38323)" /> + id="linearGradient3012" + xlink:href="#linearGradient3895" /> + id="linearGradient3895"> + + + @@ -323,77 +191,95 @@ FreeCAD - FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + FreeCAD/src/ FreeCAD LGPL2+ - 2023-12-19 + 2024 - - - - - - - - + id="layer3" + style="display:inline"> + id="path23" + d="M 18.338483,34.745395 V 55.758543 L 44.46154,57.259858 V 36.24671 Z" + style="display:inline;fill:#204b88;fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> - - + id="path24" + d="m 44.46154,57.259858 7.076915,-7.506574 V 28.740136 L 44.46154,36.24671 Z" + style="display:inline;fill:#142e52;fill-opacity:1;stroke:#0b1622;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> + style="fill:#eeeeec;stroke:#0b1d23;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-opacity:1" + d="M 4,46.999999 H 60 L 56,20 H 8 Z" + id="path2" /> + style="fill:#babdb6;stroke:#eeeeec;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1" + d="m 9.734375,34.009766 h 44.53125 l 3.404297,22.980468 H 6.3300781 Z" + id="path22" + transform="translate(0,-12)" /> + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg index 1343f13b1bd2..6a451dc42dcf 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection.svg @@ -1,41 +1,18 @@ + + - - - - - - - - - - - - - - - - + id="linearGradient2"> + id="stop1" /> - - - - + id="stop2" /> + y2="42" + gradientTransform="translate(2.5714413,-4.9824956)" /> + y2="38" + gradientTransform="translate(2.5714413,-4.9824956)" /> - - + + + + + + @@ -302,91 +191,90 @@ FreeCAD - FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + FreeCAD/src/ FreeCAD LGPL2+ - 2023-12-19 + 2024 - - + id="layer3" + style="display:inline"> + style="fill:#eeeeec;fill-opacity:1;stroke:#0b1d23;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="M 4,58.999999 H 60 L 56,32 H 8 Z" + id="path2" /> - - - - - - - - - - - - - - - + style="fill:#babdb6;fill-opacity:1;stroke:#eeeeec;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 9.734375,34.009766 h 44.53125 l 3.404297,22.980468 H 6.3300781 Z" + id="path22" /> + + + + + + + + + + + + + + + + + + + style="display:inline;fill:#8ae234;fill-opacity:1;fill-rule:evenodd;stroke:#17220c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 29.266682,23.859058 h 5.466638 v 6.538719 h 6.135545 L 32,42 23.131133,30.397777 h 6.135549 z" + id="path1-42" /> diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg index fdee350e24a4..6a1cb58c8c81 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_Projection_Constr.svg @@ -1,41 +1,18 @@ + + - - - - - - - - - - - - - - - - + id="linearGradient2"> + id="stop1" /> - - - - + id="stop2" /> + y2="42" + gradientTransform="translate(2.5714413,-4.9824956)" /> + y2="38" + gradientTransform="translate(2.5714413,-4.9824956)" /> - - + + + + + + @@ -302,91 +191,90 @@ FreeCAD - FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + FreeCAD/src/ FreeCAD LGPL2+ - 2023-12-19 + 2024 - - + id="layer3" + style="display:inline"> + style="fill:#eeeeec;fill-opacity:1;stroke:#0b1d23;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="M 4,58.999999 H 60 L 56,32 H 8 Z" + id="path2" /> - - - - - - - - - - - - - - - + style="fill:#babdb6;fill-opacity:1;stroke:#eeeeec;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + d="m 9.734375,34.009766 h 44.53125 l 3.404297,22.980468 H 6.3300781 Z" + id="path22" /> + + + + + + + + + + + + + + + + + + + style="display:inline;fill:#8ae234;fill-opacity:1;fill-rule:evenodd;stroke:#17220c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 29.266682,23.859058 h 5.466638 v 6.538719 h 6.135545 L 32,42 23.131133,30.397777 h 6.135549 z" + id="path1-42" /> diff --git a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External.svg b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External.svg index 1402ab186dbc..37890501daa1 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External.svg @@ -4,33 +4,11 @@ width="64" height="64" version="1.1" - sodipodi:docname="Sketcher_Pointer_External.svg" - inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> - @@ -43,70 +21,13 @@ - - - - - - - - - - - - - + id="defs16" /> + r="3.2321463" /> @@ -114,4 +35,38 @@ id="path9" d="m16,3v9m0,8v9m-13-13h9m8,0h9" /> + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg index b7124ee89320..f81d3ae36114 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_External_Intersection.svg @@ -4,38 +4,11 @@ width="64" height="64" version="1.1" - sodipodi:docname="Sketcher_Pointer_External_Intersection.svg" - inkscape:version="1.1-beta1 (77e7b44db3, 2021-03-28)" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> - @@ -48,44 +21,13 @@ - - - - - - - - + id="defs16" /> + @@ -93,9 +35,36 @@ id="path9" d="m16,3v9m0,8v9m-13-13h9m8,0h9" /> + + + + + + + id="path3027-8" + d="m 26.114586,26.674045 7.646078,-6.317988 20.320431,1.263598 -5.961348,6.317987 z" + style="display:inline;fill:none;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> From 0cd5768fbdb68522e601fb8bd5ef93b324b462c4 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:37:48 +0100 Subject: [PATCH 153/161] Draft: Draft_Fillet: fix error in #17945 (#18150) * Draft: Draft_Fillet: fix error in #17945 In #17945 the delete option of the command results in an error if subobjects are selected. * Command should not be available if there is no selection * Update copyright notice --- src/Mod/Draft/draftguitools/gui_fillets.py | 42 ++++++------- src/Mod/Draft/draftmake/make_fillet.py | 69 ++++++++++++---------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py index 38c57ffb0abb..74c47a1abfd4 100644 --- a/src/Mod/Draft/draftguitools/gui_fillets.py +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -54,19 +54,23 @@ class Fillet(gui_base_original.Creator): """Gui command for the Fillet tool.""" def __init__(self): - super(Fillet, self).__init__() + super().__init__() self.featureName = "Fillet" + def IsActive(self): + """Return True when this command should be available.""" + return bool(Gui.Selection.getSelection()) + def GetResources(self): """Set icon, menu and tooltip.""" return {"Pixmap": "Draft_Fillet", - "Accel":"F,I", + "Accel": "F,I", "MenuText": QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), "ToolTip": QT_TRANSLATE_NOOP("Draft_Fillet", "Creates a fillet between two selected wires or edges.")} def Activated(self, name="Fillet"): """Execute when the command is called.""" - super(Fillet, self).Activated(name=name) + super().Activated(name=name) if self.ui: self.rad = 100 @@ -140,15 +144,7 @@ def numericRadius(self, rad): def draw_arc(self, rad, chamfer, delete): """Process the selection and draw the actual object.""" sels = Gui.Selection.getSelectionEx("", 0) - objs = [] - objs_str = [] - doc = "FreeCAD.ActiveDocument." - for sel in sels: - for sub in sel.SubElementNames if sel.SubElementNames else [""]: - objs.append(sel.Object.getSubObject(sub)) - objs_str.append(doc + sel.Object.Name + ".getSubObject('" + sub + "')") - - edges = make_fillet._preprocess(objs, rad, chamfer) + edges, _ = make_fillet._preprocess(sels, rad, chamfer) if edges is None: _err(translate("draft", "Fillet cannot be created")) self.finish() @@ -156,20 +152,18 @@ def draw_arc(self, rad, chamfer, delete): Gui.addModule("Draft") - _cmd = "Draft.make_fillet" - _cmd += "(" - _cmd += "[" + objs_str[0] + ", " + objs_str[1] + "], " - _cmd += "radius=" + str(rad) + cmd = "Draft.make_fillet(sels, radius=" + str(rad) if chamfer: - _cmd += ", chamfer=True" + cmd += ", chamfer=True" if delete: - _cmd += ", delete=True" - _cmd += ")" - _cmd_list = ["fillet = " + _cmd, - "Draft.autogroup(fillet)", - "FreeCAD.ActiveDocument.recompute()"] - - self.commit(translate("draft", "Create fillet"), _cmd_list) + cmd += ", delete=True" + cmd += ")" + cmd_list = ["sels = FreeCADGui.Selection.getSelectionEx('', 0)", + "fillet = " + cmd, + "Draft.autogroup(fillet)", + "FreeCAD.ActiveDocument.recompute()"] + + self.commit(translate("draft", "Create fillet"), cmd_list) self.finish() diff --git a/src/Mod/Draft/draftmake/make_fillet.py b/src/Mod/Draft/draftmake/make_fillet.py index 7576d3992db4..5b874032e98a 100644 --- a/src/Mod/Draft/draftmake/make_fillet.py +++ b/src/Mod/Draft/draftmake/make_fillet.py @@ -1,5 +1,6 @@ # *************************************************************************** # * Copyright (c) 2019 Eliud Cabrera Castillo * +# * Copyright (c) 2024 FreeCAD Project Association * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * @@ -47,43 +48,48 @@ ## \addtogroup draftmake # @{ -def _extract_edge(obj): - """Extract the 1st edge from an object or shape.""" - if hasattr(obj, "Shape"): - obj = obj.Shape - if hasattr(obj, "ShapeType") and obj.ShapeType in ("Wire", "Edge"): - return obj.Edges[0] - return None - - def _preprocess(objs, radius, chamfer): - """Check the inputs and return the edges for the fillet.""" - if len(objs) != 2: - _err(translate("draft", "Two objects are needed.")) - return None - - edge1 = _extract_edge(objs[0]) - edge2 = _extract_edge(objs[1]) - - if edge1 is None or edge2 is None: - _err(translate("draft", "One object is not valid.")) - return None - - edges = DraftGeomUtils.fillet([edge1, edge2], radius, chamfer) + """Check the inputs and return the edges for the fillet and the objects to be deleted.""" + edges = [] + del_objs = [] + if objs[0].isDerivedFrom("Gui::SelectionObject"): + for sel in objs: + for sub in sel.SubElementNames if sel.SubElementNames else [""]: + shape = sel.Object.getSubObject(sub) + if shape.ShapeType == "Edge": + edges.append(shape) + if sel.Object not in del_objs: + del_objs.append(sel.Object) + else: + for obj in objs: + if hasattr(obj, "Shape"): + shape = obj.Shape + del_objs.append(obj) + else: + shape = obj + if hasattr(shape, "ShapeType") and shape.ShapeType in ("Wire", "Edge"): + edges.append(shape.Edges[0]) + + if len(edges) != 2: + _err(translate("draft", "Two edges are needed.")) + return None, None + + edges = DraftGeomUtils.fillet(edges, radius, chamfer) if len(edges) < 3: _err(translate("draft", "Edges are not connected or radius is too large.")) - return None + return None, None - return edges + return edges, del_objs def make_fillet(objs, radius=100, chamfer=False, delete=False): - """Create a fillet between two lines or Part.Edges. + """Create a fillet between two edges. Parameters ---------- objs: list - List of two objects of type wire, or edges. + A list of two objects or shapes of type wire (1st edge is used) or edge, + or a 2 edge selection set:`FreeCADGui.Selection.getSelectionEx("", 0)`. radius: float, optional It defaults to 100. The curvature of the fillet. @@ -94,9 +100,8 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): with the value of the `radius`. delete: bool, optional - It defaults to `False`. If it is `True` it will delete - the pair of objects that are used to create the fillet. - Otherwise, the original objects will still be there. + It defaults to `False`. If `True` the source objects are deleted. + Ignored for shapes. Returns ------- @@ -105,7 +110,7 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): It returns `None` if it fails producing the object. """ - edges = _preprocess(objs, radius, chamfer) + edges, del_objs = _preprocess(objs, radius, chamfer) if edges is None: return @@ -124,8 +129,8 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): obj.FilletRadius = radius if delete: - doc.removeObject(objs[0].Name) - doc.removeObject(objs[1].Name) + for del_obj in del_objs: + doc.removeObject(del_obj.Name) if App.GuiUp: view_fillet.ViewProviderFillet(obj.ViewObject) From 800a5cffbbd312abbe61241f0c01e22cefb39b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pinkava?= Date: Thu, 3 Oct 2024 19:32:42 +0200 Subject: [PATCH 154/161] Gui: remove unused MDITabbar and MainWindowTabBar classes --- src/Gui/MainWindow.cpp | 80 ------------------------------------------ 1 file changed, 80 deletions(-) diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 6862089d0258..c9ac2a6413dd 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -300,86 +300,6 @@ struct MainWindowP void restoreWindowState(const QByteArray &); }; -class MDITabbar : public QTabBar -{ -public: - explicit MDITabbar( QWidget * parent = nullptr ) : QTabBar(parent) - { - menu = new QMenu(this); - setDrawBase(false); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); - } - - ~MDITabbar() override - { - delete menu; - } - -protected: - void contextMenuEvent ( QContextMenuEvent * e ) override - { - menu->clear(); - CommandManager& cMgr = Application::Instance->commandManager(); - if (tabRect(currentIndex()).contains(e->pos())) - cMgr.getCommandByName("Std_CloseActiveWindow")->addTo(menu); - cMgr.getCommandByName("Std_CloseAllWindows")->addTo(menu); - menu->addSeparator(); - cMgr.getCommandByName("Std_CascadeWindows")->addTo(menu); - cMgr.getCommandByName("Std_TileWindows")->addTo(menu); - menu->addSeparator(); - cMgr.getCommandByName("Std_Windows")->addTo(menu); - menu->popup(e->globalPos()); - } - -private: - QMenu* menu; -}; - -#if defined(Q_OS_WIN32) -class MainWindowTabBar : public QTabBar -{ -public: - MainWindowTabBar(QWidget *parent) : QTabBar(parent) - { - setExpanding(false); - } -protected: - bool event(QEvent *e) - { - // show the tooltip if tab is too small to fit label - if (e->type() != QEvent::ToolTip) - return QTabBar::event(e); - QSize size = this->size(); - QSize hint = sizeHint(); - if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) { - size.transpose(); - hint.transpose(); - } - if (size.width() < hint.width()) - return QTabBar::event(e); - e->accept(); - return true; - } - void tabInserted (int index) - { - // get all dock windows - QList dw = getMainWindow()->findChildren(); - for (QList::iterator it = dw.begin(); it != dw.end(); ++it) { - // compare tab text and window title to get the right dock window - if (this->tabText(index) == (*it)->windowTitle()) { - QWidget* dock = (*it)->widget(); - if (dock) { - QIcon icon = dock->windowIcon(); - if (!icon.isNull()) - setTabIcon(index, icon); - } - break; - } - } - } -}; -#endif - } // namespace Gui /* TRANSLATOR Gui::MainWindow */ From 795c4df1c3de223e34f242c7a0c79fb20a4326ba Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Wed, 20 Nov 2024 19:37:46 +0000 Subject: [PATCH 155/161] Remove MeshPy::coarsen() and code using GTS FC_USE_GTS not used since before: 1162aaea88 ("Remove references to gts and ode", 2012-07-05) GTSAlgos.h and GTSAlgos.cpp removed in: d1431f405c ("[Mesh] remove GTSAlgos", 2022-11-11) MeshPy::coarsen() added not later than 2011 and never implemented. --- src/Mod/Mesh/.gitattributes | 2 - src/Mod/Mesh/App/MeshPy.xml | 5 - src/Mod/Mesh/App/MeshPyImp.cpp | 9 - src/Mod/Mesh/App/PreCompiled.h | 3 - src/Mod/Mesh/Gui/PreCompiled.h | 5 - src/Mod/MeshPart/App/CurveProjector.h | 4 - src/Mod/MeshPart/App/MeshAlgos.cpp | 244 -------------------------- src/Mod/MeshPart/App/MeshAlgos.h | 20 --- 8 files changed, 292 deletions(-) delete mode 100644 src/Mod/Mesh/.gitattributes diff --git a/src/Mod/Mesh/.gitattributes b/src/Mod/Mesh/.gitattributes deleted file mode 100644 index b53efa0b7360..000000000000 --- a/src/Mod/Mesh/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -GTSAlgos.cpp export-ignore -GTSAlgos.h export-ignore diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index 1c955f507932..f565f11ab86b 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -98,11 +98,6 @@ lines = mesh.section(mesh2, [ConnectLines=True, MinDist=0.0001])
- - - Coarse the mesh - - Apply a translation to the mesh diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 1f4422e0089e..0045de4c49cd 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -593,15 +593,6 @@ PyObject* MeshPy::section(PyObject* args, PyObject* kwds) return Py::new_reference_to(outer); } -PyObject* MeshPy::coarsen(PyObject* args) -{ - if (!PyArg_ParseTuple(args, "")) { - return nullptr; - } - PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); - return nullptr; -} - PyObject* MeshPy::translate(PyObject* args) { float x {}; diff --git a/src/Mod/Mesh/App/PreCompiled.h b/src/Mod/Mesh/App/PreCompiled.h index b8f33e88c2a0..4d4317c9d002 100644 --- a/src/Mod/Mesh/App/PreCompiled.h +++ b/src/Mod/Mesh/App/PreCompiled.h @@ -46,9 +46,6 @@ #include #include -#ifdef FC_USE_GTS -#include -#endif // STL #include #include diff --git a/src/Mod/Mesh/Gui/PreCompiled.h b/src/Mod/Mesh/Gui/PreCompiled.h index 6c31c3511c07..57b27a3171cd 100644 --- a/src/Mod/Mesh/Gui/PreCompiled.h +++ b/src/Mod/Mesh/Gui/PreCompiled.h @@ -37,11 +37,6 @@ #ifdef _PreComp_ -// Gts -#ifdef FC_USE_GTS -#include -#endif - // standard #include #include diff --git a/src/Mod/MeshPart/App/CurveProjector.h b/src/Mod/MeshPart/App/CurveProjector.h index e7d99100ed0a..f2c84e4c2b8b 100644 --- a/src/Mod/MeshPart/App/CurveProjector.h +++ b/src/Mod/MeshPart/App/CurveProjector.h @@ -23,10 +23,6 @@ #ifndef _CurveProjector_h_ #define _CurveProjector_h_ -#ifdef FC_USE_GTS -#include -#endif - #include #include diff --git a/src/Mod/MeshPart/App/MeshAlgos.cpp b/src/Mod/MeshPart/App/MeshAlgos.cpp index 3309481dbf0d..96c5169d5e79 100644 --- a/src/Mod/MeshPart/App/MeshAlgos.cpp +++ b/src/Mod/MeshPart/App/MeshAlgos.cpp @@ -144,250 +144,6 @@ void MeshAlgos::offsetSpecial(MeshCore::MeshKernel* Mesh, float fSize, float zma } } - -void MeshAlgos::coarsen(MeshCore::MeshKernel* /*Mesh*/, float /*f*/) -{ -#ifdef FC_USE_GTS - GtsSurface* surface; - - // create a GTS surface - surface = MeshAlgos::createGTSSurface(Mesh); - - Mesh->Clear(); - - guint stop_number = 100000; - gdouble fold = 3.1415 / 180.; - - gts_surface_coarsen(surface, - NULL, - NULL, - NULL, - NULL, - (GtsStopFunc)gts_coarsen_stop_number, - &stop_number, - fold); - - // get the standard mesh - fillMeshFromGTSSurface(Mesh, surface); -#endif -} - - -MeshCore::MeshKernel* MeshAlgos::boolean(MeshCore::MeshKernel* pMesh1, - MeshCore::MeshKernel* /*pMesh2*/, - MeshCore::MeshKernel* /*pResult*/, - int /*Type*/) -{ -#ifdef FC_USE_GTS - GtsSurface *s1, *s2, *s3; - GtsSurfaceInter* si; - GNode *tree1, *tree2; - gboolean check_self_intersection = false; - gboolean closed = true, is_open1, is_open2; - - - // create a GTS surface - s1 = MeshAlgos::createGTSSurface(pMesh1); - s2 = MeshAlgos::createGTSSurface(pMesh2); - - /* check that the surfaces are orientable manifolds */ - if (!gts_surface_is_orientable(s1)) { - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - throw std::runtime_error("surface 1 is not an orientable manifold\n"); - } - if (!gts_surface_is_orientable(s2)) { - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - throw std::runtime_error("surface 2 is not an orientable manifold\n"); - } - - /* check that the surfaces are not self-intersecting */ - if (check_self_intersection) { - GtsSurface* self_intersects; - - self_intersects = gts_surface_is_self_intersecting(s1); - if (self_intersects != NULL) { - gts_object_destroy(GTS_OBJECT(self_intersects)); - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - throw std::runtime_error("surface is self-intersecting\n"); - } - self_intersects = gts_surface_is_self_intersecting(s2); - if (self_intersects != NULL) { - gts_object_destroy(GTS_OBJECT(self_intersects)); - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - throw std::runtime_error("surface is self-intersecting\n"); - } - } - - /* build bounding box tree for first surface */ - tree1 = gts_bb_tree_surface(s1); - is_open1 = gts_surface_volume(s1) < 0. ? true : false; - - /* build bounding box tree for second surface */ - tree2 = gts_bb_tree_surface(s2); - is_open2 = gts_surface_volume(s2) < 0. ? true : false; - - si = gts_surface_inter_new(gts_surface_inter_class(), s1, s2, tree1, tree2, is_open1, is_open2); - g_assert(gts_surface_inter_check(si, &closed)); - if (!closed) { - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - gts_bb_tree_destroy(tree1, true); - gts_bb_tree_destroy(tree2, true); - throw "the intersection of 1 and 2 is not a closed curve\n"; - } - - s3 = gts_surface_new(gts_surface_class(), - gts_face_class(), - gts_edge_class(), - gts_vertex_class()); - if (Type == 0) { // union - gts_surface_inter_boolean(si, s3, GTS_1_OUT_2); - gts_surface_inter_boolean(si, s3, GTS_2_OUT_1); - } - else if (Type == 1) { // inter - gts_surface_inter_boolean(si, s3, GTS_1_IN_2); - gts_surface_inter_boolean(si, s3, GTS_2_IN_1); - } - else if (Type == 2) { // diff - gts_surface_inter_boolean(si, s3, GTS_1_OUT_2); - gts_surface_inter_boolean(si, s3, GTS_2_IN_1); - gts_surface_foreach_face(si->s2, (GtsFunc)gts_triangle_revert, NULL); - gts_surface_foreach_face(s2, (GtsFunc)gts_triangle_revert, NULL); - } - else if (Type == 3) { // cut inner - gts_surface_inter_boolean(si, s3, GTS_1_IN_2); - } - else if (Type == 4) { // cut outer - gts_surface_inter_boolean(si, s3, GTS_1_OUT_2); - } - - // check that the resulting surface is not self-intersecting - if (check_self_intersection) { - GtsSurface* self_intersects; - - self_intersects = gts_surface_is_self_intersecting(s3); - if (self_intersects != NULL) { - gts_object_destroy(GTS_OBJECT(self_intersects)); - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - gts_object_destroy(GTS_OBJECT(s3)); - gts_object_destroy(GTS_OBJECT(si)); - gts_bb_tree_destroy(tree1, true); - gts_bb_tree_destroy(tree2, true); - throw std::runtime_error("the resulting surface is self-intersecting\n"); - } - } - // display summary information about the resulting surface - // if (verbose) - // gts_surface_print_stats (s3, stderr); - // write resulting surface to standard output - - // get the standard mesh - fillMeshFromGTSSurface(pResult, s3); - - - // destroy surfaces - gts_object_destroy(GTS_OBJECT(s1)); - gts_object_destroy(GTS_OBJECT(s2)); - -#endif - return pMesh1; -} - - -#ifdef FC_USE_GTS - - -/// helper function - construct a Edge out of two Vertexes if not already there -static GtsEdge* new_edge(GtsVertex* v1, GtsVertex* v2) -{ - GtsSegment* s = gts_vertices_are_connected(v1, v2); - if (s == NULL) { - return gts_edge_new(gts_edge_class(), v1, v2); - } - else { - return GTS_EDGE(s); - } -} - - -GtsSurface* MeshAlgos::createGTSSurface(MeshCore::MeshKernel* Mesh) -{ - GtsSurface* Surf = gts_surface_new(gts_surface_class(), - gts_face_class(), - gts_edge_class(), - gts_vertex_class()); - - unsigned long p1, p2, p3; - Base::Vector3f Vertex; - - - // Getting all the points - GtsVertex** aVertex = (GtsVertex**)malloc(Mesh->CountPoints() * sizeof(GtsVertex*)); - for (unsigned int PIter = 0; PIter < Mesh->CountPoints(); PIter++) { - Vertex = Mesh->GetPoint(PIter); - aVertex[PIter] = gts_vertex_new(gts_vertex_class(), Vertex.x, Vertex.y, Vertex.z); - } - - // cycling through the facets - for (unsigned int pFIter = 0; pFIter < Mesh->CountFacets(); pFIter++) { - // getting the three points of the facet - Mesh->GetFacetPoints(pFIter, p1, p2, p3); - - // creating the edges and add the face to the surface - gts_surface_add_face(Surf, - gts_face_new(Surf->face_class, - new_edge(aVertex[p1], aVertex[p2]), - new_edge(aVertex[p2], aVertex[p3]), - new_edge(aVertex[p3], aVertex[p1]))); - } - - Base::Console().Log("GTS [%d faces, %d Points, %d Edges,%s ,%s]\n", - gts_surface_face_number(Surf), - gts_surface_vertex_number(Surf), - gts_surface_edge_number(Surf), - gts_surface_is_orientable(Surf) ? "orientable" : "not orientable", - gts_surface_is_self_intersecting(Surf) ? "self-intersections" - : "no self-intersection"); - - return Surf; -} - -/// helper function for the face (triangle iteration -static void onFaces(GtsTriangle* t, std::vector* VAry) -{ - GtsVertex *mv0, *mv1, *mv2; - - gts_triangle_vertices(t, &mv0, &mv1, &mv2); - - VAry->push_back(MeshGeomFacet(Base::Vector3f(mv0->p.x, mv0->p.y, mv0->p.z), - Base::Vector3f(mv1->p.x, mv1->p.y, mv1->p.z), - Base::Vector3f(mv2->p.x, mv2->p.y, mv2->p.z))); -} - - -void MeshAlgos::fillMeshFromGTSSurface(MeshCore::MeshKernel* pMesh, GtsSurface* pSurface) -{ - std::vector VAry; - - // remove old mesh - pMesh->Clear(); - - gts_surface_foreach_face(pSurface, (GtsFunc)onFaces, &VAry); - - // destroy surfaces - gts_object_destroy(GTS_OBJECT(pSurface)); - - // put the facets the simple way in the mesh, totp is recalculated! - (*pMesh) = VAry; -} - -#endif - #include #include #include diff --git a/src/Mod/MeshPart/App/MeshAlgos.h b/src/Mod/MeshPart/App/MeshAlgos.h index 5a0412be2005..cca7065c9afc 100644 --- a/src/Mod/MeshPart/App/MeshAlgos.h +++ b/src/Mod/MeshPart/App/MeshAlgos.h @@ -23,10 +23,6 @@ #ifndef _MeshAlgos_h_ #define _MeshAlgos_h_ -#ifdef FC_USE_GTS -#include -#endif - #include #include "CurveProjector.h" @@ -56,10 +52,6 @@ class MeshPartExport MeshAlgos static void offsetSpecial2(MeshCore::MeshKernel* Mesh, float fSize); static void offsetSpecial(MeshCore::MeshKernel* Mesh, float fSize, float zmax, float zmin); - /** Coarsen the mesh - */ - static void coarsen(MeshCore::MeshKernel* Mesh, float f); - /** makes a boolean add * The int Type stears the boolean oberation: 0=add;1=intersection;2=diff */ @@ -68,18 +60,6 @@ class MeshPartExport MeshAlgos MeshCore::MeshKernel* pResult, int Type = 0); -#ifdef FC_USE_GTS - - /** Creates a GTS Surface from a MeshKernel - */ - static GtsSurface* createGTSSurface(MeshCore::MeshKernel* Mesh); - - /** Creates a GTS Surface from a MeshKernel - */ - - static void fillMeshFromGTSSurface(MeshCore::MeshKernel* pMesh, GtsSurface* pSurface); -#endif - static void cutByShape(const TopoDS_Shape& aShape, const MeshCore::MeshKernel* pMesh, MeshCore::MeshKernel* pToolMesh); From d010645d23f18f017241e1305226177c8d2873d1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 30 Nov 2024 00:45:16 +0100 Subject: [PATCH 156/161] Fix compiler warnings --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 97b57910c920..a298eee3b568 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1546,7 +1546,7 @@ CmdSketcherIntersection::CmdSketcherIntersection() CONSTRUCTION_UPDATE_ACTION(CmdSketcherIntersection, "Sketcher_Intersection") -void CmdSketcherIntersection::activated(int iMsg) +void CmdSketcherIntersection::activated(int) { ActivateHandler(getActiveGuiDocument(), std::make_unique(true)); } From 112a6630f7783718292ff8d81e26b1d752619170 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 30 Nov 2024 07:25:05 +0100 Subject: [PATCH 157/161] Remove spd lib include --- .github/workflows/sub_lint.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/sub_lint.yml b/.github/workflows/sub_lint.yml index 7e3cadbb64a6..f16e21ed3441 100644 --- a/.github/workflows/sub_lint.yml +++ b/.github/workflows/sub_lint.yml @@ -491,8 +491,6 @@ jobs: libboost-thread-dev \ libcoin-dev \ libeigen3-dev \ - libgts-bin \ - libgts-dev \ libkdtree++-dev \ libmedc-dev \ libocct-data-exchange-dev \ From 7d874094fd5828fea19ca23e27f346bad7c82e39 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 30 Nov 2024 07:48:52 +0100 Subject: [PATCH 158/161] Update sub_buildUbuntu2004.yml --- .github/workflows/sub_buildUbuntu2004.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/sub_buildUbuntu2004.yml b/.github/workflows/sub_buildUbuntu2004.yml index c5dfc630463f..23c969e9ed64 100644 --- a/.github/workflows/sub_buildUbuntu2004.yml +++ b/.github/workflows/sub_buildUbuntu2004.yml @@ -95,8 +95,6 @@ jobs: libboost-thread-dev \ libcoin-dev \ libeigen3-dev \ - libgts-bin \ - libgts-dev \ libkdtree++-dev \ libmedc-dev \ libocct-data-exchange-dev \ From ac912cc0978dd72f6db22aae956e0ee806f22d02 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 30 Nov 2024 08:19:13 +0100 Subject: [PATCH 159/161] Update debian.sh --- tools/build/Docker/debian.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build/Docker/debian.sh b/tools/build/Docker/debian.sh index e10542527fc5..246288cb92e4 100755 --- a/tools/build/Docker/debian.sh +++ b/tools/build/Docker/debian.sh @@ -3,7 +3,7 @@ apt-get install --no-install-recommends --yes build-essential cmake doxygen \ git libboost-date-time-dev libboost-dev libboost-filesystem-dev \ libboost-graph-dev libboost-iostreams-dev libboost-program-options-dev \ libboost-python-dev libboost-regex-dev libboost-serialization-dev \ - libboost-thread-dev libcoin-dev libeigen3-dev libgtkglext1-dev libgts-dev \ + libboost-thread-dev libcoin-dev libeigen3-dev libgtkglext1-dev \ libkdtree++-dev libkml-dev libmedc-dev libocct-data-exchange-dev \ libocct-draw-dev libocct-foundation-dev libocct-modeling-algorithms-dev \ libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev \ From 16b24e10d648d76e22477cede9559bff7c098ea1 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 30 Nov 2024 08:20:27 +0100 Subject: [PATCH 160/161] Update ubuntu.sh --- tools/build/Docker/ubuntu.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build/Docker/ubuntu.sh b/tools/build/Docker/ubuntu.sh index 99fbc715c209..5819094bd7a9 100644 --- a/tools/build/Docker/ubuntu.sh +++ b/tools/build/Docker/ubuntu.sh @@ -4,7 +4,7 @@ apt-get install --no-install-recommends --yes build-essential cmake doxygen git libboost-graph-dev libboost-iostreams-dev libboost-program-options-dev \ libboost-python-dev libboost-regex-dev libboost-serialization-dev \ libboost-thread-dev libcoin-dev libeigen3-dev libgtkglext1-dev \ - libgts-dev libkdtree++-dev libkml-dev libmedc-dev libocct-data-exchange-dev \ + libkdtree++-dev libkml-dev libmedc-dev libocct-data-exchange-dev \ libocct-draw-dev libocct-foundation-dev libocct-modeling-algorithms-dev \ libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev \ libopencv-dev libproj-dev libpyside2-dev libqt5svg5-dev\ From 9f0e9a2af475370f09664f3449298ca733c0a0f5 Mon Sep 17 00:00:00 2001 From: mosfet80 Date: Sat, 30 Nov 2024 08:56:09 +0100 Subject: [PATCH 161/161] Clean MainWindow.cpp Removed unused code --- src/Gui/MainWindow.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index c9ac2a6413dd..27ac049299a9 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -384,8 +384,6 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f) d->status = new StatusBarObserver(); d->actionLabel = new QLabel(statusBar()); d->actionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - // d->actionLabel->setMinimumWidth(120); - d->sizeLabel = new DimensionWidget(statusBar()); statusBar()->addWidget(d->actionLabel, 1); @@ -1200,7 +1198,6 @@ void MainWindow::removeWindow(Gui::MDIView* view, bool close) subwindow->setParent(nullptr); assert(!d->mdiArea->subWindowList().contains(subwindow)); - // d->mdiArea->removeSubWindow(parent); } if(close) @@ -1817,19 +1814,6 @@ void MainWindow::saveWindowSettings(bool canDelay) QString qtver = QStringLiteral("Qt%1.%2").arg(major).arg(minor); QSettings config(vendor, application); -#if 0 - config.beginGroup(qtver); - config.setValue(QStringLiteral("Size"), this->size()); - config.setValue(QStringLiteral("Position"), this->pos()); - config.setValue(QStringLiteral("Maximized"), this->isMaximized()); - config.setValue(QStringLiteral("MainWindowState"), this->saveState()); - config.setValue(QStringLiteral("StatusBar"), this->statusBar()->isVisible()); - config.endGroup(); -#else - // We are migrating from saving qt main window layout state in QSettings to - // FreeCAD parameters, for more control. -#endif - Base::ConnectionBlocker block(d->connParam); d->hGrp->SetBool("Maximized", this->isMaximized()); d->hGrp->SetBool("StatusBar", this->statusBar()->isVisible());