From c017b000fc5225f54531a3e216b04bbb7bb16a81 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Thu, 4 Jan 2024 15:05:07 -0500 Subject: [PATCH 01/34] proof of concept rest machining from prior path gcode --- src/Mod/Path/App/Area.cpp | 178 +++++++++++++++++++++++++++++++++ src/Mod/Path/App/Area.h | 1 + src/Mod/Path/App/AreaPy.xml | 5 + src/Mod/Path/App/AreaPyImp.cpp | 24 +++++ src/Mod/Path/Path/Op/Area.py | 18 +++- 5 files changed, 225 insertions(+), 1 deletion(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index b57317bd4a..d26bd7fff0 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -75,6 +75,7 @@ #include #include #include +#include #include #include "Area.h" @@ -527,6 +528,181 @@ std::shared_ptr Area::getClearedArea(double tipDiameter, double diameter) return clearedArea; } +class ClearedAreaSegmentVisitor : public PathSegmentVisitor +{ +private: + CArea pathSegments; + double maxZ; + double diameter; + + void line(const Base::Vector3d &last, const Base::Vector3d &next) + { + if (last.z <= maxZ && next.z <= maxZ) { + CCurve curve; + curve.append(CVertex{{last.x, last.y}}); + curve.append(CVertex{{next.x, next.y}}); + pathSegments.append(curve); + count++; + } else { + // printf("SKIP!"); + } + } +public: + int count = 0; + + ClearedAreaSegmentVisitor(double maxZ, double diameter) : maxZ(maxZ), diameter(diameter) + { + } + + CArea getClearedArea() + { + CArea result{pathSegments}; + result.Thicken(diameter / 2); + return result; + } + + void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + { + (void)id; + // printf("g0 [ "); + processPt(last); + // printf("] "); + processPts(pts); + // printf("_ "); + processPt(next); + + line(last, next); + // printf("\n"); + } + + void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + { + (void)id; + // printf("g1 [ "); + processPt(last); + // printf("] "); + processPts(pts); + // printf("_ "); + processPt(next); + + line(last, next); + // printf("\n"); + } + + void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) override + { + (void)id; + (void)center; + // printf("g23 [ "); + processPt(last); + // printf("] "); + processPts(pts); + // printf("_ "); + processPt(next); + + // TODO do I need to add last and next to the list??? + // TODO rounding resolution of the function that calls this is too big + Base::Vector3d prev = last; + for (Base::Vector3d p : pts) { + line(prev, p); + prev = p; + } + line(prev, next); + // printf("\n"); + } + + void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, + const std::deque &p, const std::deque &q) override + { + (void)id; + (void)q; // always within the bounds of p + printf("g8x UNHANDLED\n"); + // processPt(last); + // processPts(pts); + // processPts(p); + // processPt(next); + (void)last; + (void)pts; + (void)p; + (void)next; + } + void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override + { + (void)id; + printf("g38 UNHANDLED\n"); + // processPt(last); + // processPt(next); + (void)last; + (void)next; + } + +private: + void processPts(const std::deque &pts) { + for (std::deque::const_iterator it=pts.begin(); pts.end() != it; ++it) { + processPt(*it); + } + } + + void processPt(const Base::Vector3d &pt) { + // printf("(%7.3f, %7.3f, %7.3f) ", pt.x, pt.y, pt.z); + } +}; + +std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax) { + build(); +#define AREA_MY(_param) myParams.PARAM_FNAME(_param) + PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); + PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); + (void)SubjectFill; + (void)ClipFill; + + // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off + // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway + CAreaConfig conf(myParams, /*no_fit_arcs*/ true); + + const double roundPrecision = myParams.Accuracy; + const double buffer = 2 * roundPrecision; + (void)buffer; + (void)JoinType; + (void)EndType; + + Base::Vector3d pos = Base::Vector3d(0, 0, zmax + 1); + printf("getClearedAreaFromPath(path, diameter=%g, zmax=%g:\n", diameter, zmax); + // printf("Gcode:\n"); + for (auto c : path->getCommands()) { + // printf("\t%s ", c->Name.c_str()); + for (std::map::iterator i = c->Parameters.begin(); i != c->Parameters.end(); ++i) { + // printf("%s%g ", i->first.c_str(), i->second); + } + // printf("\n"); + } + + printf("\n"); + printf("GCode walker:\n"); + ClearedAreaSegmentVisitor visitor(zmax, diameter); + PathSegmentWalker walker(*path); + walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); + printf("Count: %d\n", visitor.count); + printf("\n"); + printf("\n"); + + + std::shared_ptr clearedArea = make_shared(&myParams); + //clearedArea->myTrsf = myTrsf; + clearedArea->myTrsf = {}; + if (visitor.count > 0) { + //gp_Trsf trsf(myTrsf.Inverted()); + TopoDS_Shape clearedAreaShape = Area::toShape(visitor.getClearedArea(), false/*, &trsf*/); + clearedArea->add(clearedAreaShape, OperationCompound); + clearedArea->build(); + } else { + clearedArea->myArea = std::make_unique(); + clearedArea->myAreaOpen = std::make_unique(); + } + + return clearedArea; +} + std::shared_ptr Area::getRestArea(std::vector> clearedAreas, double diameter) { build(); PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); @@ -538,6 +714,8 @@ std::shared_ptr Area::getRestArea(std::vector> clear // transform all clearedAreas into our workplane Area clearedAreasInPlane(&myParams); clearedAreasInPlane.myArea.reset(new CArea()); + printf("getRestArea\n"); + printf("\n"); for (std::shared_ptr clearedArea : clearedAreas) { gp_Trsf trsf = clearedArea->myTrsf; trsf.Invert(); diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 5b192ae08a..3dc769dc9a 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -243,6 +243,7 @@ public: const TopoDS_Shape& plane = TopoDS_Shape()); std::shared_ptr getClearedArea(double tipDiameter, double diameter); + std::shared_ptr getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax); std::shared_ptr getRestArea(std::vector> clearedAreas, double diameter); TopoDS_Shape toTopoShape(); diff --git a/src/Mod/Path/App/AreaPy.xml b/src/Mod/Path/App/AreaPy.xml index a38a84aec1..029b245c21 100644 --- a/src/Mod/Path/App/AreaPy.xml +++ b/src/Mod/Path/App/AreaPy.xml @@ -67,6 +67,11 @@ same algorithm + + + + + diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index 817aed0e37..ec6c8d66e8 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -27,6 +27,7 @@ #include // inclusion of the generated files (generated out of AreaPy.xml) +#include "PathPy.h" #include "AreaPy.h" #include "AreaPy.cpp" @@ -152,6 +153,11 @@ static const PyMethodDef areaOverrides[] = { "getClearedArea(tipDiameter, diameter):\n" "Gets the area cleared when a tool maximally clears this area. This method assumes a tool tip diameter 'tipDiameter' traces the full area, and that (perhaps at a different height on the tool) this clears a different region with tool diameter 'diameter'.\n", }, + { + "getClearedAreaFromPath",nullptr,0, + "getClearedAreaFromPath(path, diameter, zmax):\n" + "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax.\n", + }, { "getRestArea",nullptr,0, "getRestArea(clearedAreas, diameter):\n" @@ -415,6 +421,24 @@ PyObject* AreaPy::getClearedArea(PyObject *args) } PY_CATCH_OCC } +PyObject* AreaPy::getClearedAreaFromPath(PyObject *args) +{ + PY_TRY { + PyObject *pyPath; + double diameter, zmax; + if (!PyArg_ParseTuple(args, "Odd", &pyPath, &diameter, &zmax)) + return nullptr; + if (!PyObject_TypeCheck(pyPath, &(PathPy::Type))) { + PyErr_SetString(PyExc_TypeError, "path must be of type PathPy"); + return nullptr; + } + const PathPy *path = static_cast(pyPath); + std::shared_ptr clearedArea = getAreaPtr()->getClearedAreaFromPath(path->getToolpathPtr(), diameter, zmax); + auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); + return Py::new_reference_to(pyClearedArea); + } PY_CATCH_OCC +} + PyObject* AreaPy::getRestArea(PyObject *args) { PY_TRY { diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index 8e329ae4b5..77862274c2 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -272,7 +272,23 @@ class ObjectOp(PathOp.ObjectOp): restSections = [] for section in sections: z = section.getShape().BoundBox.ZMin - sectionClearedAreas = [a for a in clearedAreas if a.getShape().BoundBox.ZMax <= z] + # sectionClearedAreas = [a for a in clearedAreas if a.getShape().BoundBox.ZMax <= z] + sectionClearedAreas = [] + for op in self.job.Operations.Group: + print(op.Name) + if self in [x.Proxy for x in [op] + op.OutListRecursive if hasattr(x, "Proxy")]: + print("found self") + break + if hasattr(op, "Active") and op.Active and op.Path: + tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) + diameter = tool.Diameter.getValueAs("mm") + sectionClearedAreas.append(area.getClearedAreaFromPath(op.Path, diameter, z+0.001)) + debugZ = -1.5 + if debugZ -.1 < z and z < debugZ + .1: + debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) + debugObj.Label = "Debug_{}_{}".format(debugZ, op.Label) + debugObj.Shape = sectionClearedAreas[-1].getShape() + pass restSection = section.getRestArea(sectionClearedAreas, self.tool.Diameter.getValueAs("mm")) restSections.append(restSection) sections = restSections From f68066a219da799164963076082e191c227f90fd Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Fri, 5 Jan 2024 11:46:39 -0500 Subject: [PATCH 02/34] expand cleared area by a small buffer to cover numeric errors --- src/Mod/Path/App/Area.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index d26bd7fff0..de9b33e85d 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -662,7 +662,6 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double const double roundPrecision = myParams.Accuracy; const double buffer = 2 * roundPrecision; - (void)buffer; (void)JoinType; (void)EndType; @@ -679,7 +678,7 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double printf("\n"); printf("GCode walker:\n"); - ClearedAreaSegmentVisitor visitor(zmax, diameter); + ClearedAreaSegmentVisitor visitor(zmax, diameter + buffer); PathSegmentWalker walker(*path); walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); printf("Count: %d\n", visitor.count); From 73e8b5ec877b91e6659a90979e65f65f9eaec76f Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Sun, 7 Jan 2024 16:53:45 -0500 Subject: [PATCH 03/34] fix precision computation --- src/Mod/Path/App/Area.cpp | 108 +++++++++++++++++++++------------ src/Mod/Path/App/AreaPyImp.cpp | 3 + src/Mod/Path/Path/Op/Area.py | 14 ++--- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index de9b33e85d..73b8200327 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -533,7 +533,7 @@ class ClearedAreaSegmentVisitor : public PathSegmentVisitor private: CArea pathSegments; double maxZ; - double diameter; + double radius; void line(const Base::Vector3d &last, const Base::Vector3d &next) { @@ -550,26 +550,27 @@ private: public: int count = 0; - ClearedAreaSegmentVisitor(double maxZ, double diameter) : maxZ(maxZ), diameter(diameter) + ClearedAreaSegmentVisitor(double maxZ, double radius) : maxZ(maxZ), radius(radius) { } CArea getClearedArea() { CArea result{pathSegments}; - result.Thicken(diameter / 2); + result.Thicken(radius); return result; } void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override { (void)id; + (void)pts; // printf("g0 [ "); - processPt(last); + //processPt(last); // printf("] "); - processPts(pts); + //processPts(pts); // printf("_ "); - processPt(next); + //processPt(next); line(last, next); // printf("\n"); @@ -578,12 +579,13 @@ public: void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override { (void)id; + (void)pts; // printf("g1 [ "); - processPt(last); + //processPt(last); // printf("] "); - processPts(pts); + //processPts(pts); // printf("_ "); - processPt(next); + //processPt(next); line(last, next); // printf("\n"); @@ -594,20 +596,29 @@ public: (void)id; (void)center; // printf("g23 [ "); - processPt(last); + // processPt(last); // printf("] "); - processPts(pts); + // processPts(pts); // printf("_ "); - processPt(next); + // processPt(next); - // TODO do I need to add last and next to the list??? - // TODO rounding resolution of the function that calls this is too big - Base::Vector3d prev = last; - for (Base::Vector3d p : pts) { - line(prev, p); - prev = p; - } - line(prev, next); + // Compute cw vs ccw + const Base::Vector3d vdirect = next - last; + const Base::Vector3d vstep = pts[0] - last; + const bool ccw = vstep.x * vdirect.y - vstep.y * vdirect.x > 0; + + // Add an arc + CCurve curve; + curve.append(CVertex{{last.x, last.y}}); + curve.append(CVertex{ccw ? 1 : -1, {next.x, next.y}, {center.x, center.y}}); + pathSegments.append(curve); + count++; + // Base::Vector3d prev = last; + // for (Base::Vector3d p : pts) { + // line(prev, p); + // prev = p; + // } + // line(prev, next); // printf("\n"); } @@ -644,27 +655,25 @@ private: } void processPt(const Base::Vector3d &pt) { - // printf("(%7.3f, %7.3f, %7.3f) ", pt.x, pt.y, pt.z); + printf("(%7.3f, %7.3f, %7.3f) ", pt.x, pt.y, pt.z); } }; std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax) { build(); -#define AREA_MY(_param) myParams.PARAM_FNAME(_param) - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); - (void)SubjectFill; - (void)ClipFill; + + // Precision losses in arc/segment conversions (multiples of Accuracy): + // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc (libarea/Curve.cpp) + // 1 in gcode arc to segment + // 1 in Thicken() cleared area + // 2 in getRestArea target area offset in and back out + // Oversize cleared areas by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this + const double buffer = myParams.Accuracy * 6.3; // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway CAreaConfig conf(myParams, /*no_fit_arcs*/ true); - const double roundPrecision = myParams.Accuracy; - const double buffer = 2 * roundPrecision; - (void)JoinType; - (void)EndType; - Base::Vector3d pos = Base::Vector3d(0, 0, zmax + 1); printf("getClearedAreaFromPath(path, diameter=%g, zmax=%g:\n", diameter, zmax); // printf("Gcode:\n"); @@ -678,7 +687,7 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double printf("\n"); printf("GCode walker:\n"); - ClearedAreaSegmentVisitor visitor(zmax, diameter + buffer); + ClearedAreaSegmentVisitor visitor(zmax, diameter/2 + buffer); PathSegmentWalker walker(*path); walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); printf("Count: %d\n", visitor.count); @@ -707,8 +716,14 @@ std::shared_ptr Area::getRestArea(std::vector> clear PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); - const double roundPrecision = myParams.Accuracy; - const double buffer = 2 * roundPrecision; + // Precision losses in arc/segment conversions (multiples of Accuracy): + // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc (libarea/Curve.cpp) + // 1 in gcode arc to segment + // 1 in Thicken() cleared area + // 2 in getRestArea target area offset in and back out + // Cleared area representations are oversized by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this + const double buffer = myParams.Accuracy * 6.3; + const double roundPrecision = buffer; // transform all clearedAreas into our workplane Area clearedAreasInPlane(&myParams); @@ -724,20 +739,35 @@ std::shared_ptr Area::getRestArea(std::vector> clear &myWorkPlane); } - // remaining = A - prevCleared - CArea remaining(*myArea); + // clearable = offset(offset(A, -dTool/2), dTool/2) + printf("Compute clearable\n"); + CArea clearable(*myArea); + clearable.OffsetWithClipper(-diameter/2, JoinType, EndType, myParams.MiterLimit, roundPrecision); + clearable.OffsetWithClipper(diameter/2, JoinType, EndType, myParams.MiterLimit, roundPrecision); + + // remaining = clearable - prevCleared + printf("Compute remaining\n"); + CArea remaining(clearable); remaining.Clip(toClipperOp(Area::OperationDifference), &*(clearedAreasInPlane.myArea), SubjectFill, ClipFill); - // rest = intersect(A, offset(remaining, dTool)) + // rest = intersect(clearable, offset(remaining, dTool)) + // add buffer to dTool to compensate for oversizing in getClearedAreaFromPath + printf("Compute rest\n"); CArea restCArea(remaining); restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, myParams.MiterLimit, roundPrecision); - restCArea.Clip(toClipperOp(Area::OperationIntersection), &*myArea, SubjectFill, ClipFill); + restCArea.Clip(toClipperOp(Area::OperationIntersection), &clearable, SubjectFill, ClipFill); + printf("Convert CArea to Area (num curves: %d)\n", (int)restCArea.m_curves.size()); + if(restCArea.m_curves.size() == 0) { + return {}; + } + + std::shared_ptr restArea = make_shared(&myParams); gp_Trsf trsf(myTrsf.Inverted()); TopoDS_Shape restShape = Area::toShape(restCArea, false, &trsf); - std::shared_ptr restArea = make_shared(&myParams); restArea->add(restShape, OperationCompound); + printf("return\n"); return restArea; } diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index ec6c8d66e8..4041d7c734 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -464,6 +464,9 @@ PyObject* AreaPy::getRestArea(PyObject *args) } std::shared_ptr restArea = getAreaPtr()->getRestArea(clearedAreas, diameter); + if (!restArea) { + return Py_None; + } auto pyRestArea = Py::asObject(new AreaPy(new Area(*restArea, true))); return Py::new_reference_to(pyRestArea); } PY_CATCH_OCC diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index 77862274c2..e98794b59b 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -283,14 +283,14 @@ class ObjectOp(PathOp.ObjectOp): tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") sectionClearedAreas.append(area.getClearedAreaFromPath(op.Path, diameter, z+0.001)) - debugZ = -1.5 - if debugZ -.1 < z and z < debugZ + .1: - debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) - debugObj.Label = "Debug_{}_{}".format(debugZ, op.Label) - debugObj.Shape = sectionClearedAreas[-1].getShape() - pass + # debugZ = -1.5 + # if debugZ -.1 < z and z < debugZ + .1: + # debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) + # debugObj.Label = "Debug_{}_{}".format(debugZ, op.Label) + # debugObj.Shape = sectionClearedAreas[-1].getShape() restSection = section.getRestArea(sectionClearedAreas, self.tool.Diameter.getValueAs("mm")) - restSections.append(restSection) + if (restSection is not None): + restSections.append(restSection) sections = restSections shapelist = [sec.getShape() for sec in sections] From 58a8d32a164ca89772a4e7ce87934f0584966d3f Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Sun, 7 Jan 2024 17:00:34 -0500 Subject: [PATCH 04/34] do computations at higher precision to mitigate error stackup --- src/Mod/Path/App/Area.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 73b8200327..cb96f3cf71 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -668,11 +668,13 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double // 1 in Thicken() cleared area // 2 in getRestArea target area offset in and back out // Oversize cleared areas by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this - const double buffer = myParams.Accuracy * 6.3; + AreaParams params = myParams; + params.Accuracy = myParams.Accuracy * .7/4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total + const double buffer = myParams.Accuracy * 3; // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway - CAreaConfig conf(myParams, /*no_fit_arcs*/ true); + CAreaConfig conf(params, /*no_fit_arcs*/ true); Base::Vector3d pos = Base::Vector3d(0, 0, zmax + 1); printf("getClearedAreaFromPath(path, diameter=%g, zmax=%g:\n", diameter, zmax); @@ -695,7 +697,7 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double printf("\n"); - std::shared_ptr clearedArea = make_shared(&myParams); + std::shared_ptr clearedArea = make_shared(¶ms); //clearedArea->myTrsf = myTrsf; clearedArea->myTrsf = {}; if (visitor.count > 0) { @@ -722,11 +724,13 @@ std::shared_ptr Area::getRestArea(std::vector> clear // 1 in Thicken() cleared area // 2 in getRestArea target area offset in and back out // Cleared area representations are oversized by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this - const double buffer = myParams.Accuracy * 6.3; - const double roundPrecision = buffer; + AreaParams params = myParams; + params.Accuracy = myParams.Accuracy * .7/4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total + const double buffer = myParams.Accuracy * 3; + const double roundPrecision = params.Accuracy; // transform all clearedAreas into our workplane - Area clearedAreasInPlane(&myParams); + Area clearedAreasInPlane(¶ms); clearedAreasInPlane.myArea.reset(new CArea()); printf("getRestArea\n"); printf("\n"); @@ -742,8 +746,8 @@ std::shared_ptr Area::getRestArea(std::vector> clear // clearable = offset(offset(A, -dTool/2), dTool/2) printf("Compute clearable\n"); CArea clearable(*myArea); - clearable.OffsetWithClipper(-diameter/2, JoinType, EndType, myParams.MiterLimit, roundPrecision); - clearable.OffsetWithClipper(diameter/2, JoinType, EndType, myParams.MiterLimit, roundPrecision); + clearable.OffsetWithClipper(-diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); + clearable.OffsetWithClipper(diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); // remaining = clearable - prevCleared printf("Compute remaining\n"); @@ -754,7 +758,7 @@ std::shared_ptr Area::getRestArea(std::vector> clear // add buffer to dTool to compensate for oversizing in getClearedAreaFromPath printf("Compute rest\n"); CArea restCArea(remaining); - restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, myParams.MiterLimit, roundPrecision); + restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, params.MiterLimit, roundPrecision); restCArea.Clip(toClipperOp(Area::OperationIntersection), &clearable, SubjectFill, ClipFill); printf("Convert CArea to Area (num curves: %d)\n", (int)restCArea.m_curves.size()); @@ -762,7 +766,7 @@ std::shared_ptr Area::getRestArea(std::vector> clear return {}; } - std::shared_ptr restArea = make_shared(&myParams); + std::shared_ptr restArea = make_shared(¶ms); gp_Trsf trsf(myTrsf.Inverted()); TopoDS_Shape restShape = Area::toShape(restCArea, false, &trsf); restArea->add(restShape, OperationCompound); From 833796c297ef531bb39f530526d0a5ee5a1feb67 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Sun, 7 Jan 2024 17:18:02 -0500 Subject: [PATCH 05/34] remove old/deprecated rest machining code --- src/Mod/Path/App/Area.cpp | 32 +------------------------- src/Mod/Path/App/Area.h | 1 - src/Mod/Path/App/AreaPy.xml | 5 ---- src/Mod/Path/App/AreaPyImp.cpp | 17 -------------- src/Mod/Path/Path/Op/Area.py | 34 --------------------------- src/Mod/Path/Path/Op/PocketBase.py | 37 ++++-------------------------- 6 files changed, 5 insertions(+), 121 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index cb96f3cf71..b979a6d155 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -497,37 +497,6 @@ void Area::add(const TopoDS_Shape& shape, short op) { myShapes.emplace_back(op, shape); } -std::shared_ptr Area::getClearedArea(double tipDiameter, double diameter) { - build(); -#define AREA_MY(_param) myParams.PARAM_FNAME(_param) - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); - (void)SubjectFill; - (void)ClipFill; - - // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off - // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway - CAreaConfig conf(myParams, /*no_fit_arcs*/ true); - - const double roundPrecision = myParams.Accuracy; - const double buffer = 2 * roundPrecision; - - // A = myArea - // prevCenters = offset(A, -rTip) - const double rTip = tipDiameter / 2.; - CArea prevCenter(*myArea); - prevCenter.OffsetWithClipper(-rTip, JoinType, EndType, myParams.MiterLimit, roundPrecision); - - // prevCleared = offset(prevCenter, r). - CArea prevCleared(prevCenter); - prevCleared.OffsetWithClipper(diameter / 2. + buffer, JoinType, EndType, myParams.MiterLimit, roundPrecision); - - std::shared_ptr clearedArea = make_shared(*this); - clearedArea->myArea.reset(new CArea(prevCleared)); - - return clearedArea; -} - class ClearedAreaSegmentVisitor : public PathSegmentVisitor { private: @@ -715,6 +684,7 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double std::shared_ptr Area::getRestArea(std::vector> clearedAreas, double diameter) { build(); +#define AREA_MY(_param) myParams.PARAM_FNAME(_param) PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 3dc769dc9a..af21097705 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -242,7 +242,6 @@ public: const std::vector& heights = std::vector(), const TopoDS_Shape& plane = TopoDS_Shape()); - std::shared_ptr getClearedArea(double tipDiameter, double diameter); std::shared_ptr getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax); std::shared_ptr getRestArea(std::vector> clearedAreas, double diameter); TopoDS_Shape toTopoShape(); diff --git a/src/Mod/Path/App/AreaPy.xml b/src/Mod/Path/App/AreaPy.xml index 029b245c21..209765c3e0 100644 --- a/src/Mod/Path/App/AreaPy.xml +++ b/src/Mod/Path/App/AreaPy.xml @@ -62,11 +62,6 @@ same algorithm - - - - - diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index 4041d7c734..5ee87a3a9c 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -148,11 +148,6 @@ static const PyMethodDef areaOverrides[] = { "\n* plane (None): optional shape to specify a section plane. If not give, the current workplane\n" "of this Area is used if section mode is 'Workplane'.", }, - { - "getClearedArea",nullptr,0, - "getClearedArea(tipDiameter, diameter):\n" - "Gets the area cleared when a tool maximally clears this area. This method assumes a tool tip diameter 'tipDiameter' traces the full area, and that (perhaps at a different height on the tool) this clears a different region with tool diameter 'diameter'.\n", - }, { "getClearedAreaFromPath",nullptr,0, "getClearedAreaFromPath(path, diameter, zmax):\n" @@ -409,18 +404,6 @@ PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds) } PY_CATCH_OCC } -PyObject* AreaPy::getClearedArea(PyObject *args) -{ - PY_TRY { - double tipDiameter, diameter; - if (!PyArg_ParseTuple(args, "dd", &tipDiameter, &diameter)) - return nullptr; - std::shared_ptr clearedArea = getAreaPtr()->getClearedArea(tipDiameter, diameter); - auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); - return Py::new_reference_to(pyClearedArea); - } PY_CATCH_OCC -} - PyObject* AreaPy::getClearedAreaFromPath(PyObject *args) { PY_TRY { diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index e98794b59b..36d0c923eb 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -240,39 +240,9 @@ class ObjectOp(PathOp.ObjectOp): # Rest machining self.sectionShapes = self.sectionShapes + [section.toTopoShape() for section in sections] if hasattr(obj, "UseRestMachining") and obj.UseRestMachining: - # Loop through prior operations - clearedAreas = [] - foundSelf = False - for op in self.job.Operations.Group: - if foundSelf: - break - oplist = [op] + op.OutListRecursive - oplist = list(filter(lambda op: hasattr(op, "Active"), oplist)) - for op in oplist: - if op.Proxy == self: - # Ignore self, and all later operations - foundSelf = True - break - if hasattr(op, "RestMachiningRegions") and op.Active: - if hasattr(op, "RestMachiningRegionsNeedRecompute") and op.RestMachiningRegionsNeedRecompute: - Path.Log.warning( - translate("PathAreaOp", "Previous operation %s is required for rest machining, but it has no stored rest machining metadata. Recomputing to generate this metadata...") % op.Label - ) - op.recompute() - - tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) - diameter = tool.Diameter.getValueAs("mm") - def shapeToArea(shape): - area = Path.Area() - area.setPlane(PathUtils.makeWorkplane(shape)) - area.add(shape) - return area - opClearedAreas = [shapeToArea(pa).getClearedArea(diameter, diameter) for pa in op.RestMachiningRegions.SubShapes] - clearedAreas.extend(opClearedAreas) restSections = [] for section in sections: z = section.getShape().BoundBox.ZMin - # sectionClearedAreas = [a for a in clearedAreas if a.getShape().BoundBox.ZMax <= z] sectionClearedAreas = [] for op in self.job.Operations.Group: print(op.Name) @@ -497,10 +467,6 @@ class ObjectOp(PathOp.ObjectOp): ) ) - if hasattr(obj, "RestMachiningRegions"): - obj.RestMachiningRegions = Part.makeCompound(self.sectionShapes) - if hasattr(obj, "RestMachiningRegionsNeedRecompute"): - obj.RestMachiningRegionsNeedRecompute = False Path.Log.debug("obj.Name: " + str(obj.Name) + "\n\n") return sims diff --git a/src/Mod/Path/Path/Op/PocketBase.py b/src/Mod/Path/Path/Op/PocketBase.py index 829dd865c3..9dc30836de 100644 --- a/src/Mod/Path/Path/Op/PocketBase.py +++ b/src/Mod/Path/Path/Op/PocketBase.py @@ -194,16 +194,6 @@ class ObjectPocket(PathAreaOp.ObjectOp): "Skips machining regions that have already been cleared by previous operations.", ), ) - obj.addProperty( - "Part::PropertyPartShape", - "RestMachiningRegions", - "Pocket", - QT_TRANSLATE_NOOP( - "App::Property", - "The areas cleared by this operation, one area per height, stored as a compound part. Used internally for rest machining.", - ), - ) - obj.setEditorMode("RestMachiningRegions", 2) # hide for n in self.pocketPropertyEnumerations(): setattr(obj, n[0], n[1]) @@ -277,29 +267,10 @@ class ObjectPocket(PathAreaOp.ObjectOp): ), ) - if not hasattr(obj, "RestMachiningRegions"): - obj.addProperty( - "Part::PropertyPartShape", - "RestMachiningRegions", - "Pocket", - QT_TRANSLATE_NOOP( - "App::Property", - "The areas cleared by this operation, one area per height, stored as a compound part. Used internally for rest machining.", - ), - ) - obj.setEditorMode("RestMachiningRegions", 2) # hide - - obj.addProperty( - "App::PropertyBool", - "RestMachiningRegionsNeedRecompute", - "Pocket", - QT_TRANSLATE_NOOP( - "App::Property", - "Flag to indicate that the rest machining regions have never been computed, and must be recomputed before being used.", - ), - ) - obj.setEditorMode("RestMachiningRegionsNeedRecompute", 2) # hide - obj.RestMachiningRegionsNeedRecompute = True + if hasattr(obj, "RestMachiningRegions"): + obj.removeProperty("RestMachiningRegions") + if hasattr(obj, "RestMachiningRegionsNeedRecompute"): + obj.removeProperty("RestMachiningRegionsNeedRecompute") Path.Log.track() From dddd13f7c008667a0157157424b475ac9e28e4b2 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Sun, 7 Jan 2024 17:23:03 -0500 Subject: [PATCH 06/34] rename getClearedAreaFromPath -> getClearedArea --- src/Mod/Path/App/Area.cpp | 6 +++--- src/Mod/Path/App/Area.h | 2 +- src/Mod/Path/App/AreaPy.xml | 2 +- src/Mod/Path/App/AreaPyImp.cpp | 8 ++++---- src/Mod/Path/Path/Op/Area.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index b979a6d155..30d680ff12 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -628,7 +628,7 @@ private: } }; -std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax) { +std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter, double zmax) { build(); // Precision losses in arc/segment conversions (multiples of Accuracy): @@ -646,7 +646,7 @@ std::shared_ptr Area::getClearedAreaFromPath(const Toolpath *path, double CAreaConfig conf(params, /*no_fit_arcs*/ true); Base::Vector3d pos = Base::Vector3d(0, 0, zmax + 1); - printf("getClearedAreaFromPath(path, diameter=%g, zmax=%g:\n", diameter, zmax); + printf("getClearedArea(path, diameter=%g, zmax=%g:\n", diameter, zmax); // printf("Gcode:\n"); for (auto c : path->getCommands()) { // printf("\t%s ", c->Name.c_str()); @@ -725,7 +725,7 @@ std::shared_ptr Area::getRestArea(std::vector> clear remaining.Clip(toClipperOp(Area::OperationDifference), &*(clearedAreasInPlane.myArea), SubjectFill, ClipFill); // rest = intersect(clearable, offset(remaining, dTool)) - // add buffer to dTool to compensate for oversizing in getClearedAreaFromPath + // add buffer to dTool to compensate for oversizing in getClearedArea printf("Compute rest\n"); CArea restCArea(remaining); restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, params.MiterLimit, roundPrecision); diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index af21097705..8056f4a3da 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -242,7 +242,7 @@ public: const std::vector& heights = std::vector(), const TopoDS_Shape& plane = TopoDS_Shape()); - std::shared_ptr getClearedAreaFromPath(const Toolpath *path, double diameter, double zmax); + std::shared_ptr getClearedArea(const Toolpath *path, double diameter, double zmax); std::shared_ptr getRestArea(std::vector> clearedAreas, double diameter); TopoDS_Shape toTopoShape(); diff --git a/src/Mod/Path/App/AreaPy.xml b/src/Mod/Path/App/AreaPy.xml index 209765c3e0..a38a84aec1 100644 --- a/src/Mod/Path/App/AreaPy.xml +++ b/src/Mod/Path/App/AreaPy.xml @@ -62,7 +62,7 @@ same algorithm - + diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index 5ee87a3a9c..a0a85b930b 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -149,8 +149,8 @@ static const PyMethodDef areaOverrides[] = { "of this Area is used if section mode is 'Workplane'.", }, { - "getClearedAreaFromPath",nullptr,0, - "getClearedAreaFromPath(path, diameter, zmax):\n" + "getClearedArea",nullptr,0, + "getClearedArea(path, diameter, zmax):\n" "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax.\n", }, { @@ -404,7 +404,7 @@ PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds) } PY_CATCH_OCC } -PyObject* AreaPy::getClearedAreaFromPath(PyObject *args) +PyObject* AreaPy::getClearedArea(PyObject *args) { PY_TRY { PyObject *pyPath; @@ -416,7 +416,7 @@ PyObject* AreaPy::getClearedAreaFromPath(PyObject *args) return nullptr; } const PathPy *path = static_cast(pyPath); - std::shared_ptr clearedArea = getAreaPtr()->getClearedAreaFromPath(path->getToolpathPtr(), diameter, zmax); + std::shared_ptr clearedArea = getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax); auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); return Py::new_reference_to(pyClearedArea); } PY_CATCH_OCC diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index 36d0c923eb..5f9e3a759f 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -252,7 +252,7 @@ class ObjectOp(PathOp.ObjectOp): if hasattr(op, "Active") and op.Active and op.Path: tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") - sectionClearedAreas.append(area.getClearedAreaFromPath(op.Path, diameter, z+0.001)) + sectionClearedAreas.append(area.getClearedArea(op.Path, diameter, z+0.001)) # debugZ = -1.5 # if debugZ -.1 < z and z < debugZ + .1: # debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) From 41c1206d803500ef58227c05ba6465d8fc34f292 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Mon, 8 Jan 2024 00:52:19 -0500 Subject: [PATCH 07/34] Important performance optimization: union Thicken() polygons individually, not en masse --- src/Mod/Path/libarea/AreaClipper.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Mod/Path/libarea/AreaClipper.cpp b/src/Mod/Path/libarea/AreaClipper.cpp index d3e9ff8397..48f3dc93af 100644 --- a/src/Mod/Path/libarea/AreaClipper.cpp +++ b/src/Mod/Path/libarea/AreaClipper.cpp @@ -253,11 +253,15 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou { Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - + pp_new.clear(); for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) { + c.Clear(); + c.AddPaths(pp_new, ptSubject, true); + pp_new.clear(); pts_for_AddVertex.clear(); + const CCurve& curve = *It; const CVertex* prev_vertex = NULL; for(std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) @@ -278,10 +282,9 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou } prev_vertex = &vertex; } + c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); } - pp_new.clear(); - c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); // reverse all the resulting polygons TPolyPolygon copy = pp_new; From 0b219307516a5ca873ae25b5d7ac07c202d69487 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Mon, 8 Jan 2024 14:33:19 -0500 Subject: [PATCH 08/34] add bbox check to getClearedArea to filter out irrelevant gcode --- src/Mod/Path/App/Area.cpp | 47 ++++++++++++++++------------------ src/Mod/Path/App/Area.h | 2 +- src/Mod/Path/App/AreaPyImp.cpp | 16 ++++++++---- src/Mod/Path/Path/Op/Area.py | 5 ++-- 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 30d680ff12..7c9ed4ce00 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -503,24 +503,26 @@ private: CArea pathSegments; double maxZ; double radius; + Base::BoundBox3d bbox; void line(const Base::Vector3d &last, const Base::Vector3d &next) { if (last.z <= maxZ && next.z <= maxZ) { - CCurve curve; - curve.append(CVertex{{last.x, last.y}}); - curve.append(CVertex{{next.x, next.y}}); - pathSegments.append(curve); - count++; - } else { - // printf("SKIP!"); + Base::BoundBox2d segBox = {}; + segBox.Add({last.x, last.y}); + segBox.Add({next.x, next.y}); + if (bbox.Intersect(segBox)) { + CCurve curve; + curve.append(CVertex{{last.x, last.y}}); + curve.append(CVertex{{next.x, next.y}}); + pathSegments.append(curve); + } } } public: - int count = 0; - - ClearedAreaSegmentVisitor(double maxZ, double radius) : maxZ(maxZ), radius(radius) + ClearedAreaSegmentVisitor(double maxZ, double radius, Base::BoundBox3d bbox) : maxZ(maxZ), radius(radius), bbox(bbox) { + bbox.Enlarge(radius); } CArea getClearedArea() @@ -581,7 +583,6 @@ public: curve.append(CVertex{{last.x, last.y}}); curve.append(CVertex{ccw ? 1 : -1, {next.x, next.y}, {center.x, center.y}}); pathSegments.append(curve); - count++; // Base::Vector3d prev = last; // for (Base::Vector3d p : pts) { // line(prev, p); @@ -597,10 +598,10 @@ public: (void)id; (void)q; // always within the bounds of p printf("g8x UNHANDLED\n"); - // processPt(last); - // processPts(pts); - // processPts(p); - // processPt(next); + processPt(last); + processPts(pts); + processPts(p); + processPt(next); (void)last; (void)pts; (void)p; @@ -608,10 +609,8 @@ public: } void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override { + // probe operation; clears nothing (void)id; - printf("g38 UNHANDLED\n"); - // processPt(last); - // processPt(next); (void)last; (void)next; } @@ -628,7 +627,7 @@ private: } }; -std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter, double zmax) { +std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter, double zmax, Base::BoundBox3d bbox) { build(); // Precision losses in arc/segment conversions (multiples of Accuracy): @@ -658,20 +657,18 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter printf("\n"); printf("GCode walker:\n"); - ClearedAreaSegmentVisitor visitor(zmax, diameter/2 + buffer); + ClearedAreaSegmentVisitor visitor(zmax, diameter/2 + buffer, bbox); PathSegmentWalker walker(*path); walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); - printf("Count: %d\n", visitor.count); printf("\n"); printf("\n"); std::shared_ptr clearedArea = make_shared(¶ms); - //clearedArea->myTrsf = myTrsf; clearedArea->myTrsf = {}; - if (visitor.count > 0) { - //gp_Trsf trsf(myTrsf.Inverted()); - TopoDS_Shape clearedAreaShape = Area::toShape(visitor.getClearedArea(), false/*, &trsf*/); + const CArea ca = visitor.getClearedArea(); + if (ca.m_curves.size() > 0) { + TopoDS_Shape clearedAreaShape = Area::toShape(ca, false); clearedArea->add(clearedAreaShape, OperationCompound); clearedArea->build(); } else { diff --git a/src/Mod/Path/App/Area.h b/src/Mod/Path/App/Area.h index 8056f4a3da..e79a62577d 100644 --- a/src/Mod/Path/App/Area.h +++ b/src/Mod/Path/App/Area.h @@ -242,7 +242,7 @@ public: const std::vector& heights = std::vector(), const TopoDS_Shape& plane = TopoDS_Shape()); - std::shared_ptr getClearedArea(const Toolpath *path, double diameter, double zmax); + std::shared_ptr getClearedArea(const Toolpath *path, double diameter, double zmax, Base::BoundBox3d bbox); std::shared_ptr getRestArea(std::vector> clearedAreas, double diameter); TopoDS_Shape toTopoShape(); diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index a0a85b930b..bbe4182c23 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" +#include #include #include #include @@ -150,8 +151,8 @@ static const PyMethodDef areaOverrides[] = { }, { "getClearedArea",nullptr,0, - "getClearedArea(path, diameter, zmax):\n" - "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax.\n", + "getClearedArea(path, diameter, zmax, bbox):\n" + "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax and path segments that don't affect space within bbox.\n", }, { "getRestArea",nullptr,0, @@ -407,16 +408,21 @@ PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds) PyObject* AreaPy::getClearedArea(PyObject *args) { PY_TRY { - PyObject *pyPath; + PyObject *pyPath, *pyBbox; double diameter, zmax; - if (!PyArg_ParseTuple(args, "Odd", &pyPath, &diameter, &zmax)) + if (!PyArg_ParseTuple(args, "OddO", &pyPath, &diameter, &zmax, &pyBbox)) return nullptr; if (!PyObject_TypeCheck(pyPath, &(PathPy::Type))) { PyErr_SetString(PyExc_TypeError, "path must be of type PathPy"); return nullptr; } + if (!PyObject_TypeCheck(pyBbox, &(Base::BoundBoxPy::Type))) { + PyErr_SetString(PyExc_TypeError, "bbox must be of type BoundBoxPy"); + return nullptr; + } const PathPy *path = static_cast(pyPath); - std::shared_ptr clearedArea = getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax); + const Py::BoundingBox bbox(pyBbox, false); + std::shared_ptr clearedArea = getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax, bbox.getValue()); auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); return Py::new_reference_to(pyClearedArea); } PY_CATCH_OCC diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index 5f9e3a759f..e88440f55f 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -242,7 +242,8 @@ class ObjectOp(PathOp.ObjectOp): if hasattr(obj, "UseRestMachining") and obj.UseRestMachining: restSections = [] for section in sections: - z = section.getShape().BoundBox.ZMin + bbox = section.getShape().BoundBox + z = bbox.ZMin sectionClearedAreas = [] for op in self.job.Operations.Group: print(op.Name) @@ -252,7 +253,7 @@ class ObjectOp(PathOp.ObjectOp): if hasattr(op, "Active") and op.Active and op.Path: tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") - sectionClearedAreas.append(area.getClearedArea(op.Path, diameter, z+0.001)) + sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+0.001, bbox)) # debugZ = -1.5 # if debugZ -.1 < z and z < debugZ + .1: # debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) From 4a35e788c24c9a324e514c91411f6e9002ca90cd Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Mon, 8 Jan 2024 19:31:00 -0500 Subject: [PATCH 09/34] add support for drilling gcode --- src/Mod/Path/App/Area.cpp | 44 +++++++++++++++++++++++++++--------- src/Mod/Path/Path/Op/Area.py | 3 ++- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 7c9ed4ce00..5b13bd75cc 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -501,10 +501,27 @@ class ClearedAreaSegmentVisitor : public PathSegmentVisitor { private: CArea pathSegments; + CArea holes; double maxZ; double radius; Base::BoundBox3d bbox; + void point(const Base::Vector3d &p) + { + printf("Point? (%.0f, %.0f, %.0f) ", p.x, p.y, p.z); + if (p.z <= maxZ) { + if (bbox.MinX <= p.x && p.x <= bbox.MaxX && bbox.MinY <= p.y && p.y <= bbox.MaxY) { + CCurve curve; + curve.append(CVertex{{p.x + radius, p.y}}); + curve.append(CVertex{1, {p.x - radius, p.y}, {p.x, p.y}}); + curve.append(CVertex{1, {p.x + radius, p.y}, {p.x, p.y}}); + holes.append(curve); + printf("accepted"); + } + } + printf("\n"); + } + void line(const Base::Vector3d &last, const Base::Vector3d &next) { if (last.z <= maxZ && next.z <= maxZ) { @@ -529,6 +546,7 @@ public: { CArea result{pathSegments}; result.Thicken(radius); + result.Union(holes); return result; } @@ -593,19 +611,20 @@ public: } void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &p, const std::deque &q) override + const std::deque &plist, const std::deque &qlist) override { + // (peck) drilling (void)id; - (void)q; // always within the bounds of p - printf("g8x UNHANDLED\n"); - processPt(last); - processPts(pts); - processPts(p); - processPt(next); - (void)last; - (void)pts; - (void)p; - (void)next; + (void)qlist; // pecks are always within the bounds of plist + + point(last); + for (const auto p : pts) { + point(p); + } + for (const auto p : plist) { + point(p); + } + point(next); } void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override { @@ -638,6 +657,8 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter // Oversize cleared areas by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this AreaParams params = myParams; params.Accuracy = myParams.Accuracy * .7/4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total + params.SubjectFill = ClipperLib::pftNonZero; + params.ClipFill = ClipperLib::pftNonZero; const double buffer = myParams.Accuracy * 3; // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off @@ -667,6 +688,7 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter std::shared_ptr clearedArea = make_shared(¶ms); clearedArea->myTrsf = {}; const CArea ca = visitor.getClearedArea(); + printf("Cleared area segments: %ld\n", ca.m_curves.size()); if (ca.m_curves.size() > 0) { TopoDS_Shape clearedAreaShape = Area::toShape(ca, false); clearedArea->add(clearedAreaShape, OperationCompound); diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index e88440f55f..5ec88b640f 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -253,7 +253,8 @@ class ObjectOp(PathOp.ObjectOp): if hasattr(op, "Active") and op.Active and op.Path: tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") - sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+0.001, bbox)) + dz = 0 if not hasattr(tool, "TipAngle") else -PathUtils.drillTipLength(tool) # for drills, dz moves to the full width part of the tool + sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+dz+0.001, bbox)) # debugZ = -1.5 # if debugZ -.1 < z and z < debugZ + .1: # debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) From 257b500779ca03fd1c2a456bfdd02c814fe62b16 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Mon, 8 Jan 2024 19:44:22 -0500 Subject: [PATCH 10/34] cleanup --- src/Mod/Path/App/Area.cpp | 67 ---------------------------- src/Mod/Path/App/AreaPyImp.cpp | 2 +- src/Mod/Path/Path/Op/Area.py | 9 +--- src/Mod/Path/libarea/AreaClipper.cpp | 10 ++--- 4 files changed, 7 insertions(+), 81 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index 5b13bd75cc..39fbc884af 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -508,7 +508,6 @@ private: void point(const Base::Vector3d &p) { - printf("Point? (%.0f, %.0f, %.0f) ", p.x, p.y, p.z); if (p.z <= maxZ) { if (bbox.MinX <= p.x && p.x <= bbox.MaxX && bbox.MinY <= p.y && p.y <= bbox.MaxY) { CCurve curve; @@ -516,10 +515,8 @@ private: curve.append(CVertex{1, {p.x - radius, p.y}, {p.x, p.y}}); curve.append(CVertex{1, {p.x + radius, p.y}, {p.x, p.y}}); holes.append(curve); - printf("accepted"); } } - printf("\n"); } void line(const Base::Vector3d &last, const Base::Vector3d &next) @@ -554,42 +551,20 @@ public: { (void)id; (void)pts; - // printf("g0 [ "); - //processPt(last); - // printf("] "); - //processPts(pts); - // printf("_ "); - //processPt(next); - line(last, next); - // printf("\n"); } void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override { (void)id; (void)pts; - // printf("g1 [ "); - //processPt(last); - // printf("] "); - //processPts(pts); - // printf("_ "); - //processPt(next); - line(last, next); - // printf("\n"); } void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) override { (void)id; (void)center; - // printf("g23 [ "); - // processPt(last); - // printf("] "); - // processPts(pts); - // printf("_ "); - // processPt(next); // Compute cw vs ccw const Base::Vector3d vdirect = next - last; @@ -601,13 +576,6 @@ public: curve.append(CVertex{{last.x, last.y}}); curve.append(CVertex{ccw ? 1 : -1, {next.x, next.y}, {center.x, center.y}}); pathSegments.append(curve); - // Base::Vector3d prev = last; - // for (Base::Vector3d p : pts) { - // line(prev, p); - // prev = p; - // } - // line(prev, next); - // printf("\n"); } void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, @@ -633,17 +601,6 @@ public: (void)last; (void)next; } - -private: - void processPts(const std::deque &pts) { - for (std::deque::const_iterator it=pts.begin(); pts.end() != it; ++it) { - processPt(*it); - } - } - - void processPt(const Base::Vector3d &pt) { - printf("(%7.3f, %7.3f, %7.3f) ", pt.x, pt.y, pt.z); - } }; std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter, double zmax, Base::BoundBox3d bbox) { @@ -665,30 +622,13 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway CAreaConfig conf(params, /*no_fit_arcs*/ true); - Base::Vector3d pos = Base::Vector3d(0, 0, zmax + 1); - printf("getClearedArea(path, diameter=%g, zmax=%g:\n", diameter, zmax); - // printf("Gcode:\n"); - for (auto c : path->getCommands()) { - // printf("\t%s ", c->Name.c_str()); - for (std::map::iterator i = c->Parameters.begin(); i != c->Parameters.end(); ++i) { - // printf("%s%g ", i->first.c_str(), i->second); - } - // printf("\n"); - } - - printf("\n"); - printf("GCode walker:\n"); ClearedAreaSegmentVisitor visitor(zmax, diameter/2 + buffer, bbox); PathSegmentWalker walker(*path); walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); - printf("\n"); - printf("\n"); - std::shared_ptr clearedArea = make_shared(¶ms); clearedArea->myTrsf = {}; const CArea ca = visitor.getClearedArea(); - printf("Cleared area segments: %ld\n", ca.m_curves.size()); if (ca.m_curves.size() > 0) { TopoDS_Shape clearedAreaShape = Area::toShape(ca, false); clearedArea->add(clearedAreaShape, OperationCompound); @@ -721,8 +661,6 @@ std::shared_ptr Area::getRestArea(std::vector> clear // transform all clearedAreas into our workplane Area clearedAreasInPlane(¶ms); clearedAreasInPlane.myArea.reset(new CArea()); - printf("getRestArea\n"); - printf("\n"); for (std::shared_ptr clearedArea : clearedAreas) { gp_Trsf trsf = clearedArea->myTrsf; trsf.Invert(); @@ -733,24 +671,20 @@ std::shared_ptr Area::getRestArea(std::vector> clear } // clearable = offset(offset(A, -dTool/2), dTool/2) - printf("Compute clearable\n"); CArea clearable(*myArea); clearable.OffsetWithClipper(-diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); clearable.OffsetWithClipper(diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); // remaining = clearable - prevCleared - printf("Compute remaining\n"); CArea remaining(clearable); remaining.Clip(toClipperOp(Area::OperationDifference), &*(clearedAreasInPlane.myArea), SubjectFill, ClipFill); // rest = intersect(clearable, offset(remaining, dTool)) // add buffer to dTool to compensate for oversizing in getClearedArea - printf("Compute rest\n"); CArea restCArea(remaining); restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, params.MiterLimit, roundPrecision); restCArea.Clip(toClipperOp(Area::OperationIntersection), &clearable, SubjectFill, ClipFill); - printf("Convert CArea to Area (num curves: %d)\n", (int)restCArea.m_curves.size()); if(restCArea.m_curves.size() == 0) { return {}; } @@ -760,7 +694,6 @@ std::shared_ptr Area::getRestArea(std::vector> clear TopoDS_Shape restShape = Area::toShape(restCArea, false, &trsf); restArea->add(restShape, OperationCompound); - printf("return\n"); return restArea; } diff --git a/src/Mod/Path/App/AreaPyImp.cpp b/src/Mod/Path/App/AreaPyImp.cpp index bbe4182c23..bbfb1b5088 100644 --- a/src/Mod/Path/App/AreaPyImp.cpp +++ b/src/Mod/Path/App/AreaPyImp.cpp @@ -152,7 +152,7 @@ static const PyMethodDef areaOverrides[] = { { "getClearedArea",nullptr,0, "getClearedArea(path, diameter, zmax, bbox):\n" - "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax and path segments that don't affect space within bbox.\n", + "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax and path segments that don't affect space within the x/y space of bbox.\n", }, { "getRestArea",nullptr,0, diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index 5ec88b640f..fd831341b2 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -246,20 +246,13 @@ class ObjectOp(PathOp.ObjectOp): z = bbox.ZMin sectionClearedAreas = [] for op in self.job.Operations.Group: - print(op.Name) if self in [x.Proxy for x in [op] + op.OutListRecursive if hasattr(x, "Proxy")]: - print("found self") break if hasattr(op, "Active") and op.Active and op.Path: tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") - dz = 0 if not hasattr(tool, "TipAngle") else -PathUtils.drillTipLength(tool) # for drills, dz moves to the full width part of the tool + dz = 0 if not hasattr(tool, "TipAngle") else -PathUtils.drillTipLength(tool) # for drills, dz translates to the full width part of the tool sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+dz+0.001, bbox)) - # debugZ = -1.5 - # if debugZ -.1 < z and z < debugZ + .1: - # debugObj = obj.Document.addObject("Part::Feature", "Debug_{}_{}".format(debugZ, op.Name)) - # debugObj.Label = "Debug_{}_{}".format(debugZ, op.Label) - # debugObj.Shape = sectionClearedAreas[-1].getShape() restSection = section.getRestArea(sectionClearedAreas, self.tool.Diameter.getValueAs("mm")) if (restSection is not None): restSections.append(restSection) diff --git a/src/Mod/Path/libarea/AreaClipper.cpp b/src/Mod/Path/libarea/AreaClipper.cpp index 48f3dc93af..1ee608bbba 100644 --- a/src/Mod/Path/libarea/AreaClipper.cpp +++ b/src/Mod/Path/libarea/AreaClipper.cpp @@ -252,14 +252,14 @@ static void MakeObround(const Point &pt0, const CVertex &vt1, double radius) static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, double radius) { Clipper c; - c.StrictlySimple(CArea::m_clipper_simple); + c.StrictlySimple(CArea::m_clipper_simple); pp_new.clear(); for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) { - c.Clear(); - c.AddPaths(pp_new, ptSubject, true); - pp_new.clear(); + c.Clear(); + c.AddPaths(pp_new, ptSubject, true); + pp_new.clear(); pts_for_AddVertex.clear(); const CCurve& curve = *It; @@ -282,7 +282,7 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou } prev_vertex = &vertex; } - c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); + c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); } From 15306066db3993c99d1dde0abe618c58e59a00d2 Mon Sep 17 00:00:00 2001 From: David Kaufman Date: Thu, 11 Jan 2024 22:49:11 -0500 Subject: [PATCH 11/34] replace hard coded 1um tolerance with job.GeometryTolerance --- src/Mod/Path/Path/Op/Area.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Path/Path/Op/Area.py b/src/Mod/Path/Path/Op/Area.py index fd831341b2..5a3756cacd 100644 --- a/src/Mod/Path/Path/Op/Area.py +++ b/src/Mod/Path/Path/Op/Area.py @@ -252,7 +252,7 @@ class ObjectOp(PathOp.ObjectOp): tool = op.Proxy.tool if hasattr(op.Proxy, "tool") else op.ToolController.Proxy.getTool(op.ToolController) diameter = tool.Diameter.getValueAs("mm") dz = 0 if not hasattr(tool, "TipAngle") else -PathUtils.drillTipLength(tool) # for drills, dz translates to the full width part of the tool - sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+dz+0.001, bbox)) + sectionClearedAreas.append(section.getClearedArea(op.Path, diameter, z+dz+self.job.GeometryTolerance.getValueAs("mm"), bbox)) restSection = section.getRestArea(sectionClearedAreas, self.tool.Diameter.getValueAs("mm")) if (restSection is not None): restSections.append(restSection) From eab628460d92926597ffe8b5fc06c34564da9051 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Sun, 14 Jan 2024 10:43:39 +0100 Subject: [PATCH 12/34] Material: fix Qt6 build failure QRegExp has been replaced with QRegularExpression and isn't part of the base of Qt6 any more --- src/Mod/Material/App/MaterialLoader.cpp | 14 +++++--------- src/Mod/Material/App/MaterialValue.cpp | 5 ++--- src/Mod/Material/App/ModelLibrary.cpp | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Mod/Material/App/MaterialLoader.cpp b/src/Mod/Material/App/MaterialLoader.cpp index a6ab7a5a8a..fc0e6f14c7 100644 --- a/src/Mod/Material/App/MaterialLoader.cpp +++ b/src/Mod/Material/App/MaterialLoader.cpp @@ -21,16 +21,12 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include -#endif - #include #include #include #include - -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) -#include +#include +#include #endif #include @@ -85,7 +81,7 @@ std::shared_ptr> MaterialYamlEntry::readList(const YAML::Node& n QVariant nodeValue; if (isImageList) { nodeValue = QString::fromStdString(it->as()) - .remove(QRegExp(QString::fromStdString("[\r\n]"))); + .remove(QRegularExpression(QString::fromStdString("[\r\n]"))); } else { nodeValue = QString::fromStdString(it->as()); @@ -247,7 +243,7 @@ void MaterialYamlEntry::addToTree( QString::fromStdString((itp->second).as()); if (type == MaterialValue::Image) { propertyValue = - propertyValue.remove(QRegExp(QString::fromStdString("[\r\n]"))); + propertyValue.remove(QRegularExpression(QString::fromStdString("[\r\n]"))); } finalModel->setPhysicalValue(QString::fromStdString(propertyName), propertyValue); @@ -314,7 +310,7 @@ void MaterialYamlEntry::addToTree( QString::fromStdString((itp->second).as()); if (type == MaterialValue::Image) { propertyValue = - propertyValue.remove(QRegExp(QString::fromStdString("[\r\n]"))); + propertyValue.remove(QRegularExpression(QString::fromStdString("[\r\n]"))); } finalModel->setAppearanceValue(QString::fromStdString(propertyName), propertyValue); diff --git a/src/Mod/Material/App/MaterialValue.cpp b/src/Mod/Material/App/MaterialValue.cpp index a9ccc6513e..f27bfed838 100644 --- a/src/Mod/Material/App/MaterialValue.cpp +++ b/src/Mod/Material/App/MaterialValue.cpp @@ -21,11 +21,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif -#include - #include #include #include @@ -264,7 +263,7 @@ QString MaterialValue::getYAMLStringMultiLine() const QString yaml; yaml = QString::fromStdString(" |2"); auto list = - getValue().toString().split(QRegExp(QString::fromStdString("[\r\n]")), Qt::SkipEmptyParts); + getValue().toString().split(QRegularExpression(QString::fromStdString("[\r\n]")), Qt::SkipEmptyParts); for (auto& it : list) { yaml += QString::fromStdString("\n ") + it; } diff --git a/src/Mod/Material/App/ModelLibrary.cpp b/src/Mod/Material/App/ModelLibrary.cpp index baa244ecdd..63d06f2d06 100644 --- a/src/Mod/Material/App/ModelLibrary.cpp +++ b/src/Mod/Material/App/ModelLibrary.cpp @@ -55,7 +55,7 @@ QString LibraryBase::getLocalPath(const QString& path) const QString prefix = QString::fromStdString("/") + getName(); if (cleanPath.startsWith(prefix)) { // Remove the library name from the path - filePath += cleanPath.rightRef(cleanPath.length() - prefix.length()); + filePath += cleanPath.right(cleanPath.length() - prefix.length()); } else { filePath += cleanPath; From 5fe2b33bb0bdfa24b3600d440a2c331ae9ec1148 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Mon, 15 Jan 2024 17:36:25 +0100 Subject: [PATCH 13/34] Tests: Avoid use of fmtlib when not needed --- tests/src/App/ComplexGeoData.cpp | 4 ++-- tests/src/Base/Reader.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/src/App/ComplexGeoData.cpp b/tests/src/App/ComplexGeoData.cpp index 6eab5175d9..4c344495ea 100644 --- a/tests/src/App/ComplexGeoData.cpp +++ b/tests/src/App/ComplexGeoData.cpp @@ -3,7 +3,6 @@ #include "gtest/gtest.h" #include -#include #include #include @@ -318,7 +317,8 @@ TEST_F(ComplexGeoDataTest, elementTypeCharMappedNameWithPrefix) // NOLINT int size {0}; Data::MappedName mappedName; Data::IndexedName indexedName; - auto name = fmt::format("{}TestMappedElement:;", Data::ELEMENT_MAP_PREFIX); + std::string name(Data::ELEMENT_MAP_PREFIX); + name.append("TestMappedElement:;"); std::tie(indexedName, mappedName) = createMappedName(name); // Act diff --git a/tests/src/Base/Reader.cpp b/tests/src/Base/Reader.cpp index 04153c68bd..7ff4f17585 100644 --- a/tests/src/Base/Reader.cpp +++ b/tests/src/Base/Reader.cpp @@ -10,7 +10,6 @@ #include "Base/Reader.h" #include #include -#include #include namespace fs = boost::filesystem; From 3a53a69379927d88ff6365b5b4b89055525f80c1 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 15 Jan 2024 21:22:57 -0600 Subject: [PATCH 14/34] App/Toponaming: Add Comparator for mapped elements This is the original code from the Toponaming branch, modified slightly to update the method name and correct some grammatical errors in the descriptive comment. Co-authored-by: Chris Hennes --- src/App/MappedElement.cpp | 102 ++++++++++++++++++++++++++++++++++++++ src/App/MappedElement.h | 16 ++++++ 2 files changed, 118 insertions(+) diff --git a/src/App/MappedElement.cpp b/src/App/MappedElement.cpp index 14eb6f99ba..5df937adfe 100644 --- a/src/App/MappedElement.cpp +++ b/src/App/MappedElement.cpp @@ -22,3 +22,105 @@ #include "PreCompiled.h" #include "MappedElement.h" + +using namespace Data; + +bool ElementNameComparator::operator()(const MappedName &a, const MappedName &b) const { + size_t size = std::min(a.size(),b.size()); + if(!size) + return a.size()bc) + res = 1; + } + }else if(std::isxdigit(ac)) + return false; + else + break; + } + if(res < 0) + return true; + else if(res > 0) + return false; + + for (; i bc) + return false; + } + return a.size()bc) + return false; + } else if(!std::isdigit(ac)) { + return false; + } else + break; + } + + // Then compare the following digits part by integer value + int res = 0; + for(;ibc) + res = 1; + } + }else if(std::isdigit(ac)) + return false; + else + break; + } + if(res < 0) + return true; + else if(res > 0) + return false; + + // Finally, compare the remaining tail using lexical order + for (; i bc) + return false; + } + return a.size() Date: Mon, 15 Jan 2024 21:50:32 -0600 Subject: [PATCH 15/34] App/Toponaming: ElementNameComparator linter cleanup Does not address cognitive complexity. --- src/App/MappedElement.cpp | 155 +++++++++++++++++++++++--------------- src/App/MappedElement.h | 2 +- 2 files changed, 94 insertions(+), 63 deletions(-) diff --git a/src/App/MappedElement.cpp b/src/App/MappedElement.cpp index 5df937adfe..25e7abf7cc 100644 --- a/src/App/MappedElement.cpp +++ b/src/App/MappedElement.cpp @@ -25,102 +25,133 @@ using namespace Data; -bool ElementNameComparator::operator()(const MappedName &a, const MappedName &b) const { - size_t size = std::min(a.size(),b.size()); - if(!size) - return a.size()(std::min(leftName.size(), rightName.size())); + if (size == 0U) { + return leftName.size() < rightName.size(); + } + int currentIndex = 0; + if (rightName[0] == '#') { + if (leftName[0] != '#') { return true; + } // If both string starts with '#', compare the following hex digits by // its integer value. int res = 0; - for(i=1;ibc) - res = 1; } - }else if(std::isxdigit(ac)) - return false; - else + if (res == 0) { + if (ac < bc) { + res = -1; + } + else if (ac > bc) { + res = 1; + } + } + } + else if (std::isxdigit(ac) != 0) { + res = 1; + } + else { break; + } } - if(res < 0) + if (res < 0) { return true; - else if(res > 0) - return false; - - for (; i bc) - return false; } - return a.size() 0) { + return false; + } + + for (; currentIndex < size; ++currentIndex) { + char ac = leftName[currentIndex]; + char bc = rightName[currentIndex]; + if (ac < bc) { + return true; + } + if (ac > bc) { + return false; + } + } + return leftName.size() < rightName.size(); } - else if (a[0] == '#') + if (leftName[0] == '#') { return false; + } // If the string does not start with '#', compare the non-digits prefix // using lexical order. - for(i=0;ibc) + } + if (ac > bc) { return false; - } else if(!std::isdigit(ac)) { + } + } + else if (std::isdigit(ac) == 0) { return false; - } else + } + else { break; + } } // Then compare the following digits part by integer value int res = 0; - for(;ibc) - res = 1; } - }else if(std::isdigit(ac)) + if (res == 0) { + if (ac < bc) { + res = -1; + } + else if (ac > bc) { + res = 1; + } + } + } + else if (std::isdigit(ac) != 0) { return false; - else + } + else { break; + } } - if(res < 0) + if (res < 0) { return true; - else if(res > 0) + } + if (res > 0) { return false; + } // Finally, compare the remaining tail using lexical order - for (; i bc) + } + if (ac > bc) { return false; + } } - return a.size() Date: Tue, 16 Jan 2024 19:05:40 -0600 Subject: [PATCH 16/34] Tests/Toponaming: Add tests for ElementNameComparator This verifies the existing functionality, but does not alter it. Two tests are disabled because they represent cases that the current code does not handle correctly. They are edge cases that are not expected in real code. --- tests/src/App/MappedElement.cpp | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/tests/src/App/MappedElement.cpp b/tests/src/App/MappedElement.cpp index 0ea03de6af..36588a8d92 100644 --- a/tests/src/App/MappedElement.cpp +++ b/tests/src/App/MappedElement.cpp @@ -127,3 +127,91 @@ TEST_F(MappedElementTest, lessThanOperator) EXPECT_FALSE(mappedElement2A < mappedElement1B); EXPECT_FALSE(mappedElement2B < mappedElement2BDuplicate); } + +TEST_F(MappedElementTest, comparatorBothAreZeroSize) +{ + // Arrange + Data::MappedName mappedName1 {""}; + Data::MappedName mappedName2 {""}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_FALSE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, comparatorOneIsZeroSize) +{ + // Arrange + Data::MappedName mappedName1 {""}; + Data::MappedName mappedName2 {"#12345"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_TRUE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, comparatorBothStartWithHexDigitsThatDiffer) +{ + // Arrange + Data::MappedName mappedName1 {"#fed;B"}; + Data::MappedName mappedName2 {"#abcdef;A"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_TRUE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, comparatorBothStartWithTheSameHexDigits) +{ + // Arrange + Data::MappedName mappedName1 {"#12345;B"}; + Data::MappedName mappedName2 {"#12345;A"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_FALSE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, DISABLED_comparatorHexWithoutTerminatorIsBroken) +{ + // Arrange + Data::MappedName mappedName1 {"#fed"}; + Data::MappedName mappedName2 {"#abcdef"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_FALSE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, comparatorNoHexDigitsLexicalCompare) +{ + // Arrange + Data::MappedName mappedName1 {"A"}; + Data::MappedName mappedName2 {"B"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_TRUE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, comparatorNoHexDigitsSameStringNumericCompare) +{ + // Arrange + Data::MappedName mappedName1 {"Edge123456;"}; + Data::MappedName mappedName2 {"Edge321;"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_FALSE(comp(mappedName1, mappedName2)); +} + +TEST_F(MappedElementTest, DISABLED_comparatorIntegerWithoutTerminatorIsBroken) +{ + // Arrange + Data::MappedName mappedName1 {"Edge123456"}; + Data::MappedName mappedName2 {"Edge321"}; + auto comp = Data::ElementNameComparator(); + + // Act & Assert + EXPECT_FALSE(comp(mappedName1, mappedName2)); +} From 56bf4e7ebdb258b61eadd3563de6afbd3aaca6f1 Mon Sep 17 00:00:00 2001 From: Paddle Date: Wed, 17 Jan 2024 17:00:55 +0100 Subject: [PATCH 17/34] Core : Tree: Add 'Properties' action in contextual menu. Opens a property dialog. --- src/Gui/PropertyView.cpp | 6 ++--- src/Gui/PropertyView.h | 2 +- src/Gui/Tree.cpp | 27 +++++++++++++++++++++++ src/Gui/Tree.h | 2 ++ src/Gui/propertyeditor/PropertyEditor.cpp | 6 ++++- src/Gui/propertyeditor/PropertyEditor.h | 2 +- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/Gui/PropertyView.cpp b/src/Gui/PropertyView.cpp index 535f54fa2c..fb0dda47d1 100644 --- a/src/Gui/PropertyView.cpp +++ b/src/Gui/PropertyView.cpp @@ -67,7 +67,7 @@ static ParameterGrp::handle _GetParam() { * Provides two Gui::PropertyEditor::PropertyEditor widgets, for "View" and "Data", * in two tabs. */ -PropertyView::PropertyView(QWidget *parent) +PropertyView::PropertyView(QWidget *parent, int sizeOfFirstColumn) : QWidget(parent), SelectionObserver(false, ResolveMode::NoResolve) { auto pLayout = new QGridLayout( this ); @@ -83,12 +83,12 @@ PropertyView::PropertyView(QWidget *parent) tabs->setTabPosition(QTabWidget::South); pLayout->addWidget(tabs, 0, 0); - propertyEditorView = new Gui::PropertyEditor::PropertyEditor(); + propertyEditorView = new Gui::PropertyEditor::PropertyEditor(parent, sizeOfFirstColumn); propertyEditorView->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionView", false)); propertyEditorView->setAutomaticExpand(_GetParam()->GetBool("AutoExpandView", false)); tabs->addTab(propertyEditorView, tr("View")); - propertyEditorData = new Gui::PropertyEditor::PropertyEditor(); + propertyEditorData = new Gui::PropertyEditor::PropertyEditor(parent, sizeOfFirstColumn); propertyEditorData->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionData", true)); propertyEditorData->setAutomaticExpand(_GetParam()->GetBool("AutoExpandData", false)); tabs->addTab(propertyEditorData, tr("Data")); diff --git a/src/Gui/PropertyView.h b/src/Gui/PropertyView.h index a058fcd04e..cf539df318 100644 --- a/src/Gui/PropertyView.h +++ b/src/Gui/PropertyView.h @@ -56,7 +56,7 @@ class PropertyView : public QWidget, public Gui::SelectionObserver Q_OBJECT public: - explicit PropertyView(QWidget *parent=nullptr); + explicit PropertyView(QWidget *parent=nullptr, int sizeOfFirstColumn = 0); ~PropertyView() override; Gui::PropertyEditor::PropertyEditor* propertyEditorView; diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 4a657680d4..3b2cc0717c 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -61,6 +61,7 @@ #include "Macro.h" #include "MainWindow.h" #include "MenuManager.h" +#include "PropertyView.h" #include "TreeParams.h" #include "View3DInventor.h" #include "ViewProviderDocumentObject.h" @@ -523,6 +524,13 @@ TreeWidget::TreeWidget(const char* name, QWidget* parent) connect(this->relabelObjectAction, &QAction::triggered, this, &TreeWidget::onRelabelObject); + this->objectPropertyAction = new QAction(this); +#ifndef Q_OS_MAC + this->objectPropertyAction->setShortcut(Qt::Key_F6); +#endif + connect(this->objectPropertyAction, &QAction::triggered, + this, &TreeWidget::onObjectProperty); + this->finishEditingAction = new QAction(this); connect(this->finishEditingAction, &QAction::triggered, this, &TreeWidget::onFinishEditing); @@ -961,6 +969,7 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) // relabeling is only possible for a single selected document if (SelectedObjectsList.size() == 1) contextMenu.addAction(this->relabelObjectAction); + contextMenu.addAction(this->objectPropertyAction); auto selItems = this->selectedItems(); // if only one item is selected, setup the edit menu @@ -1082,6 +1091,21 @@ void TreeWidget::onRelabelObject() editItem(item); } +void TreeWidget::onObjectProperty() +{ + int sizeOfFirstColumn = 200; + auto prop = new PropertyView(this, sizeOfFirstColumn); + QDialog* propertyDialog = new QDialog(this); + propertyDialog->setWindowTitle(QString::fromLatin1("Properties")); + propertyDialog->resize(700, 500); + QVBoxLayout* layout = new QVBoxLayout(propertyDialog); + layout->addWidget(prop); + propertyDialog->setLayout(layout); + QPoint cursorPos = QCursor::pos() - QPoint(0, 300); + propertyDialog->move(cursorPos); + propertyDialog->show(); +} + void TreeWidget::onStartEditing() { auto action = qobject_cast(sender()); @@ -2965,6 +2989,9 @@ void TreeWidget::setupText() this->relabelObjectAction->setText(tr("Rename")); this->relabelObjectAction->setStatusTip(tr("Rename object")); + this->objectPropertyAction->setText(tr("Properties")); + this->objectPropertyAction->setStatusTip(tr("Properties of the selected object")); + this->finishEditingAction->setText(tr("Finish editing")); this->finishEditingAction->setStatusTip(tr("Finish editing object")); diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index 6d35edfec2..877cddf664 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -154,6 +154,7 @@ protected: protected Q_SLOTS: void onCreateGroup(); void onRelabelObject(); + void onObjectProperty(); void onActivateDocument(QAction*); void onStartEditing(); void onFinishEditing(); @@ -208,6 +209,7 @@ private: private: QAction* createGroupAction; QAction* relabelObjectAction; + QAction* objectPropertyAction; QAction* finishEditingAction; QAction* selectDependentsAction; QAction* skipRecomputeAction; diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index b0b0e3489b..184d0420dd 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -51,7 +51,7 @@ FC_LOG_LEVEL_INIT("PropertyView", true, true) using namespace Gui::PropertyEditor; -PropertyEditor::PropertyEditor(QWidget *parent) +PropertyEditor::PropertyEditor(QWidget *parent, int sizeOfFirstColumn) : QTreeView(parent) , autoexpand(false) , autoupdate(false) @@ -99,6 +99,10 @@ PropertyEditor::PropertyEditor(QWidget *parent) setHeaderHidden(true); viewport()->installEventFilter(this); viewport()->setMouseTracking(true); + + if (sizeOfFirstColumn != 0) { + header()->resizeSection(0, sizeOfFirstColumn); + } } PropertyEditor::~PropertyEditor() diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index bd01c2f99e..5c5342d129 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -67,7 +67,7 @@ class PropertyEditor : public QTreeView Q_PROPERTY(QBrush itemBackground READ itemBackground WRITE setItemBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify public: - PropertyEditor(QWidget *parent = nullptr); + PropertyEditor(QWidget *parent = nullptr, int sizeOfFirstColumn = 0); ~PropertyEditor() override; /** Builds up the list view with the properties. */ From be03a9cebfe072ee73f0a1c9070bb96387bc7a52 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Tue, 9 Jan 2024 14:03:55 +0100 Subject: [PATCH 18/34] Arch: implement new get_param functions Additionally 2 Arch_Window bugs were fixed: * If the W1 value was changed the box tracker was not repositioned relative to the cursor. * The WindowColor was not applied because of a typo in the code. De current default color is quite dark BTW. Note that all dimensional values that were not really defaults, but just the last entered values, have been removed from preferences-archdefaults.ui. As a result the layout looks a bit strange. That will be improved in a next PR. --- src/Mod/Arch/ArchAxis.py | 10 +- src/Mod/Arch/ArchBuilding.py | 5 +- src/Mod/Arch/ArchBuildingPart.py | 17 +- src/Mod/Arch/ArchCommands.py | 52 +- src/Mod/Arch/ArchComponent.py | 14 +- src/Mod/Arch/ArchCurtainWall.py | 4 +- src/Mod/Arch/ArchFloor.py | 5 +- src/Mod/Arch/ArchIFCSchema.py | 3 +- src/Mod/Arch/ArchMaterial.py | 12 +- src/Mod/Arch/ArchPanel.py | 26 +- src/Mod/Arch/ArchPipe.py | 5 +- src/Mod/Arch/ArchPrecast.py | 59 +- src/Mod/Arch/ArchProfile.py | 11 +- src/Mod/Arch/ArchRebar.py | 9 +- src/Mod/Arch/ArchReference.py | 4 +- src/Mod/Arch/ArchSchedule.py | 30 +- src/Mod/Arch/ArchSectionPlane.py | 13 +- src/Mod/Arch/ArchSite.py | 9 +- src/Mod/Arch/ArchSpace.py | 20 +- src/Mod/Arch/ArchStairs.py | 13 +- src/Mod/Arch/ArchStructure.py | 39 +- src/Mod/Arch/ArchVRM.py | 3 +- src/Mod/Arch/ArchWall.py | 34 +- src/Mod/Arch/ArchWindow.py | 58 +- .../Resources/ui/preferences-archdefaults.ui | 829 +++++------------- src/Mod/Arch/exportIFC.py | 39 +- src/Mod/Arch/exportIFCHelper.py | 5 +- src/Mod/Arch/importDAE.py | 26 +- src/Mod/Arch/importIFC.py | 3 +- src/Mod/Arch/importIFCHelper.py | 43 +- src/Mod/Arch/importIFClegacy.py | 35 +- src/Mod/Arch/importOBJ.py | 4 +- src/Mod/Arch/importSHP.py | 4 +- src/Mod/Draft/draftutils/params.py | 100 ++- 34 files changed, 597 insertions(+), 946 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index ecda27a768..b23aff4612 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -26,6 +26,8 @@ import ArchCommands import Draft import Part from FreeCAD import Vector +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui, re from PySide import QtCore, QtGui @@ -224,7 +226,7 @@ class _ViewProviderAxis: def setProperties(self,vobj): - ts = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetFloat("textheight",350) + ts = params.get_param("textheight") pl = vobj.PropertiesList if not "BubbleSize" in pl: vobj.addProperty("App::PropertyLength","BubbleSize","Axis", QT_TRANSLATE_NOOP("App::Property","The size of the axis bubbles")) @@ -251,7 +253,7 @@ class _ViewProviderAxis: vobj.StartNumber = 1 if not "FontName" in pl: vobj.addProperty("App::PropertyFont","FontName","Axis",QT_TRANSLATE_NOOP("App::Property","The font to use for texts")) - vobj.FontName = Draft.getParam("textfont","Arial,Sans") + vobj.FontName = params.get_param("textfont") if not "FontSize" in pl: vobj.addProperty("App::PropertyLength","FontSize","Axis",QT_TRANSLATE_NOOP("App::Property","The font size")) vobj.FontSize = ts @@ -476,7 +478,7 @@ class _ViewProviderAxis: txpos = FreeCAD.Vector(center.x,center.y-fs/2.5,center.z) tr.translation.setValue(tuple(txpos)) fo = coin.SoFont() - fn = Draft.getParam("textfont","Arial,Sans") + fn = params.get_param("textfont") if hasattr(vobj,"FontName"): if vobj.FontName: try: @@ -545,7 +547,7 @@ class _ViewProviderAxis: fs = vobj.BubbleSize*0.75 tr.translation.setValue(tuple(pl.Base)) tr.rotation.setValue(pl.Rotation.Q) - fn = Draft.getParam("textfont","Arial,Sans") + fn = params.get_param("textfont") if hasattr(vobj,"FontName"): if vobj.FontName: try: diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index 68e5a9352a..8231f81a34 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -24,6 +24,8 @@ import FreeCAD import ArchCommands import ArchFloor import Draft +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtCore @@ -227,8 +229,7 @@ class _CommandBuilding: def Activated(self): sel = FreeCADGui.Selection.getSelection() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - link = p.GetBool("FreeLinking",False) + link = params.get_param_arch("FreeLinking") buildingobj = [] warning = False for obj in sel : diff --git a/src/Mod/Arch/ArchBuildingPart.py b/src/Mod/Arch/ArchBuildingPart.py index f21b7ae935..e327004fcc 100644 --- a/src/Mod/Arch/ArchBuildingPart.py +++ b/src/Mod/Arch/ArchBuildingPart.py @@ -27,6 +27,8 @@ import DraftVecUtils import ArchIFC import tempfile import os +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from draftutils.translate import translate @@ -567,10 +569,10 @@ class ViewProviderBuildingPart: vobj.ShowLabel = True if not "FontName" in pl: vobj.addProperty("App::PropertyFont","FontName","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The font to be used for texts")) - vobj.FontName = Draft.getParam("textfont","Arial") + vobj.FontName = params.get_param("textfont") if not "FontSize" in pl: vobj.addProperty("App::PropertyLength","FontSize","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The font size of texts")) - vobj.FontSize = Draft.getParam("textheight",2.0) + vobj.FontSize = params.get_param("textheight") if not "DiffuseColor" in pl: vobj.addProperty("App::PropertyColorList","DiffuseColor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The individual face colors")) @@ -600,17 +602,16 @@ class ViewProviderBuildingPart: vobj.addProperty("App::PropertyBool","ChildrenOverride","Children",QT_TRANSLATE_NOOP("App::Property","If true, show the objects contained in this Building Part will adopt these line, color and transparency settings")) if not "ChildrenLineWidth" in pl: vobj.addProperty("App::PropertyFloat","ChildrenLineWidth","Children",QT_TRANSLATE_NOOP("App::Property","The line width of child objects")) - vobj.LineWidth = 1 + vobj.ChildrenLineWidth = params.get_param_view("DefaultShapeLineWidth") if not "ChildrenLineColor" in pl: vobj.addProperty("App::PropertyColor","ChildrenLineColor","Children",QT_TRANSLATE_NOOP("App::Property","The line color of child objects")) - c = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned("DefaultShapeLineColor",255) - vobj.ChildrenLineColor = (float((c>>24)&0xFF)/255.0,float((c>>16)&0xFF)/255.0,float((c>>8)&0xFF)/255.0,0.0) + vobj.ChildrenLineColor = params.get_param_view("DefaultShapeLineColor") & 0xFFFFFF00 if not "ChildrenShapeColor" in pl: vobj.addProperty("App::PropertyColor","ChildrenShapeColor","Children",QT_TRANSLATE_NOOP("App::Property","The shape color of child objects")) - c = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned("DefaultShapeColor",4294967295) - vobj.ChildrenLineColor = (float((c>>24)&0xFF)/255.0,float((c>>16)&0xFF)/255.0,float((c>>8)&0xFF)/255.0,0.0) + vobj.ChildrenShapeColor = params.get_param_view("DefaultShapeColor") & 0xFFFFFF00 if not "ChildrenTransparency" in pl: vobj.addProperty("App::PropertyPercent","ChildrenTransparency","Children",QT_TRANSLATE_NOOP("App::Property","The transparency of child objects")) + vobj.ChildrenTransparency = params.get_param_view("DefaultShapeTransparency") # clip properties if not "CutView" in pl: @@ -790,7 +791,7 @@ class ViewProviderBuildingPart: txt += units.display_external(float(q),None,'Length',vobj.ShowUnit,u) except Exception: q = q.getValueAs(q.getUserPreferred()[2]) - d = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",0) + d = params.get_param("Decimals",path="Units") fmt = "{0:."+ str(d) + "f}" if not vobj.ShowUnit: u = "" diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 61635d21ab..712d55ed5d 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -25,6 +25,8 @@ import ArchComponent import Draft import DraftVecUtils from FreeCAD import Vector +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtGui,QtCore @@ -62,33 +64,29 @@ def getStringList(objects): def getDefaultColor(objectType): '''getDefaultColor(string): returns a color value for the given object type (Wall, Structure, Window, WindowGlass)''' - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") transparency = 0.0 if objectType == "Wall": - c = p.GetUnsigned("WallColor",4294967295) + c = params.get_param_arch("WallColor") elif objectType == "Structure": - c = p.GetUnsigned("StructureColor",2847259391) + c = params.get_param_arch("StructureColor") elif objectType == "WindowGlass": - c = p.GetUnsigned("WindowGlassColor",1772731135) - transparency = p.GetInt("WindowTransparency",85)/100.0 + c = params.get_param_arch("WindowGlassColor") + transparency = params.get_param_arch("WindowTransparency") / 100.0 elif objectType == "Rebar": - c = p.GetUnsigned("RebarColor",3111475967) + c = params.get_param_arch("RebarColor") elif objectType == "Panel": - c = p.GetUnsigned("PanelColor",3416289279) + c = params.get_param_arch("PanelColor") elif objectType == "Space": - c = p.GetUnsigned("defaultSpaceColor",4278190080) + c = params.get_param_arch("defaultSpaceColor") elif objectType == "Helpers": - c = p.GetUnsigned("ColorHelpers",674321151) + c = params.get_param_arch("ColorHelpers") elif objectType == "Construction": - c = Draft.getParam("constructioncolor",746455039) + c = params.get_param("constructioncolor") transparency = 0.80 else: - c = p.GetUnsigned("WindowsColor",810781695) - r = float((c>>24)&0xFF)/255.0 - g = float((c>>16)&0xFF)/255.0 - b = float((c>>8)&0xFF)/255.0 - result = (r,g,b,transparency) - return result + c = params.get_param_arch("WindowColor") + r, g, b, _ = Draft.get_rgba_tuple(c) + return (r, g, b, transparency) def addComponents(objectsList,host): '''addComponents(objectsList,hostObject): adds the given object or the objects @@ -251,7 +249,7 @@ def setAsSubcomponent(obj): '''Sets the given object properly to become a subcomponent (addition, subtraction) of an Arch component''' Draft.ungroup(obj) - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("applyConstructionStyle",True): + if params.get_param_arch("applyConstructionStyle"): if FreeCAD.GuiUp: color = getDefaultColor("Construction") if hasattr(obj.ViewObject,"LineColor"): @@ -662,10 +660,7 @@ def download(url,force=False): from urllib2 import urlopen import os name = url.split('/')[-1] - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") - macropath = p.GetString("MacroPath","") - if not macropath: - macropath = FreeCAD.ConfigGet("UserAppData") + macropath = FreeCAD.getUserMacroDir(True) filepath = os.path.join(macropath,name) if os.path.exists(filepath) and not(force): return filepath @@ -845,7 +840,7 @@ def survey(callback=False): for o in newsels: if hasattr(o.Object, 'Shape'): n = o.Object.Label - showUnit = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("surveyUnits",True) + showUnit = params.get_param_arch("surveyUnits") t = "" u = FreeCAD.Units.Quantity() if not o.HasSubObjects: @@ -1040,7 +1035,7 @@ class SurveyTaskPanel: if hasattr(FreeCAD,"SurveyObserver"): u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalLength,FreeCAD.Units.Length) t = u.getUserPreferred()[0] - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("surveyUnits",True): + if params.get_param_arch("surveyUnits"): QtGui.QApplication.clipboard().setText(t) else: QtGui.QApplication.clipboard().setText(str(u.Value/u.getUserPreferred()[1])) @@ -1050,7 +1045,7 @@ class SurveyTaskPanel: u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalArea,FreeCAD.Units.Area) t = u.getUserPreferred()[0] t = t.replace("^2","²") - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("surveyUnits",True): + if params.get_param_arch("surveyUnits"): QtGui.QApplication.clipboard().setText(t) else: QtGui.QApplication.clipboard().setText(str(u.Value/u.getUserPreferred()[1])) @@ -1448,11 +1443,10 @@ class _CommandMeshToShape: if f.InList: if f.InList[0].isDerivedFrom("App::DocumentObjectGroup"): g = f.InList[0] - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - fast = p.GetBool("ConversionFast",True) - tol = p.GetFloat("ConversionTolerance",0.001) - flat = p.GetBool("ConversionFlat",False) - cut = p.GetBool("ConversionCut",False) + fast = params.get_param_arch("ConversionFast") + tol = params.get_param_arch("ConversionTolerance") + flat = params.get_param_arch("ConversionFlat") + cut = params.get_param_arch("ConversionCut") FreeCAD.ActiveDocument.openTransaction(translate("Arch","Mesh to Shape")) for obj in FreeCADGui.Selection.getSelection(): newobj = meshToShape(obj,True,fast,tol,flat,cut) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index d6d4e06379..1faaa34111 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -35,6 +35,8 @@ import FreeCAD import ArchCommands import ArchIFC import Draft +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtGui,QtCore @@ -213,10 +215,10 @@ class Component(ArchIFC.IfcProduct): FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" BaseMaterial property to Material\n") if not "MoveBase" in pl: obj.addProperty("App::PropertyBool","MoveBase","Component",QT_TRANSLATE_NOOP("App::Property","Specifies if moving this object moves its base instead")) - obj.MoveBase = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("MoveBase",False) + obj.MoveBase = params.get_param_arch("MoveBase") if not "MoveWithHost" in pl: obj.addProperty("App::PropertyBool","MoveWithHost","Component",QT_TRANSLATE_NOOP("App::Property","Specifies if this object must move together when its host is moved")) - obj.MoveWithHost = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("MoveWithHost",False) + obj.MoveWithHost = params.get_param_arch("MoveWithHost") if not "VerticalArea" in pl: obj.addProperty("App::PropertyArea","VerticalArea","Component",QT_TRANSLATE_NOOP("App::Property","The area of all vertical faces of this object")) obj.setEditorMode("VerticalArea",1) @@ -992,7 +994,7 @@ class Component(ArchIFC.IfcProduct): import Part import TechDraw - fmax = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("MaxComputeAreas",20) + fmax = params.get_param_arch("MaxComputeAreas") if len(obj.Shape.Faces) > fmax: obj.VerticalArea = 0 obj.HorizontalArea = 0 @@ -1174,7 +1176,7 @@ class ViewProviderComponent: if not "UseMaterialColor" in vobj.PropertiesList: vobj.addProperty("App::PropertyBool","UseMaterialColor","Component",QT_TRANSLATE_NOOP("App::Property","Use the material color as this object's shape color, if available")) - vobj.UseMaterialColor = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("UseMaterialColor",True) + vobj.UseMaterialColor = params.get_param_arch("UseMaterialColor") def updateData(self,obj,prop): """Method called when the host object has a property changed. @@ -1456,7 +1458,7 @@ class ViewProviderComponent: objlink = getattr(self.Object,link) if objlink: c.append(objlink) - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ClaimHosted",True): + if params.get_param_arch("ClaimHosted"): for link in self.Object.Proxy.getHosts(self.Object): c.append(link) @@ -2294,7 +2296,7 @@ if FreeCAD.GuiUp: editor = QtGui.QSpinBox(parent) elif "Real" in ptype: editor = QtGui.QDoubleSpinBox(parent) - editor.setDecimals(FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2)) + editor.setDecimals(params.get_param("Decimals",path="Units")) elif ("Boolean" in ptype) or ("Logical" in ptype): editor = QtGui.QComboBox(parent) editor.addItems(["True","False"]) diff --git a/src/Mod/Arch/ArchCurtainWall.py b/src/Mod/Arch/ArchCurtainWall.py index 64ce7ea311..6b67f3f929 100644 --- a/src/Mod/Arch/ArchCurtainWall.py +++ b/src/Mod/Arch/ArchCurtainWall.py @@ -29,6 +29,7 @@ import FreeCAD import ArchComponent import ArchCommands import DraftVecUtils +from draftutils import params if FreeCAD.GuiUp: import FreeCADGui @@ -167,13 +168,12 @@ class CurtainWall(ArchComponent.Component): pl = obj.PropertiesList vsize = 50 hsize = 50 - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") if not "Host" in pl: obj.addProperty("App::PropertyLink","Host","CurtainWall",QT_TRANSLATE_NOOP("App::Property","An optional host object for this curtain wall")) if not "Height" in pl: obj.addProperty("App::PropertyLength","Height","CurtainWall", QT_TRANSLATE_NOOP("App::Property","The height of the curtain wall, if based on an edge")) - obj.Height = p.GetFloat("WallHeight",3000) + obj.Height = params.get_param_arch("WallHeight") if not "VerticalMullionNumber" in pl: obj.addProperty("App::PropertyInteger","VerticalMullionNumber","CurtainWall", QT_TRANSLATE_NOOP("App::Property","The number of vertical mullions")) diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index 601abd661b..85c66daf6f 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -33,6 +33,8 @@ import ArchCommands import ArchIFC import Draft import DraftVecUtils +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from draftutils.translate import translate @@ -135,8 +137,7 @@ class _CommandFloor: """ sel = FreeCADGui.Selection.getSelection() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - link = p.GetBool("FreeLinking",False) + link = params.get_param_arch("FreeLinking") floorobj = [] warning = False for obj in sel : diff --git a/src/Mod/Arch/ArchIFCSchema.py b/src/Mod/Arch/ArchIFCSchema.py index 917b0a2c3a..f196545068 100644 --- a/src/Mod/Arch/ArchIFCSchema.py +++ b/src/Mod/Arch/ArchIFCSchema.py @@ -30,9 +30,10 @@ import os import json import FreeCAD +from draftutils import params ifcVersions = ["IFC4", "IFC2X3"] -IfcVersion = ifcVersions[FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("IfcVersion",0)] +IfcVersion = ifcVersions[params.get_param_arch("IfcVersion")] with open(os.path.join(FreeCAD.getResourceDir(), "Mod", "Arch", "Presets", "ifc_contexts_" + IfcVersion + ".json")) as f: diff --git a/src/Mod/Arch/ArchMaterial.py b/src/Mod/Arch/ArchMaterial.py index a9809fb44d..f5d39abcb1 100644 --- a/src/Mod/Arch/ArchMaterial.py +++ b/src/Mod/Arch/ArchMaterial.py @@ -20,6 +20,8 @@ #*************************************************************************** import FreeCAD +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui, os import Arch_rc # Needed for access to icons # lgtm [py/unused_import] @@ -887,9 +889,8 @@ class _ArchMultiMaterialTaskPanel: self.model.clear() self.model.setHorizontalHeaderLabels([translate("Arch","Name"),translate("Arch","Material"),translate("Arch","Thickness")]) # restore widths - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - self.form.tree.setColumnWidth(0,p.GetInt("MultiMaterialColumnWidth0",60)) - self.form.tree.setColumnWidth(1,p.GetInt("MultiMaterialColumnWidth1",60)) + self.form.tree.setColumnWidth(0,params.get_param_arch("MultiMaterialColumnWidth0")) + self.form.tree.setColumnWidth(1,params.get_param_arch("MultiMaterialColumnWidth1")) for i in range(len(obj.Names)): item1 = QtGui.QStandardItem(obj.Names[i]) item2 = QtGui.QStandardItem(obj.Materials[i].Label) @@ -974,9 +975,8 @@ class _ArchMultiMaterialTaskPanel: def accept(self): # store widths - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - p.SetInt("MultiMaterialColumnWidth0",self.form.tree.columnWidth(0)) - p.SetInt("MultiMaterialColumnWidth1",self.form.tree.columnWidth(1)) + params.set_param_arch("MultiMaterialColumnWidth0",self.form.tree.columnWidth(0)) + params.set_param_arch("MultiMaterialColumnWidth1",self.form.tree.columnWidth(1)) if self.obj: mats = [] for m in FreeCAD.ActiveDocument.Objects: diff --git a/src/Mod/Arch/ArchPanel.py b/src/Mod/Arch/ArchPanel.py index 20fb4f4083..36bd428be7 100644 --- a/src/Mod/Arch/ArchPanel.py +++ b/src/Mod/Arch/ArchPanel.py @@ -28,6 +28,8 @@ import Draft import DraftVecUtils import Part from FreeCAD import Vector +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtCore, QtGui @@ -142,10 +144,9 @@ class CommandPanel: def Activated(self): - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - self.Length = p.GetFloat("PanelLength",1000) - self.Width = p.GetFloat("PanelWidth",1000) - self.Thickness = p.GetFloat("PanelThickness",10) + self.Length = params.get_param_arch("PanelLength") + self.Width = params.get_param_arch("PanelWidth") + self.Thickness = params.get_param_arch("PanelThickness") self.Profile = None self.continueCmd = False self.rotated = False @@ -167,7 +168,7 @@ class CommandPanel: # interactive mode import WorkingPlane WorkingPlane.get_working_plane() - + self.points = [] self.tracker = DraftTrackers.boxTracker() self.tracker.width(self.Width) @@ -282,17 +283,17 @@ class CommandPanel: def setWidth(self,d): self.Width = d - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PanelWidth",d) + params.set_param_arch("PanelWidth",d) def setThickness(self,d): self.Thickness = d - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PanelThickness",d) + params.set_param_arch("PanelThickness",d) def setLength(self,d): self.Length = d - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PanelLength",d) + params.set_param_arch("PanelLength",d) def setContinue(self,i): @@ -832,7 +833,7 @@ class PanelCut(Draft.DraftObject): obj.addProperty("App::PropertyAngle","TagRotation","PanelCut",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text")) if not "FontFile" in pl: obj.addProperty("App::PropertyFile","FontFile","PanelCut",QT_TRANSLATE_NOOP("App::Property","The font of the tag text")) - obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile","") + obj.FontFile = params.get_param("FontFile") if not "MakeFace" in pl: obj.addProperty("App::PropertyBool","MakeFace","PanelCut",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible.")) if not "AllowedAngles" in pl: @@ -1099,7 +1100,6 @@ class PanelSheet(Draft.DraftObject): def setProperties(self,obj): pl = obj.PropertiesList - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") if not "Group" in pl: obj.addProperty("App::PropertyLinkList","Group","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The linked Panel cuts")) if not "TagText" in pl: @@ -1113,13 +1113,13 @@ class PanelSheet(Draft.DraftObject): obj.addProperty("App::PropertyAngle","TagRotation","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text")) if not "FontFile" in pl: obj.addProperty("App::PropertyFile","FontFile","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The font of the tag text")) - obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile",QT_TRANSLATE_NOOP("App::Property","The font file")) + obj.FontFile = params.get_param("FontFile") if not "Width" in pl: obj.addProperty("App::PropertyLength","Width","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The width of the sheet")) - obj.Width = p.GetFloat("PanelLength",1000) + obj.Width = params.get_param_arch("PanelLength") if not "Height" in pl: obj.addProperty("App::PropertyLength","Height","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The height of the sheet")) - obj.Height = p.GetFloat("PanelWidth",1000) + obj.Height = params.get_param_arch("PanelWidth") if not "FillRatio" in pl: obj.addProperty("App::PropertyPercent","FillRatio","PanelSheet",QT_TRANSLATE_NOOP("App::Property","The fill ratio of this sheet")) obj.setEditorMode("FillRatio",2) diff --git a/src/Mod/Arch/ArchPipe.py b/src/Mod/Arch/ArchPipe.py index bdcdfac1ab..596fac7cb0 100644 --- a/src/Mod/Arch/ArchPipe.py +++ b/src/Mod/Arch/ArchPipe.py @@ -22,6 +22,8 @@ import FreeCAD import ArchComponent +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui import Arch_rc @@ -71,8 +73,7 @@ def makePipe(baseobj=None,diameter=0,length=0,placement=None,name=None): if diameter: obj.Diameter = diameter else: - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - obj.Diameter = p.GetFloat("PipeDiameter",50) + obj.Diameter = params.get_param_arch("PipeDiameter") if placement: obj.Placement = placement return obj diff --git a/src/Mod/Arch/ArchPrecast.py b/src/Mod/Arch/ArchPrecast.py index 1b7543da25..7bb929b10e 100644 --- a/src/Mod/Arch/ArchPrecast.py +++ b/src/Mod/Arch/ArchPrecast.py @@ -28,6 +28,8 @@ Beams, pillars, slabs and panels""" import ArchCommands,ArchComponent,FreeCAD from FreeCAD import Vector +from draftutils import params + if FreeCAD.GuiUp: from draftutils.translate import translate from PySide.QtCore import QT_TRANSLATE_NOOP @@ -897,21 +899,20 @@ class _PrecastTaskPanel: QtCore.QObject.connect(self.valueTread,QtCore.SIGNAL("valueChanged(double)"),self.setTread) # restore presets - param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - self.restoreValue(self.valueChamfer, param.GetFloat("PrecastChamfer", 0.0)) - self.restoreValue(self.valueDentLength, param.GetFloat("PrecastDentLength", 0.0)) - self.restoreValue(self.valueDentWidth, param.GetFloat("PrecastDentWidth", 0.0)) - self.restoreValue(self.valueDentHeight, param.GetFloat("PrecastDentHeight", 0.0)) - self.restoreValue(self.valueBase, param.GetFloat("PrecastBase", 0.0)) - self.restoreValue(self.valueHoleMajor, param.GetFloat("PrecastHoleMajor", 0.0)) - self.restoreValue(self.valueHoleMinor, param.GetFloat("PrecastHoleMinor", 0.0)) - self.restoreValue(self.valueHoleSpacing, param.GetFloat("PrecastHoleSpacing", 0.0)) - self.restoreValue(self.valueGrooveDepth, param.GetFloat("PrecastGrooveDepth", 0.0)) - self.restoreValue(self.valueGrooveHeight, param.GetFloat("PrecastGrooveHeight", 0.0)) - self.restoreValue(self.valueGrooveSpacing, param.GetFloat("PrecastGrooveSpacing", 0.0)) - self.restoreValue(self.valueDownLength, param.GetFloat("PrecastDownLength", 0.0)) - self.restoreValue(self.valueRiser, param.GetFloat("PrecastRiser", 0.0)) - self.restoreValue(self.valueTread, param.GetFloat("PrecastTread", 0.0)) + self.restoreValue(self.valueChamfer, params.get_param_arch("PrecastChamfer")) + self.restoreValue(self.valueDentLength, params.get_param_arch("PrecastDentLength")) + self.restoreValue(self.valueDentWidth, params.get_param_arch("PrecastDentWidth")) + self.restoreValue(self.valueDentHeight, params.get_param_arch("PrecastDentHeight")) + self.restoreValue(self.valueBase, params.get_param_arch("PrecastBase")) + self.restoreValue(self.valueHoleMajor, params.get_param_arch("PrecastHoleMajor")) + self.restoreValue(self.valueHoleMinor, params.get_param_arch("PrecastHoleMinor")) + self.restoreValue(self.valueHoleSpacing, params.get_param_arch("PrecastHoleSpacing")) + self.restoreValue(self.valueGrooveDepth, params.get_param_arch("PrecastGrooveDepth")) + self.restoreValue(self.valueGrooveHeight, params.get_param_arch("PrecastGrooveHeight")) + self.restoreValue(self.valueGrooveSpacing, params.get_param_arch("PrecastGrooveSpacing")) + self.restoreValue(self.valueDownLength, params.get_param_arch("PrecastDownLength")) + self.restoreValue(self.valueRiser, params.get_param_arch("PrecastRiser")) + self.restoreValue(self.valueTread, params.get_param_arch("PrecastTread")) self.retranslateUi(self.form) self.form.hide() @@ -945,59 +946,59 @@ class _PrecastTaskPanel: def setChamfer(self,value): self.Chamfer = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastChamfer",value) + params.set_param_arch("PrecastChamfer",value) def setDentLength(self,value): self.DentLength = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastDentLength",value) + params.set_param_arch("PrecastDentLength",value) def setDentWidth(self,value): self.DentWidth = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastDentWidth",value) + params.set_param_arch("PrecastDentWidth",value) def setDentHeight(self,value): self.DentHeight = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastDentHeight",value) + params.set_param_arch("PrecastDentHeight",value) def setBase(self,value): self.Base = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastBase",value) + params.set_param_arch("PrecastBase",value) def setHoleMajor(self,value): self.HoleMajor = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastHoleMajor",value) + params.set_param_arch("PrecastHoleMajor",value) def setHoleMinor(self,value): self.HoleMinor = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastHoleMinor",value) + params.set_param_arch("PrecastHoleMinor",value) def setHoleSpacing(self,value): self.HoleSpacing = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastHoleSpacing",value) + params.set_param_arch("PrecastHoleSpacing",value) def setGrooveDepth(self,value): self.GrooveDepth = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastGrooveDepth",value) + params.set_param_arch("PrecastGrooveDepth",value) def setGrooveHeight(self,value): self.GrooveHeight = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastGrooveHeight",value) + params.set_param_arch("PrecastGrooveHeight",value) def setGrooveSpacing(self,value): self.GrooveSpacing = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastGrooveSpacing",value) + params.set_param_arch("PrecastGrooveSpacing",value) def setDownLength(self,value): self.DownLength = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastDownLength",value) + params.set_param_arch("PrecastDownLength",value) def setRiser(self,value): self.Riser = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastRiser",value) + params.set_param_arch("PrecastRiser",value) def setTread(self,value): self.Tread = value - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetFloat("PrecastTread",value) + params.set_param_arch("PrecastTread",value) def retranslateUi(self, dialog): from PySide import QtGui diff --git a/src/Mod/Arch/ArchProfile.py b/src/Mod/Arch/ArchProfile.py index 923a7c78d2..a8d88689ab 100644 --- a/src/Mod/Arch/ArchProfile.py +++ b/src/Mod/Arch/ArchProfile.py @@ -36,6 +36,7 @@ import os import FreeCAD import Draft from FreeCAD import Vector +from draftutils import params if FreeCAD.GuiUp: import FreeCADGui @@ -169,7 +170,7 @@ class Arch_Profile: self.vPresets.currentIndexChanged.connect(self.setPreset) # restore preset - stored = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetString("StructurePreset","") + stored = params.get_param_arch("StructurePreset") if stored: if ";" in stored: stored = stored.split(";") @@ -206,13 +207,13 @@ class Arch_Profile: if i == 0: self.pSelect = [None] self.vPresets.addItems([" "]) - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetString("StructurePreset","") + params.set_param_arch("StructurePreset","") else: self.pSelect = [p for p in self.Presets if p[1] == self.Categories[i-1]] fpresets = [] for p in self.pSelect: f = FreeCAD.Units.Quantity(p[4],FreeCAD.Units.Length).getUserPreferred() - d = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2) + d = params.get_param("Decimals",path="Units") s1 = str(round(p[4]/f[1],d)) s2 = str(round(p[5]/f[1],d)) s3 = str(f[2]) @@ -227,7 +228,7 @@ class Arch_Profile: if elt: p=elt[0]-1 # Presets indexes are 1-based self.Profile = self.Presets[p] - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").SetString("StructurePreset",";".join([str(i) for i in self.Profile])) + params.set_param_arch("StructurePreset",";".join([str(i) for i in self.Profile])) class _Profile(Draft._DraftObject): @@ -565,7 +566,7 @@ class ProfileTaskPanel: if pre[1] == text: self.currentpresets.append(pre) f = FreeCAD.Units.Quantity(pre[4],FreeCAD.Units.Length).getUserPreferred() - d = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2) + d = params.get_param("Decimals",path="Units") s1 = str(round(pre[4]/f[1],d)) s2 = str(round(pre[5]/f[1],d)) s3 = str(f[2]) diff --git a/src/Mod/Arch/ArchRebar.py b/src/Mod/Arch/ArchRebar.py index abe3221a72..d60585a60a 100644 --- a/src/Mod/Arch/ArchRebar.py +++ b/src/Mod/Arch/ArchRebar.py @@ -25,6 +25,8 @@ import Draft import ArchComponent import DraftVecUtils import ArchCommands +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from draftutils.translate import translate @@ -58,7 +60,6 @@ def makeRebar(baseobj=None,sketch=None,diameter=None,amount=1,offset=None,name=N if not FreeCAD.ActiveDocument: FreeCAD.Console.PrintError("No active document. Aborting\n") return - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Rebar") obj.Label = name if name else translate("Arch","Rebar") _Rebar(obj) @@ -87,15 +88,15 @@ def makeRebar(baseobj=None,sketch=None,diameter=None,amount=1,offset=None,name=N if diameter: obj.Diameter = diameter else: - obj.Diameter = p.GetFloat("RebarDiameter",6) + obj.Diameter = params.get_param_arch("RebarDiameter") obj.Amount = amount obj.Document.recompute() if offset is not None: obj.OffsetStart = offset obj.OffsetEnd = offset else: - obj.OffsetStart = p.GetFloat("RebarOffset",30) - obj.OffsetEnd = p.GetFloat("RebarOffset",30) + obj.OffsetStart = params.get_param_arch("RebarOffset") + obj.OffsetEnd = params.get_param_arch("RebarOffset") obj.Mark = obj.Label return obj diff --git a/src/Mod/Arch/ArchReference.py b/src/Mod/Arch/ArchReference.py index ae2e209d5f..2c474f42f8 100644 --- a/src/Mod/Arch/ArchReference.py +++ b/src/Mod/Arch/ArchReference.py @@ -28,6 +28,8 @@ import FreeCAD import os import zipfile import re +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtCore, QtGui @@ -404,7 +406,7 @@ class ViewProviderArchReference: # Check for file change every minute self.timer = QtCore.QTimer() self.timer.timeout.connect(self.checkChanges) - s = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("ReferenceCheckInterval",60) + s = params.get_param_arch("ReferenceCheckInterval") self.timer.start(1000*s) def dumps(self): diff --git a/src/Mod/Arch/ArchSchedule.py b/src/Mod/Arch/ArchSchedule.py index 5e6e2b0209..7ee88f0b75 100644 --- a/src/Mod/Arch/ArchSchedule.py +++ b/src/Mod/Arch/ArchSchedule.py @@ -21,6 +21,8 @@ #*************************************************************************** import FreeCAD +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtCore, QtGui @@ -344,7 +346,7 @@ class _ArchSchedule: tp = FreeCAD.Units.Length # format value - dv = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2) + dv = params.get_param("Decimals",path="Units") fs = "{:."+str(dv)+"f}" # format string for o in objs: if verbose: @@ -514,13 +516,12 @@ class ArchScheduleTaskPanel: self.form.buttonSelect.setIcon(QtGui.QIcon(":/icons/edit-select-all.svg")) # restore widths - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - self.form.list.setColumnWidth(0,p.GetInt("ScheduleColumnWidth0",100)) - self.form.list.setColumnWidth(1,p.GetInt("ScheduleColumnWidth1",100)) - self.form.list.setColumnWidth(2,p.GetInt("ScheduleColumnWidth2",50)) - self.form.list.setColumnWidth(3,p.GetInt("ScheduleColumnWidth3",100)) - w = p.GetInt("ScheduleDialogWidth",300) - h = p.GetInt("ScheduleDialogHeight",200) + self.form.list.setColumnWidth(0,params.get_param_arch("ScheduleColumnWidth0")) + self.form.list.setColumnWidth(1,params.get_param_arch("ScheduleColumnWidth1")) + self.form.list.setColumnWidth(2,params.get_param_arch("ScheduleColumnWidth2")) + self.form.list.setColumnWidth(3,params.get_param_arch("ScheduleColumnWidth3")) + w = params.get_param_arch("ScheduleDialogWidth") + h = params.get_param_arch("ScheduleDialogHeight") self.form.resize(w,h) # set delegate - Not using custom delegates for now... @@ -712,13 +713,12 @@ class ArchScheduleTaskPanel: """Saves the changes and closes the dialog""" # store widths - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - p.SetInt("ScheduleColumnWidth0",self.form.list.columnWidth(0)) - p.SetInt("ScheduleColumnWidth1",self.form.list.columnWidth(1)) - p.SetInt("ScheduleColumnWidth2",self.form.list.columnWidth(2)) - p.SetInt("ScheduleColumnWidth3",self.form.list.columnWidth(3)) - p.SetInt("ScheduleDialogWidth",self.form.width()) - p.SetInt("ScheduleDialogHeight",self.form.height()) + params.set_param_arch("ScheduleColumnWidth0",self.form.list.columnWidth(0)) + params.set_param_arch("ScheduleColumnWidth1",self.form.list.columnWidth(1)) + params.set_param_arch("ScheduleColumnWidth2",self.form.list.columnWidth(2)) + params.set_param_arch("ScheduleColumnWidth3",self.form.list.columnWidth(3)) + params.set_param_arch("ScheduleDialogWidth",self.form.width()) + params.set_param_arch("ScheduleDialogHeight",self.form.height()) # commit values self.writeValues() diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 281c525425..ae3f058c85 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -31,6 +31,8 @@ import uuid import time from FreeCAD import Vector +from draftutils import params + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtCore, QtGui @@ -346,7 +348,6 @@ def getSVG(source, windows.append(o) objs = nonspaces - archUserParameters = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") scaledLineWidth = linewidth/scale if renderMode in ["Coin",2,"Coin mono",3]: # don't scale linewidths in coin mode @@ -357,11 +358,11 @@ def getSVG(source, scaledCutLineWidth = cutlinewidth/scale svgCutLineWidth = str(scaledCutLineWidth) + 'px' else: - st = archUserParameters.GetFloat("CutLineThickness",2) + st = params.get_param_arch("CutLineThickness") svgCutLineWidth = str(scaledLineWidth * st) + 'px' - yt = archUserParameters.GetFloat("SymbolLineThickness",0.6) + yt = params.get_param_arch("SymbolLineThickness") svgSymbolLineWidth = str(linewidth * yt) - hiddenPattern = archUserParameters.GetString("archHiddenPattern","30,10") + hiddenPattern = params.get_param_arch("archHiddenPattern") svgHiddenPattern = hiddenPattern.replace(" ","") #fillpattern = '= 0: FreeCADGui.Snapper.setSelectMode(False) self.tracker.length(self.Width) - self.tracker.width(self.Thickness) self.tracker.height(self.Height) + self.tracker.width(self.W1) self.tracker.on() self.pic.hide() self.im.show() @@ -1180,7 +1174,9 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent): typeidx = (i*5)+1 if typeidx < len(obj.WindowParts): typ = obj.WindowParts[typeidx] - if typ == WindowPartTypes[2]: # transparent parts + if typ == WindowPartTypes[0]: # "Frame" + ccol = ArchCommands.getDefaultColor("") + elif typ == WindowPartTypes[2]: # "Glass panel" ccol = ArchCommands.getDefaultColor("WindowGlass") if not ccol: ccol = base diff --git a/src/Mod/Arch/Resources/ui/preferences-archdefaults.ui b/src/Mod/Arch/Resources/ui/preferences-archdefaults.ui index 09c08af4e3..7ce6a3b397 100644 --- a/src/Mod/Arch/Resources/ui/preferences-archdefaults.ui +++ b/src/Mod/Arch/Resources/ui/preferences-archdefaults.ui @@ -25,135 +25,62 @@ Walls - + - - - - - Width: - - - - - - - mm - - - 9999.989999999999782 - - - 200.000000000000000 - - - WallWidth - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Height: - - - - - - - mm - - - 9999.989999999999782 - - - 3000.000000000000000 - - - WallHeight - - - Mod/Arch - - - - + + + Use sketches + + + true + + + WallSketches + + + Mod/Arch + + - - - - - Use sketches - - - true - - - WallSketches - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Color: - - - - - - - This is the default color for new Wall objects - - - - 214 - 214 - 214 - - - - WallColor - - - Mod/Arch - - - - + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Color: + + + + + + + This is the default color for new Wall objects + + + + 214 + 214 + 214 + + + + WallColor + + + Mod/Arch + + @@ -163,158 +90,46 @@ Structures - + - - - - - Length: - - - - - - - mm - - - 9999.989999999999782 - - - 100.000000000000000 - - - StructureLength - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Width: - - - - - - - mm - - - 9999.989999999999782 - - - 100.000000000000000 - - - StructureWidth - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Height: - - - - - - - mm - - - 9999.989999999999782 - - - 1000.000000000000000 - - - StructureHeight - - - Mod/Arch - - - - + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Color: - - - - - - - This is the default color for new Structure objects - - - - 150 - 169 - 186 - - - - StructureColor - - - Mod/Arch - - - - + + + Color: + + + + + + + This is the default color for new Structure objects + + + + 150 + 169 + 186 + + + + StructureColor + + + Mod/Arch + + @@ -443,208 +258,87 @@ Windows - + - - - - - Width: - - - - - - - The default width for new windows - - - mm - - - 99999.990000000005239 - - - 1000.000000000000000 - - - WindowWidth - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Height: - - - - - - - The default height for new windows - - - mm - - - 99999.990000000005239 - - - 1000.000000000000000 - - - WindowHeight - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Thickness: - - - - - - - The default thickness for new windows - - - mm - - - 99999.990000000005239 - - - 100.000000000000000 - - - WindowThickness - - - Mod/Arch - - - - + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Transparency: - - - - - - - 85 - - - WindowTransparency - - - Mod/Arch - - - - - - - Frame color: - - - - - - - - 33 - 45 - 66 - - - - WindowColor - - - Mod/Arch - - - - - - - Glass color: - - - - - - - - 93 - 183 - 203 - - - - WindowGlassColor - - - Mod/Arch - - - - + + + Transparency: + + + + + + + 85 + + + WindowTransparency + + + Mod/Arch + + + + + + + Frame color: + + + + + + + + 33 + 45 + 66 + + + + WindowColor + + + Mod/Arch + + + + + + + Glass color: + + + + + + + + 93 + 183 + 203 + + + + WindowGlassColor + + + Mod/Arch + + @@ -811,155 +505,43 @@ Panels - + - - - - - Length: - - - - - - - mm - - - 99999.990000000005239 - - - 1000.000000000000000 - - - PanelLength - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Width: - - - - - - - mm - - - 9999.989999999999782 - - - 1000.000000000000000 - - - PanelWidth - - - Mod/Arch - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Thickness - - - - - - - mm - - - 9999.989999999999782 - - - 10.000000000000000 - - - PanelThickness - - - Mod/Arch - - - - + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Color: - - - - - - - - 203 - 160 - 111 - - - - PanelColor - - - Mod/Arch - - - - + + + Color: + + + + + + + + 203 + 160 + 111 + + + + PanelColor + + + Mod/Arch + + @@ -1181,6 +763,13 @@ + + + + Qt::Vertical + + + diff --git a/src/Mod/Arch/exportIFC.py b/src/Mod/Arch/exportIFC.py index c10938cd90..e4e8dec5f6 100644 --- a/src/Mod/Arch/exportIFC.py +++ b/src/Mod/Arch/exportIFC.py @@ -44,6 +44,7 @@ import exportIFCStructuralTools from DraftGeomUtils import vec from importIFCHelper import dd2dms +from draftutils import params from draftutils.messages import _msg, _err if FreeCAD.GuiUp: @@ -107,12 +108,10 @@ END-ISO-10303-21; def getPreferences(): """Retrieve the IFC preferences available in import and export.""" - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - - if FreeCAD.GuiUp and p.GetBool("ifcShowDialog", False): + if FreeCAD.GuiUp and params.get_param_arch("ifcShowDialog"): FreeCADGui.showPreferences("Import-Export", 1) - ifcunit = p.GetInt("ifcUnit", 0) + ifcunit = params.get_param_arch("ifcUnit") # Factor to multiply the dimension in millimeters # mm x 0.001 = metre @@ -142,20 +141,20 @@ def getPreferences(): # some objects may be "unreferenced" and won't belong to the `IfcProject`. # Some applications may fail at importing these unreferenced objects. preferences = { - 'DEBUG': p.GetBool("ifcDebug", False), - 'CREATE_CLONES': p.GetBool("ifcCreateClones", True), - 'FORCE_BREP': p.GetBool("ifcExportAsBrep", False), - 'STORE_UID': p.GetBool("ifcStoreUid", True), - 'SERIALIZE': p.GetBool("ifcSerialize", False), - 'EXPORT_2D': p.GetBool("ifcExport2D", True), - 'FULL_PARAMETRIC': p.GetBool("IfcExportFreeCADProperties", False), - 'ADD_DEFAULT_SITE': p.GetBool("IfcAddDefaultSite", True), - 'ADD_DEFAULT_BUILDING': p.GetBool("IfcAddDefaultBuilding", True), - 'ADD_DEFAULT_STOREY': p.GetBool("IfcAddDefaultStorey", True), + 'DEBUG': params.get_param_arch("ifcDebug"), + 'CREATE_CLONES': params.get_param_arch("ifcCreateClones"), + 'FORCE_BREP': params.get_param_arch("ifcExportAsBrep"), + 'STORE_UID': params.get_param_arch("ifcStoreUid"), + 'SERIALIZE': params.get_param_arch("ifcSerialize"), + 'EXPORT_2D': params.get_param_arch("ifcExport2D"), + 'FULL_PARAMETRIC': params.get_param_arch("IfcExportFreeCADProperties"), + 'ADD_DEFAULT_SITE': params.get_param_arch("IfcAddDefaultSite"), + 'ADD_DEFAULT_BUILDING': params.get_param_arch("IfcAddDefaultBuilding"), + 'ADD_DEFAULT_STOREY': params.get_param_arch("IfcAddDefaultStorey"), 'IFC_UNIT': u, 'SCALE_FACTOR': f, - 'GET_STANDARD': p.GetBool("getStandardType", False), - 'EXPORT_MODEL': ['arch', 'struct', 'hybrid'][p.GetInt("ifcExportModel", 0)] + 'GET_STANDARD': params.get_param_arch("getStandardType"), + 'EXPORT_MODEL': ['arch', 'struct', 'hybrid'][params.get_param_arch("ifcExportModel")] } # get ifcopenshell version @@ -175,7 +174,7 @@ def getPreferences(): schema = ifcopenshell.schema_identifier elif ifcos_version >= 0.6: # v0.6 onwards allows to set our own schema - schema = ["IFC4", "IFC2X3"][p.GetInt("IfcVersion", 0)] + schema = ["IFC4", "IFC2X3"][params.get_param_arch("IfcVersion")] else: schema = "IFC2X3" @@ -1869,7 +1868,7 @@ def checkRectangle(edges): or not. It will return True when edges form a rectangular shape or return False when edges do not form a rectangular shape.""" - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("DisableIfcRectangleProfileDef",False): + if params.get_param_arch("DisableIfcRectangleProfileDef"): return False if len(edges) != 4: return False @@ -2226,8 +2225,8 @@ def getRepresentation( except Base.FreeCADError: pass if curves: - joinfacets = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcJoinCoplanarFacets",False) - usedae = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcUseDaeOptions",False) + joinfacets = params.get_param_arch("ifcJoinCoplanarFacets") + usedae = params.get_param_arch("ifcUseDaeOptions") if joinfacets: result = Arch.removeCurves(fcsolid,dae=usedae) if result: diff --git a/src/Mod/Arch/exportIFCHelper.py b/src/Mod/Arch/exportIFCHelper.py index 926aecf553..cd2f6c0304 100644 --- a/src/Mod/Arch/exportIFCHelper.py +++ b/src/Mod/Arch/exportIFCHelper.py @@ -25,6 +25,7 @@ import math import FreeCAD # import Draft import ifcopenshell +from draftutils import params def getObjectsOfIfcType(objects, ifcType): results = [] @@ -204,8 +205,8 @@ class recycler: def __init__(self,ifcfile,template=True): self.ifcfile = ifcfile - self.compress = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcCompress",True) - self.mergeProfiles = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcMergeProfiles",False) + self.compress = params.get_param_arch("ifcCompress") + self.mergeProfiles = params.get_param_arch("ifcMergeProfiles") self.cartesianpoints = {} self.directions = {} self.axis2placement3ds = {} diff --git a/src/Mod/Arch/importDAE.py b/src/Mod/Arch/importDAE.py index 2dfaad11b7..fea72e98e9 100644 --- a/src/Mod/Arch/importDAE.py +++ b/src/Mod/Arch/importDAE.py @@ -20,6 +20,8 @@ #*************************************************************************** import FreeCAD, Mesh, os, numpy, MeshPart, Arch, Draft +from draftutils import params + if FreeCAD.GuiUp: from draftutils.translate import translate else: @@ -65,15 +67,14 @@ def triangulate(shape): "triangulates the given face" - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - mesher = p.GetInt("ColladaMesher",0) - tessellation = p.GetFloat("ColladaTessellation",1.0) - grading = p.GetFloat("ColladaGrading",0.3) - segsperedge = p.GetInt("ColladaSegsPerEdge",1) - segsperradius = p.GetInt("ColladaSegsPerRadius",2) - secondorder = p.GetBool("ColladaSecondOrder",False) - optimize = p.GetBool("ColladaOptimize",True) - allowquads = p.GetBool("ColladaAllowQuads",False) + mesher = params.get_param_arch("ColladaMesher") + tessellation = params.get_param_arch("ColladaTessellation") + grading = params.get_param_arch("ColladaGrading") + segsperedge = params.get_param_arch("ColladaSegsPerEdge") + segsperradius = params.get_param_arch("ColladaSegsPerRadius") + secondorder = params.get_param_arch("ColladaSecondOrder") + optimize = params.get_param_arch("ColladaOptimize") + allowquads = params.get_param_arch("ColladaAllowQuads") if mesher == 0: return shape.tessellate(tessellation) elif mesher == 1: @@ -178,12 +179,9 @@ def export(exportList,filename,tessellation=1,colors=None): curved surfaces into triangles.""" if not checkCollada(): return - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - scale = p.GetFloat("ColladaScalingFactor",1.0) + scale = params.get_param_arch("ColladaScalingFactor") scale = scale * 0.001 # from millimeters (FreeCAD) to meters (Collada) - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View") - c = p.GetUnsigned("DefaultShapeColor",4294967295) - defaultcolor = (float((c>>24)&0xFF)/255.0,float((c>>16)&0xFF)/255.0,float((c>>8)&0xFF)/255.0) + defaultcolor = Draft.get_rgba_tuple(params.get_param_view("DefaultShapeColor"))[:3] colmesh = collada.Collada() colmesh.assetInfo.upaxis = collada.asset.UP_AXIS.Z_UP # authoring info diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index d05aac8e8d..bf4d65ad70 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -42,6 +42,7 @@ import ArchIFCSchema import importIFCHelper import importIFCmulticore +from draftutils import params from draftutils.messages import _msg, _err if FreeCAD.GuiUp: @@ -379,7 +380,7 @@ def insert(srcfile, docname, skip=[], only=[], root=None, preferences=None): if preferences['DEBUG']: print(" no layer found", ptype,end="") # checking for full FreeCAD parametric definition, overriding everything else - if psets and FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("IfcImportFreeCADProperties",False): + if psets and params.get_param_arch("IfcImportFreeCADProperties"): if "FreeCADPropertySet" in [ifcfile[pset].Name for pset in psets.keys()]: if preferences['DEBUG']: print(" restoring from parametric definition...",end="") obj,parametrics = importIFCHelper.createFromProperties(psets,ifcfile,parametrics) diff --git a/src/Mod/Arch/importIFCHelper.py b/src/Mod/Arch/importIFCHelper.py index 3e86fd522e..0939e5fdcb 100644 --- a/src/Mod/Arch/importIFCHelper.py +++ b/src/Mod/Arch/importIFCHelper.py @@ -26,11 +26,12 @@ import FreeCAD import Arch import ArchIFC +from draftutils import params +from draftutils.messages import _msg, _wrn + if FreeCAD.GuiUp: import FreeCADGui as Gui -from draftutils.messages import _msg, _wrn - PREDEFINED_RGB = {"black": (0, 0, 0), "red": (1.0, 0, 0), @@ -82,29 +83,27 @@ def getPreferences(): 2 = Part shapes 3 = One compound per storey """ - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - - if FreeCAD.GuiUp and p.GetBool("ifcShowDialog", False): + if FreeCAD.GuiUp and params.get_param_arch("ifcShowDialog"): Gui.showPreferences("Import-Export", 0) preferences = { - 'DEBUG': p.GetBool("ifcDebug", False), - 'PREFIX_NUMBERS': p.GetBool("ifcPrefixNumbers", False), - 'SKIP': p.GetString("ifcSkip", "").split(","), - 'SEPARATE_OPENINGS': p.GetBool("ifcSeparateOpenings", False), - 'ROOT_ELEMENT': p.GetString("ifcRootElement", "IfcProduct"), - 'GET_EXTRUSIONS': p.GetBool("ifcGetExtrusions", False), - 'MERGE_MATERIALS': p.GetBool("ifcMergeMaterials", False), - 'MERGE_MODE_ARCH': p.GetInt("ifcImportModeArch", 0), - 'MERGE_MODE_STRUCT': p.GetInt("ifcImportModeStruct", 1), - 'CREATE_CLONES': p.GetBool("ifcCreateClones", True), - 'IMPORT_PROPERTIES': p.GetBool("ifcImportProperties", False), - 'SPLIT_LAYERS': p.GetBool("ifcSplitLayers", False), # wall layer, not layer for visual props - 'FITVIEW_ONIMPORT': p.GetBool("ifcFitViewOnImport", False), - 'ALLOW_INVALID': p.GetBool("ifcAllowInvalid", False), - 'REPLACE_PROJECT': p.GetBool("ifcReplaceProject", False), - 'MULTICORE': p.GetInt("ifcMulticore", 0), - 'IMPORT_LAYER': p.GetBool("ifcImportLayer", True) + 'DEBUG': params.get_param_arch("ifcDebug"), + 'PREFIX_NUMBERS': params.get_param_arch("ifcPrefixNumbers"), + 'SKIP': params.get_param_arch("ifcSkip").split(","), + 'SEPARATE_OPENINGS': params.get_param_arch("ifcSeparateOpenings"), + 'ROOT_ELEMENT': params.get_param_arch("ifcRootElement"), + 'GET_EXTRUSIONS': params.get_param_arch("ifcGetExtrusions"), + 'MERGE_MATERIALS': params.get_param_arch("ifcMergeMaterials"), + 'MERGE_MODE_ARCH': params.get_param_arch("ifcImportModeArch"), + 'MERGE_MODE_STRUCT': params.get_param_arch("ifcImportModeStruct"), + 'CREATE_CLONES': params.get_param_arch("ifcCreateClones"), + 'IMPORT_PROPERTIES': params.get_param_arch("ifcImportProperties"), + 'SPLIT_LAYERS': params.get_param_arch("ifcSplitLayers"), # wall layer, not layer for visual props + 'FITVIEW_ONIMPORT': params.get_param_arch("ifcFitViewOnImport"), + 'ALLOW_INVALID': params.get_param_arch("ifcAllowInvalid"), + 'REPLACE_PROJECT': params.get_param_arch("ifcReplaceProject"), + 'MULTICORE': params.get_param_arch("ifcMulticore"), + 'IMPORT_LAYER': params.get_param_arch("ifcImportLayer") } if preferences['MERGE_MODE_ARCH'] > 0: diff --git a/src/Mod/Arch/importIFClegacy.py b/src/Mod/Arch/importIFClegacy.py index bf2e1a36aa..037e889ce5 100644 --- a/src/Mod/Arch/importIFClegacy.py +++ b/src/Mod/Arch/importIFClegacy.py @@ -27,6 +27,7 @@ import FreeCAD, Arch, Draft, os, sys, time, Part, DraftVecUtils, uuid, math, re +from draftutils import params from draftutils.translate import translate __title__="FreeCAD IFC importer" @@ -82,19 +83,18 @@ def getConfig(): global SKIP, CREATE_IFC_GROUPS, ASMESH, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS, SEPARATE_PLACEMENTS, JOINSOLIDS, AGGREGATE_WINDOWS IMPORT_IFC_FURNITURE = False ASMESH = ["IfcFurnishingElement"] - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - CREATE_IFC_GROUPS = p.GetBool("createIfcGroups",False) - FORCE_PYTHON_PARSER = p.GetBool("forceIfcPythonParser",False) - DEBUG = p.GetBool("ifcDebug",False) - SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False) - SEPARATE_PLACEMENTS = p.GetBool("ifcSeparatePlacements",False) - PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False) - JOINSOLIDS = p.GetBool("ifcJoinSolids",False) - AGGREGATE_WINDOWS = p.GetBool("ifcAggregateWindows",False) - skiplist = p.GetString("ifcSkip","") + CREATE_IFC_GROUPS = params.get_param_arch("createIfcGroups") + FORCE_PYTHON_PARSER = params.get_param_arch("forceIfcPythonParser") + DEBUG = params.get_param_arch("ifcDebug") + SEPARATE_OPENINGS = params.get_param_arch("ifcSeparateOpenings") + SEPARATE_PLACEMENTS = params.get_param_arch("ifcSeparatePlacements") + PREFIX_NUMBERS = params.get_param_arch("ifcPrefixNumbers") + JOINSOLIDS = params.get_param_arch("ifcJoinSolids") + AGGREGATE_WINDOWS = params.get_param_arch("ifcAggregateWindows") + skiplist = params.get_param_arch("ifcSkip") if skiplist: SKIP = skiplist.split(",") - asmeshlist = p.GetString("ifcAsMesh","") + asmeshlist = params.get_param_arch("ifcAsMesh") if asmeshlist: ASMESH = asmeshlist.split(",") @@ -811,7 +811,7 @@ def getVector(entity): def getSchema(): "retrieves the express schema" - custom = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetString("CustomIfcSchema","") + custom = params.get_param_arch("CustomIfcSchema") if custom: if os.path.exists(custom): if DEBUG: print("Using custom schema: ",custom.split(os.sep)[-1]) @@ -943,10 +943,9 @@ def export(exportList,filename): # creating base IFC project getConfig() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - scaling = p.GetFloat("IfcScalingFactor",1.0) - exporttxt = p.GetBool("IfcExportList",False) - forcebrep = p.GetBool("ifcExportAsBrep",False) + scaling = params.get_param_arch("IfcScalingFactor") + exporttxt = params.get_param_arch("IfcExportList") + forcebrep = params.get_param_arch("ifcExportAsBrep") application = "FreeCAD" ver = FreeCAD.Version() version = ver[0]+"."+ver[1]+" build"+ver[2] @@ -1394,9 +1393,7 @@ class IfcSchema: def __init__(self, filename): self.filename = filename if not os.path.exists(filename): - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") - p = p.GetString("MacroPath","") - filename = p + os.sep + filename + filename = FreeCAD.getUserMacroDir(True) + os.sep + filename if not os.path.exists(filename): raise ImportError("no IFCSchema file found!") diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py index 6fbfe04eb0..b69d6d92a7 100644 --- a/src/Mod/Arch/importOBJ.py +++ b/src/Mod/Arch/importOBJ.py @@ -31,6 +31,7 @@ import DraftGeomUtils import Mesh import MeshPart import Part +from draftutils import params if FreeCAD.GuiUp: from draftutils.translate import translate @@ -80,8 +81,7 @@ def getIndices(obj,shape,offsetv,offsetvn): except Exception: # unimplemented curve type hascurve = True if hascurve: - param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Mesh") - tol = param.GetFloat("MaxDeviationExport",0.1) + tol = params.get_param("MaxDeviationExport",path="Mod/Mesh") mesh = Mesh.Mesh() mesh.addFacets(shape.getFaces(tol)) FreeCAD.Console.PrintWarning(translate("Arch","Found a shape containing curves, triangulating")+"\n") diff --git a/src/Mod/Arch/importSHP.py b/src/Mod/Arch/importSHP.py index 6878f50682..4fe6c88eb3 100644 --- a/src/Mod/Arch/importSHP.py +++ b/src/Mod/Arch/importSHP.py @@ -141,9 +141,7 @@ def checkShapeFileLibrary(): FreeCAD.Console.PrintError(translate("Arch","Error: Unable to download from:")+" "+url+"\n") return False b = u.read() - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") - fp = p.GetString("MacroPath",os.path.join(FreeCAD.getUserAppDataDir(),"Macros")) - fp = os.path.join(fp,"shapefile.py") + fp = os.path.join(FreeCAD.getUserMacroDir(True),"shapefile.py") f = pythonopen(fp,"wb") f.write(b) f.close() diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index fce3a67fc9..09c47218a6 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -393,8 +393,91 @@ def _get_param_dictionary(): # Arch parameters that are not in the preferences: param_dict["Mod/Arch"] = { + "ClaimHosted": ("bool", True), + "CustomIfcSchema": ("string", ""), # importIFClegacy.py + "createIfcGroups": ("bool", False), # importIFClegacy.py + "DoorHeight": ("float", 2100.0), + "DoorPreset": ("int", 5), + "DoorSill": ("float", 0.0), + "DoorWidth": ("float", 1000.0), + "FreeLinking": ("bool", False), + "forceIfcPythonParser": ("bool", False), # importIFClegacy.py + "getStandardType": ("bool", False), + "ifcAggregateWindows": ("bool", False), # importIFClegacy.py + "ifcAsMesh": ("string", ""), # importIFClegacy.py + "IfcExportList": ("bool", False), # importIFClegacy.py + "ifcImportLayer": ("bool", True), + "ifcJoinSolids": ("bool", False), # importIFClegacy.py + "ifcMergeProfiles": ("bool", False), + "IfcScalingFactor": ("float", 1.0), # importIFClegacy.py + "ifcSeparatePlacements": ("bool", False), # importIFClegacy.py + "MultiMaterialColumnWidth0": ("int", 60), + "MultiMaterialColumnWidth1": ("int", 60), + "PanelLength": ("float", 1000.0), + "PanelThickness": ("float", 10.0), + "PanelWidth": ("float", 1000.0), + "PrecastBase": ("float", 0.0), + "PrecastChamfer": ("float", 0.0), + "PrecastDentHeight": ("float", 0.0), + "PrecastDentLength": ("float", 0.0), + "PrecastDentWidth": ("float", 0.0), + "PrecastDownLength": ("float", 0.0), + "PrecastGrooveDepth": ("float", 0.0), + "PrecastGrooveHeight": ("float", 0.0), + "PrecastGrooveSpacing": ("float", 0.0), + "PrecastHoleMajor": ("float", 0.0), + "PrecastHoleMinor": ("float", 0.0), + "PrecastHoleSpacing": ("float", 0.0), + "PrecastRiser": ("float", 0.0), + "PrecastTread": ("float", 0.0), + "ScheduleColumnWidth0": ("int", 100), + "ScheduleColumnWidth1": ("int", 100), + "ScheduleColumnWidth2": ("int", 50), + "ScheduleColumnWidth3": ("int", 100), + "ScheduleDialogHeight": ("int", 200), + "ScheduleDialogWidth": ("int", 300), + "StructureHeight": ("float", 1000.0), + "StructureLength": ("float", 100.0), + "StructurePreset": ("string", ""), + "StructureWidth": ("float", 100.0), + "swallowAdditions": ("bool", True), + "swallowSubtractions": ("bool", True), + "WallAlignment": ("int", 0), + "WallHeight": ("float", 3000.0), + "WallWidth": ("float", 200.0), + "WindowH1": ("float", 50.0), + "WindowH2": ("float", 50.0), + "WindowH3": ("float", 50.0), + "WindowHeight": ("float", 1000.0), + "WindowO1": ("float", 0.0), + "WindowO2": ("float", 50.0), + "WindowPreset": ("int", 0), + "WindowSill": ("float", 0.0), + "WindowW1": ("float", 100.0), + "WindowW2": ("float", 50.0), + "WindowWidth": ("float", 1000.0), + } + # For the Mod/Mesh parameters we do not check the preferences: + param_dict["Mod/Mesh"] = { + "MaxDeviationExport": ("float", 0.1), + } + # For the Mod/TechDraw/PAT parameters we do not check the preferences: + param_dict["Mod/TechDraw/PAT"] = { + "FilePattern": ("string", ""), + "NamePattern": ("string", "Diamant"), + } + + # For the General parameters we do not check the preferences: + param_dict["General"] = { + "ToolbarIconSize": ("int", 24), + } + + # For the Units parameters we do not check the preferences: + param_dict["Units"] = { + "Decimals": ("int", 2), + "UserSchema": ("int", 0), } # For the View parameters we do not check the preferences: @@ -414,23 +497,6 @@ def _get_param_dictionary(): "NewDocumentCameraScale": ("float", 100.0), } - # For the General parameters we do not check the preferences: - param_dict["General"] = { - "ToolbarIconSize": ("int", 24), - } - - # For the Units parameters we do not check the preferences: - param_dict["Units"] = { - "Decimals": ("int", 2), - "UserSchema": ("int", 0), - } - - # For the Mod/TechDraw/PAT parameters we do not check the preferences: - param_dict["Mod/TechDraw/PAT"] = { - "FilePattern": ("string", ""), - "NamePattern": ("string", "Diamant"), - } - # Preferences ui files are stored in resource files. # For the Draft Workbench: /Mod/Draft/Draft_rc.py From 5e67755b4f274f62c226f9be8e10e950e5f8128a Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 12 Jan 2024 12:24:01 +0100 Subject: [PATCH 19/34] Multiply textheight by DefaultAnnoScaleMultiplier --- src/Mod/Arch/ArchAxis.py | 4 ++-- src/Mod/Arch/ArchBuildingPart.py | 2 +- src/Mod/Arch/ArchSectionPlane.py | 2 +- src/Mod/Arch/ArchSpace.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index b23aff4612..7384fef8ed 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -226,11 +226,11 @@ class _ViewProviderAxis: def setProperties(self,vobj): - ts = params.get_param("textheight") + ts = params.get_param("textheight") * params.get_param("DefaultAnnoScaleMultiplier") pl = vobj.PropertiesList if not "BubbleSize" in pl: vobj.addProperty("App::PropertyLength","BubbleSize","Axis", QT_TRANSLATE_NOOP("App::Property","The size of the axis bubbles")) - vobj.BubbleSize = ts*1.42 + vobj.BubbleSize = ts * 1.42 if not "NumberingStyle" in pl: vobj.addProperty("App::PropertyEnumeration","NumberingStyle","Axis", QT_TRANSLATE_NOOP("App::Property","The numbering style")) vobj.NumberingStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"] diff --git a/src/Mod/Arch/ArchBuildingPart.py b/src/Mod/Arch/ArchBuildingPart.py index e327004fcc..c7fa948cf0 100644 --- a/src/Mod/Arch/ArchBuildingPart.py +++ b/src/Mod/Arch/ArchBuildingPart.py @@ -572,7 +572,7 @@ class ViewProviderBuildingPart: vobj.FontName = params.get_param("textfont") if not "FontSize" in pl: vobj.addProperty("App::PropertyLength","FontSize","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The font size of texts")) - vobj.FontSize = params.get_param("textheight") + vobj.FontSize = params.get_param("textheight") * params.get_param("DefaultAnnoScaleMultiplier") if not "DiffuseColor" in pl: vobj.addProperty("App::PropertyColorList","DiffuseColor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The individual face colors")) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index ae3f058c85..33596ee4ec 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -971,7 +971,7 @@ class _ViewProviderSectionPlane: vobj.FontName = params.get_param("textfont") if not "FontSize" in pl: vobj.addProperty("App::PropertyLength","FontSize","SectionPlane",QT_TRANSLATE_NOOP("App::Property","The size of the text font")) - vobj.FontSize = params.get_param("textheight") + vobj.FontSize = params.get_param("textheight") * params.get_param("DefaultAnnoScaleMultiplier") def onDocumentRestored(self,vobj): diff --git a/src/Mod/Arch/ArchSpace.py b/src/Mod/Arch/ArchSpace.py index ebe2b56fe1..3fcc7af653 100644 --- a/src/Mod/Arch/ArchSpace.py +++ b/src/Mod/Arch/ArchSpace.py @@ -519,10 +519,10 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent): vobj.TextColor = (0.0,0.0,0.0,1.0) if not "FontSize" in pl: vobj.addProperty("App::PropertyLength", "FontSize", "Space",QT_TRANSLATE_NOOP("App::Property","The size of the text font")) - vobj.FontSize = params.get_param("textheight") + vobj.FontSize = params.get_param("textheight") * params.get_param("DefaultAnnoScaleMultiplier") if not "FirstLine" in pl: vobj.addProperty("App::PropertyLength", "FirstLine", "Space",QT_TRANSLATE_NOOP("App::Property","The size of the first line of text")) - vobj.FirstLine = params.get_param("textheight") + vobj.FirstLine = params.get_param("textheight") * params.get_param("DefaultAnnoScaleMultiplier") if not "LineSpacing" in pl: vobj.addProperty("App::PropertyFloat", "LineSpacing", "Space",QT_TRANSLATE_NOOP("App::Property","The space between the lines of text")) vobj.LineSpacing = 1.0 From 238e8acda55a4234c4342e0294f2e1ce46659bc6 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Wed, 17 Jan 2024 20:11:59 -0500 Subject: [PATCH 20/34] [TD]fix Section scale for DPGI base views --- src/Mod/TechDraw/App/DrawProjGroupItem.cpp | 10 ++++++ src/Mod/TechDraw/App/DrawProjGroupItem.h | 1 + src/Mod/TechDraw/App/DrawView.h | 1 + src/Mod/TechDraw/Gui/TaskSectionView.cpp | 38 +++++++--------------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp index 17755f4ea8..d49cbedaa4 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp @@ -329,6 +329,16 @@ double DrawProjGroupItem::getScale(void) const return 1.0; } +int DrawProjGroupItem::getScaleType() const +{ + auto pgroup = getPGroup(); + if (pgroup) { + return pgroup->getScaleType(); + } + + return ScaleType.getValue(); +} + void DrawProjGroupItem::unsetupObject() { if (!getPGroup()) { diff --git a/src/Mod/TechDraw/App/DrawProjGroupItem.h b/src/Mod/TechDraw/App/DrawProjGroupItem.h index 7e1a93fe4d..1a15f68241 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupItem.h +++ b/src/Mod/TechDraw/App/DrawProjGroupItem.h @@ -86,6 +86,7 @@ public: const bool flip=true) const override; double getScale() const override; + int getScaleType() const override; void autoPosition(); bool isAnchor() const; diff --git a/src/Mod/TechDraw/App/DrawView.h b/src/Mod/TechDraw/App/DrawView.h index 4082c1fcb3..7bd6adce88 100644 --- a/src/Mod/TechDraw/App/DrawView.h +++ b/src/Mod/TechDraw/App/DrawView.h @@ -100,6 +100,7 @@ public: void showProgressMessage(std::string featureName, std::string text); virtual double getScale(void) const; + virtual int getScaleType() const { return ScaleType.getValue(); }; void checkScale(void); virtual void handleXYLock(void); diff --git a/src/Mod/TechDraw/Gui/TaskSectionView.cpp b/src/Mod/TechDraw/Gui/TaskSectionView.cpp index 059145bacc..3eaa4a937d 100644 --- a/src/Mod/TechDraw/Gui/TaskSectionView.cpp +++ b/src/Mod/TechDraw/Gui/TaskSectionView.cpp @@ -126,11 +126,15 @@ void TaskSectionView::setUiPrimary() // Base::Console().Message("TSV::setUiPrimary()\n"); setWindowTitle(QObject::tr("Create Section View")); + // note DPGI will have a custom scale type and scale = 1.0. In this case, + // we need the values from the parent DPG! ui->sbScale->setValue(m_base->getScale()); - ui->cmbScaleType->setCurrentIndex(m_base->ScaleType.getValue()); + + ui->cmbScaleType->setCurrentIndex(m_base->getScaleType()); //Allow or prevent scale changing initially - if (m_base->ScaleType.isValue("Custom")) { + if (m_base->getScaleType() == 2) { + // custom scale type ui->sbScale->setEnabled(true); } else { @@ -160,7 +164,7 @@ void TaskSectionView::setUiEdit() ui->leSymbol->setText(qTemp); ui->sbScale->setValue(m_section->getScale()); - ui->cmbScaleType->setCurrentIndex(m_section->ScaleType.getValue()); + ui->cmbScaleType->setCurrentIndex(m_section->getScaleType()); //Allow or prevent scale changing initially if (m_section->ScaleType.isValue("Custom")) { ui->sbScale->setEnabled(true); @@ -240,7 +244,7 @@ void TaskSectionView::saveSectionState() if (m_section) { m_saveSymbol = m_section->SectionSymbol.getValue(); m_saveScale = m_section->getScale(); - m_saveScaleType = m_section->ScaleType.getValue(); + m_saveScaleType = m_section->getScaleType(); m_saveNormal = m_section->SectionNormal.getValue(); m_normal = m_saveNormal; m_saveDirection = m_section->Direction.getValue(); @@ -493,7 +497,7 @@ void TaskSectionView::applyAligned() TechDraw::DrawViewSection* TaskSectionView::createSectionView(void) { - // Base::Console().Message("TSV::createSectionView()\n"); + // Base::Console().Message("TSV::createSectionView()\n"); if (!isBaseValid()) { failNoObject(); return nullptr; @@ -535,17 +539,8 @@ TechDraw::DrawViewSection* TaskSectionView::createSectionView(void) m_sectionName.c_str(), ui->sbOrgX->value().getValue(), ui->sbOrgY->value().getValue(), ui->sbOrgZ->value().getValue()); - if (m_scaleEdited) { - // user has changed the scale - Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", + Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", m_sectionName.c_str(), ui->sbScale->value()); - } else { - // scale is untouched, use value from base view - Command::doCommand(Command::Doc, - "App.ActiveDocument.%s.Scale = App.ActiveDocument.%s.Scale", - m_sectionName.c_str(), - baseName.c_str()); - } int scaleType = ui->cmbScaleType->currentIndex(); Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d", @@ -582,7 +577,7 @@ TechDraw::DrawViewSection* TaskSectionView::createSectionView(void) void TaskSectionView::updateSectionView() { -// Base::Console().Message("TSV::updateSectionView() - m_sectionName: %s\n", m_sectionName.c_str()); + // Base::Console().Message("TSV::updateSectionView() - m_sectionName: %s\n", m_sectionName.c_str()); if (!isSectionValid()) { failNoObject(); return; @@ -611,17 +606,8 @@ void TaskSectionView::updateSectionView() Command::doCommand(Command::Doc, "App.activeDocument().%s.translateLabel('DrawViewSection', 'Section', '%s')", m_sectionName.c_str(), makeSectionLabel(qTemp).c_str()); - if (m_scaleEdited) { - // user has changed the scale - Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", + Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", m_sectionName.c_str(), ui->sbScale->value()); - } else { - // scale is untouched, use value from base view - Command::doCommand(Command::Doc, - "App.ActiveDocument.%s.Scale = App.ActiveDocument.%s.Scale", - m_sectionName.c_str(), - baseName.c_str()); - } int scaleType = ui->cmbScaleType->currentIndex(); Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d", From 62bd9b5e4ac1bb3fd9d99a95534c3bada611d403 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Wed, 17 Jan 2024 20:41:51 -0500 Subject: [PATCH 21/34] [TD]fix Complex Section scale with DPGI base --- src/Mod/TechDraw/Gui/TaskComplexSection.cpp | 31 +++++---------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/Mod/TechDraw/Gui/TaskComplexSection.cpp b/src/Mod/TechDraw/Gui/TaskComplexSection.cpp index df8d8fc3fa..91a7a842c2 100644 --- a/src/Mod/TechDraw/Gui/TaskComplexSection.cpp +++ b/src/Mod/TechDraw/Gui/TaskComplexSection.cpp @@ -138,7 +138,7 @@ void TaskComplexSection::setUiPrimary() setWindowTitle(QObject::tr("New Complex Section")); if (m_baseView) { ui->sbScale->setValue(m_baseView->getScale()); - ui->cmbScaleType->setCurrentIndex(m_baseView->ScaleType.getValue()); + ui->cmbScaleType->setCurrentIndex(m_baseView->getScaleType()); } else { ui->sbScale->setValue(Preferences::scale()); @@ -184,7 +184,7 @@ void TaskComplexSection::setUiEdit() ui->cmbStrategy->setCurrentIndex(m_section->ProjectionStrategy.getValue()); ui->leSymbol->setText(Base::Tools::fromStdString(m_section->SectionSymbol.getValue())); ui->sbScale->setValue(m_section->Scale.getValue()); - ui->cmbScaleType->setCurrentIndex(m_section->ScaleType.getValue()); + ui->cmbScaleType->setCurrentIndex(m_section->getScaleType()); setUiCommon(); @@ -246,7 +246,7 @@ void TaskComplexSection::saveSectionState() if (m_section) { m_saveSymbol = m_section->SectionSymbol.getValue(); m_saveScale = m_section->getScale(); - m_saveScaleType = m_section->ScaleType.getValue(); + m_saveScaleType = m_section->getScaleType(); m_saveNormal = m_section->SectionNormal.getValue(); m_saveDirection = m_section->Direction.getValue(); m_saveXDir = m_section->XDirection.getValue(); @@ -582,17 +582,9 @@ void TaskComplexSection::createComplexSection() m_sectionName.c_str(), ui->sbScale->value()); std::string baseName = m_baseView->getNameInDocument(); - if (m_scaleEdited) { - // user has changed the scale - Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", + + Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", m_sectionName.c_str(), ui->sbScale->value()); - } else { - // scale is untouched, use value from base view - Command::doCommand(Command::Doc, - "App.ActiveDocument.%s.Scale = App.ActiveDocument.%s.Scale", - m_sectionName.c_str(), - baseName.c_str()); - } int scaleType = ui->cmbScaleType->currentIndex(); Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d", @@ -672,18 +664,9 @@ void TaskComplexSection::updateComplexSection() m_sectionName.c_str(), makeSectionLabel(qTemp).c_str()); std::string baseName = m_baseView->getNameInDocument(); - if (m_scaleEdited) { - // user has changed the scale - Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", - m_sectionName.c_str(), ui->sbScale->value()); - } else { - // scale is untouched, use value from base view - Command::doCommand(Command::Doc, - "App.ActiveDocument.%s.Scale = App.ActiveDocument.%s.Scale", - m_sectionName.c_str(), - baseName.c_str()); - } + Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f", + m_sectionName.c_str(), ui->sbScale->value()); int scaleType = ui->cmbScaleType->currentIndex(); Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d", From 21905c0d624c51013554cb2583ef090e739e7491 Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 19 Jan 2024 10:26:00 +0100 Subject: [PATCH 22/34] Core: add property command, that shows property view. --- src/Gui/CommandDoc.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/Gui/Tree.cpp | 31 ++----------------------------- src/Gui/Tree.h | 2 -- src/Gui/Workbench.cpp | 2 +- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 6e1ffefefc..55d4b91d64 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -50,6 +50,7 @@ #include "BitmapFactory.h" #include "Command.h" #include "Control.h" +#include "DockWindowManager.h" #include "FileDialog.h" #include "MainWindow.h" #include "Selection.h" @@ -1715,6 +1716,41 @@ bool StdCmdEdit::isActive() return (!Selection().getCompleteSelection().empty()) || (Gui::Control().activeDialog() != nullptr); } +//=========================================================================== +// Std_Properties +//=========================================================================== +DEF_STD_CMD_A(StdCmdProperties) + +StdCmdProperties::StdCmdProperties() + : Command("Std_Properties") +{ + sGroup = "Edit"; + sMenuText = QT_TR_NOOP("Properties"); + sToolTipText = QT_TR_NOOP("Show the property view, which displays the properties of the selected object."); + sWhatsThis = "Std_Properties"; + sStatusTip = sToolTipText; + sAccel = "Alt+Return"; + sPixmap = "document-properties"; + eType = Alter3DView; +} + +void StdCmdProperties::activated(int iMsg) +{ + Q_UNUSED(iMsg); + QWidget* propertyView = Gui::DockWindowManager::instance()->getDockWindow("Property view"); + if (propertyView) { + QWidget* parent = propertyView->parentWidget(); + if (parent && !parent->isVisible()) { + parent->show(); + } + } +} + +bool StdCmdProperties::isActive() +{ + return !Selection().getCompleteSelection().empty(); +} + //====================================================================== // StdCmdExpression //=========================================================================== @@ -1969,6 +2005,7 @@ void CreateDocCommands() rcCmdMgr.addCommand(new StdCmdTransformManip()); rcCmdMgr.addCommand(new StdCmdAlignment()); rcCmdMgr.addCommand(new StdCmdEdit()); + rcCmdMgr.addCommand(new StdCmdProperties()); rcCmdMgr.addCommand(new StdCmdExpression()); } diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 3b2cc0717c..212eb7db24 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -524,13 +524,6 @@ TreeWidget::TreeWidget(const char* name, QWidget* parent) connect(this->relabelObjectAction, &QAction::triggered, this, &TreeWidget::onRelabelObject); - this->objectPropertyAction = new QAction(this); -#ifndef Q_OS_MAC - this->objectPropertyAction->setShortcut(Qt::Key_F6); -#endif - connect(this->objectPropertyAction, &QAction::triggered, - this, &TreeWidget::onObjectProperty); - this->finishEditingAction = new QAction(this); connect(this->finishEditingAction, &QAction::triggered, this, &TreeWidget::onFinishEditing); @@ -889,7 +882,7 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) MenuItem view; Gui::Application::Instance->setupContextMenu("Tree", &view); - view << "Std_Expressions"; + view << "Std_Properties" << "Separator" << "Std_Expressions"; Workbench::createLinkMenu(&view); QMenu contextMenu; @@ -898,8 +891,7 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) QMenu editMenu; QActionGroup subMenuGroup(&subMenu); subMenuGroup.setExclusive(true); - connect(&subMenuGroup, &QActionGroup::triggered, - this, &TreeWidget::onActivateDocument); + connect(&subMenuGroup, &QActionGroup::triggered, this, &TreeWidget::onActivateDocument); MenuManager::getInstance()->setupContextMenu(&view, contextMenu); // get the current item @@ -969,7 +961,6 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) // relabeling is only possible for a single selected document if (SelectedObjectsList.size() == 1) contextMenu.addAction(this->relabelObjectAction); - contextMenu.addAction(this->objectPropertyAction); auto selItems = this->selectedItems(); // if only one item is selected, setup the edit menu @@ -1091,21 +1082,6 @@ void TreeWidget::onRelabelObject() editItem(item); } -void TreeWidget::onObjectProperty() -{ - int sizeOfFirstColumn = 200; - auto prop = new PropertyView(this, sizeOfFirstColumn); - QDialog* propertyDialog = new QDialog(this); - propertyDialog->setWindowTitle(QString::fromLatin1("Properties")); - propertyDialog->resize(700, 500); - QVBoxLayout* layout = new QVBoxLayout(propertyDialog); - layout->addWidget(prop); - propertyDialog->setLayout(layout); - QPoint cursorPos = QCursor::pos() - QPoint(0, 300); - propertyDialog->move(cursorPos); - propertyDialog->show(); -} - void TreeWidget::onStartEditing() { auto action = qobject_cast(sender()); @@ -2989,9 +2965,6 @@ void TreeWidget::setupText() this->relabelObjectAction->setText(tr("Rename")); this->relabelObjectAction->setStatusTip(tr("Rename object")); - this->objectPropertyAction->setText(tr("Properties")); - this->objectPropertyAction->setStatusTip(tr("Properties of the selected object")); - this->finishEditingAction->setText(tr("Finish editing")); this->finishEditingAction->setStatusTip(tr("Finish editing object")); diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index 877cddf664..6d35edfec2 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -154,7 +154,6 @@ protected: protected Q_SLOTS: void onCreateGroup(); void onRelabelObject(); - void onObjectProperty(); void onActivateDocument(QAction*); void onStartEditing(); void onFinishEditing(); @@ -209,7 +208,6 @@ private: private: QAction* createGroupAction; QAction* relabelObjectAction; - QAction* objectPropertyAction; QAction* finishEditingAction; QAction* selectDependentsAction; QAction* skipRecomputeAction; diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index 3f03d97a57..131e938f98 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -647,7 +647,7 @@ MenuItem* StdWorkbench::setupMenuBar() const << "Std_Refresh" << "Std_BoxSelection" << "Std_BoxElementSelection" << "Std_SelectAll" << "Std_Delete" << "Std_SendToPythonConsole" << "Separator" << "Std_Placement" << "Std_TransformManip" << "Std_Alignment" - << "Std_Edit" << "Separator" << "Std_UserEditMode" << "Separator" << "Std_DlgPreferences"; + << "Std_Edit" << "Std_Properties" << "Separator" << "Std_UserEditMode" << "Separator" << "Std_DlgPreferences"; auto axoviews = new MenuItem; axoviews->setCommand("Axonometric"); From f7798327cf9a9c35752bb45fdfd17aeed6145933 Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 19 Jan 2024 10:47:10 +0100 Subject: [PATCH 23/34] Core: PropertyEditor : save properly the size of the first column. --- src/Gui/PropertyView.cpp | 6 +++--- src/Gui/PropertyView.h | 2 +- src/Gui/Tree.cpp | 4 ++-- src/Gui/propertyeditor/PropertyEditor.cpp | 11 ++++++++--- src/Gui/propertyeditor/PropertyEditor.h | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Gui/PropertyView.cpp b/src/Gui/PropertyView.cpp index fb0dda47d1..535f54fa2c 100644 --- a/src/Gui/PropertyView.cpp +++ b/src/Gui/PropertyView.cpp @@ -67,7 +67,7 @@ static ParameterGrp::handle _GetParam() { * Provides two Gui::PropertyEditor::PropertyEditor widgets, for "View" and "Data", * in two tabs. */ -PropertyView::PropertyView(QWidget *parent, int sizeOfFirstColumn) +PropertyView::PropertyView(QWidget *parent) : QWidget(parent), SelectionObserver(false, ResolveMode::NoResolve) { auto pLayout = new QGridLayout( this ); @@ -83,12 +83,12 @@ PropertyView::PropertyView(QWidget *parent, int sizeOfFirstColumn) tabs->setTabPosition(QTabWidget::South); pLayout->addWidget(tabs, 0, 0); - propertyEditorView = new Gui::PropertyEditor::PropertyEditor(parent, sizeOfFirstColumn); + propertyEditorView = new Gui::PropertyEditor::PropertyEditor(); propertyEditorView->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionView", false)); propertyEditorView->setAutomaticExpand(_GetParam()->GetBool("AutoExpandView", false)); tabs->addTab(propertyEditorView, tr("View")); - propertyEditorData = new Gui::PropertyEditor::PropertyEditor(parent, sizeOfFirstColumn); + propertyEditorData = new Gui::PropertyEditor::PropertyEditor(); propertyEditorData->setAutomaticDocumentUpdate(_GetParam()->GetBool("AutoTransactionData", true)); propertyEditorData->setAutomaticExpand(_GetParam()->GetBool("AutoExpandData", false)); tabs->addTab(propertyEditorData, tr("Data")); diff --git a/src/Gui/PropertyView.h b/src/Gui/PropertyView.h index cf539df318..a058fcd04e 100644 --- a/src/Gui/PropertyView.h +++ b/src/Gui/PropertyView.h @@ -56,7 +56,7 @@ class PropertyView : public QWidget, public Gui::SelectionObserver Q_OBJECT public: - explicit PropertyView(QWidget *parent=nullptr, int sizeOfFirstColumn = 0); + explicit PropertyView(QWidget *parent=nullptr); ~PropertyView() override; Gui::PropertyEditor::PropertyEditor* propertyEditorView; diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 212eb7db24..fe830d468f 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -61,7 +61,6 @@ #include "Macro.h" #include "MainWindow.h" #include "MenuManager.h" -#include "PropertyView.h" #include "TreeParams.h" #include "View3DInventor.h" #include "ViewProviderDocumentObject.h" @@ -891,7 +890,8 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) QMenu editMenu; QActionGroup subMenuGroup(&subMenu); subMenuGroup.setExclusive(true); - connect(&subMenuGroup, &QActionGroup::triggered, this, &TreeWidget::onActivateDocument); + connect(&subMenuGroup, &QActionGroup::triggered, + this, &TreeWidget::onActivateDocument); MenuManager::getInstance()->setupContextMenu(&view, contextMenu); // get the current item diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index 184d0420dd..e9aa88ca2d 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -51,7 +51,7 @@ FC_LOG_LEVEL_INIT("PropertyView", true, true) using namespace Gui::PropertyEditor; -PropertyEditor::PropertyEditor(QWidget *parent, int sizeOfFirstColumn) +PropertyEditor::PropertyEditor(QWidget *parent) : QTreeView(parent) , autoexpand(false) , autoupdate(false) @@ -100,8 +100,10 @@ PropertyEditor::PropertyEditor(QWidget *parent, int sizeOfFirstColumn) viewport()->installEventFilter(this); viewport()->setMouseTracking(true); - if (sizeOfFirstColumn != 0) { - header()->resizeSection(0, sizeOfFirstColumn); + auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows/PropertyView"); + int firstColumnSize = hGrp->GetInt("FirstColumnSize", 0); + if (firstColumnSize != 0) { + header()->resizeSection(0, firstColumnSize); } } @@ -872,6 +874,9 @@ bool PropertyEditor::eventFilter(QObject* object, QEvent* event) { else if (mouse_event->type() == QEvent::MouseButtonRelease && mouse_event->button() == Qt::LeftButton && dragInProgress) { dragInProgress = false; + + auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows/PropertyView"); + hGrp->SetInt("FirstColumnSize", header()->sectionSize(0)); return true; } } diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index 5c5342d129..bd01c2f99e 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -67,7 +67,7 @@ class PropertyEditor : public QTreeView Q_PROPERTY(QBrush itemBackground READ itemBackground WRITE setItemBackground DESIGNABLE true SCRIPTABLE true) // clazy:exclude=qproperty-without-notify public: - PropertyEditor(QWidget *parent = nullptr, int sizeOfFirstColumn = 0); + PropertyEditor(QWidget *parent = nullptr); ~PropertyEditor() override; /** Builds up the list view with the properties. */ From 1a4639f71f1a8416c8df266809d04f6e45829276 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Thu, 18 Jan 2024 23:28:13 +0100 Subject: [PATCH 24/34] Gui: Fix scroll behaviour in preference pages selector This fixes problem with scroll jumping after selecting page on bottom of the pages tree view. It was caused by collapsing group of the current item and then re-expanding it few lines after. Fixes: #12000 --- src/Gui/DlgPreferencesImp.cpp | 45 +++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/Gui/DlgPreferencesImp.cpp b/src/Gui/DlgPreferencesImp.cpp index 1c31064a85..cd37e6fc88 100644 --- a/src/Gui/DlgPreferencesImp.cpp +++ b/src/Gui/DlgPreferencesImp.cpp @@ -56,6 +56,28 @@ using namespace Gui::Dialog; +bool isParentOf(const QModelIndex& parent, const QModelIndex& child) +{ + for (auto it = child; it.isValid(); it = it.parent()) { + if (it == parent) { + return true; + } + } + + return false; +} + +QModelIndex findRootIndex(const QModelIndex& index) +{ + auto root = index; + + while (root.parent().isValid()) { + root = root.parent(); + } + + return root; +} + QWidget* PreferencesPageItem::getWidget() const { return _widget; @@ -714,17 +736,6 @@ void DlgPreferencesImp::showEvent(QShowEvent* ev) } } -QModelIndex findRootIndex(const QModelIndex& index) -{ - auto root = index; - - while (root.parent().isValid()) { - root = root.parent(); - } - - return root; -} - void DlgPreferencesImp::onPageSelected(const QModelIndex& index) { auto* currentItem = static_cast(_model.itemFromIndex(index)); @@ -790,14 +801,20 @@ void DlgPreferencesImp::onStackWidgetChange(int index) return; } - ui->groupsTreeView->selectionModel()->select(currentItem->index(), QItemSelectionModel::ClearAndSelect); + auto currentIndex = currentItem->index(); auto root = _model.invisibleRootItem(); for (int i = 0; i < root->rowCount(); i++) { auto currentGroup = static_cast(root->child(i)); + auto currentGroupIndex = currentGroup->index(); + + // don't do anything to group of selected item + if (isParentOf(currentGroupIndex, currentIndex)) { + continue; + } if (!currentGroup->isExpanded()) { - ui->groupsTreeView->collapse(currentGroup->index()); + ui->groupsTreeView->collapse(currentGroupIndex); } } @@ -807,6 +824,8 @@ void DlgPreferencesImp::onStackWidgetChange(int index) ui->groupsTreeView->expand(parentItem->index()); parentItem->setExpanded(wasExpanded); } + + ui->groupsTreeView->selectionModel()->select(currentIndex, QItemSelectionModel::ClearAndSelect); } void DlgPreferencesImp::changeEvent(QEvent *e) From c155edcd878e30ec94843c769d4ee87af5fb0653 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 19 Jan 2024 18:31:11 +0100 Subject: [PATCH 25/34] Draft: DraftGui.py make type of self.facecolor consistent Since V0.19 self.facecolor had two types: integer (initial value) or QColor. With this PR it is again always a QColor. --- src/Mod/Draft/DraftGui.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 6974b3b1ca..326b7a5a1c 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -163,10 +163,8 @@ class DraftToolBar: self.pointcallback = None # OBSOLETE BUT STILL USED BY SOME ADDONS AND MACROS - self.paramcolor = utils.rgba_to_argb(params.get_param_view("DefaultShapeLineColor")) - self.color = QtGui.QColor(self.paramcolor) - # ToDo: in setStyleButton() self.facecolor is assigned a QColor - self.facecolor = utils.rgba_to_argb(params.get_param_view("DefaultShapeColor")) + self.color = QtGui.QColor(utils.rgba_to_argb(params.get_param_view("DefaultShapeLineColor"))) + self.facecolor = QtGui.QColor(utils.rgba_to_argb(params.get_param_view("DefaultShapeColor"))) self.linewidth = params.get_param_view("DefaultShapeLineWidth") self.fontsize = params.get_param("textheight") From 8e48165b16a572f15aea0b4cca2171d22f21d1d4 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Fri, 19 Jan 2024 11:31:53 -0600 Subject: [PATCH 26/34] fixes #12029 --- src/Mod/Path/Path/Main/Gui/Job.py | 49 +++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Mod/Path/Path/Main/Gui/Job.py b/src/Mod/Path/Path/Main/Gui/Job.py index aec6fe875f..faa6b1c2e9 100644 --- a/src/Mod/Path/Path/Main/Gui/Job.py +++ b/src/Mod/Path/Path/Main/Gui/Job.py @@ -621,25 +621,29 @@ class TaskPanel: vUnit = FreeCAD.Units.Quantity(1, FreeCAD.Units.Velocity).getUserPreferred()[2] self.form.toolControllerList.horizontalHeaderItem(1).setText("#") self.form.toolControllerList.horizontalHeaderItem(2).setText( - translate("Path", "H","H is horizontal feed rate. Must be as short as possible") + translate( + "Path", "H", "H is horizontal feed rate. Must be as short as possible" + ) ) self.form.toolControllerList.horizontalHeaderItem(3).setText( - translate("Path", "V","V is vertical feed rate. Must be as short as possible") + translate( + "Path", "V", "V is vertical feed rate. Must be as short as possible" + ) ) self.form.toolControllerList.horizontalHeader().setResizeMode( 0, QtGui.QHeaderView.Stretch ) self.form.toolControllerList.horizontalHeaderItem(1).setToolTip( - translate("Path", "Tool number") + ' ' + translate("Path", "Tool number") + " " ) self.form.toolControllerList.horizontalHeaderItem(2).setToolTip( - translate("Path", "Horizontal feedrate")+ ' ' + vUnit + translate("Path", "Horizontal feedrate") + " " + vUnit ) self.form.toolControllerList.horizontalHeaderItem(3).setToolTip( - translate("Path", "Vertical feedrate")+ ' ' + vUnit + translate("Path", "Vertical feedrate") + " " + vUnit ) self.form.toolControllerList.horizontalHeaderItem(4).setToolTip( - translate("Path", "Spindle RPM")+ ' ' + translate("Path", "Spindle RPM") + " " ) # ensure correct ellisis behaviour on tool controller names. @@ -804,11 +808,31 @@ class TaskPanel: self.setupOps.getFields() def selectComboBoxText(self, widget, text): - index = widget.findText(text, QtCore.Qt.MatchFixedString) - if index >= 0: + """selectInComboBox(name, combo) ... + helper function to select a specific value in a combo box.""" + index = widget.currentIndex() # Save initial index + + # Search using currentData and return if found + newindex = widget.findData(text) + if newindex >= 0: + widget.blockSignals(True) - widget.setCurrentIndex(index) + widget.setCurrentIndex(newindex) widget.blockSignals(False) + return + + # if not found, search using current text + newindex = widget.findText(text, QtCore.Qt.MatchFixedString) + if newindex >= 0: + widget.blockSignals(True) + widget.setCurrentIndex(newindex) + widget.blockSignals(False) + return + + widget.blockSignals(True) + widget.setCurrentIndex(index) + widget.blockSignals(False) + return def updateToolController(self): tcRow = self.form.toolControllerList.currentRow() @@ -900,10 +924,9 @@ class TaskPanel: self.form.operationsList.addItem(item) self.form.jobModel.clear() - for name, count in Counter([ - self.obj.Proxy.baseObject(self.obj, o).Label - for o in self.obj.Model.Group - ]).items(): + for name, count in Counter( + [self.obj.Proxy.baseObject(self.obj, o).Label for o in self.obj.Model.Group] + ).items(): if count == 1: self.form.jobModel.addItem(name) else: From 56d4214317b3b56aed9e79e6dacac3538dc66774 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Fri, 19 Jan 2024 17:54:16 -0300 Subject: [PATCH 27/34] Fem: Improve self weight constraint - fixes #11652 --- .../constraint_selfweight_cantilever.py | 2 +- .../Fem/femobjects/constraint_selfweight.py | 69 ++++++++++++------- .../calculix/write_constraint_selfweight.py | 8 +-- .../elmer/equations/deformation_writer.py | 8 +-- .../elmer/equations/elasticity_writer.py | 8 +-- .../constraint_selfweight_cantilever.inp | 2 +- 6 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/Mod/Fem/femexamples/constraint_selfweight_cantilever.py b/src/Mod/Fem/femexamples/constraint_selfweight_cantilever.py index ee6e3c572a..6473c0b959 100644 --- a/src/Mod/Fem/femexamples/constraint_selfweight_cantilever.py +++ b/src/Mod/Fem/femexamples/constraint_selfweight_cantilever.py @@ -124,7 +124,7 @@ def setup(doc=None, solvertype="ccxtools"): # constraint selfweight con_selfweight = ObjectsFem.makeConstraintSelfWeight(doc, "ConstraintSelfWeight") - con_selfweight.Gravity_z = -1.00 + con_selfweight.GravityDirection = (0, 0, -1) analysis.addObject(con_selfweight) # mesh diff --git a/src/Mod/Fem/femobjects/constraint_selfweight.py b/src/Mod/Fem/femobjects/constraint_selfweight.py index 843457bd38..6972ad2d9d 100644 --- a/src/Mod/Fem/femobjects/constraint_selfweight.py +++ b/src/Mod/Fem/femobjects/constraint_selfweight.py @@ -29,7 +29,9 @@ __url__ = "https://www.freecad.org" # \ingroup FEM # \brief constraint self weight object +import FreeCAD from . import base_fempythonobject +from femtools import constants class ConstraintSelfWeight(base_fempythonobject.BaseFemPythonObject): @@ -42,33 +44,52 @@ class ConstraintSelfWeight(base_fempythonobject.BaseFemPythonObject): def __init__(self, obj): super(ConstraintSelfWeight, self).__init__(obj) - obj.addProperty( - "App::PropertyFloat", - "Gravity_x", - "Gravity", - "Gravity direction: set the x-component of the normalized gravity vector" - ) - - obj.addProperty( - "App::PropertyFloat", - "Gravity_y", - "Gravity", - "Gravity direction: set the y-component of the normalized gravity vector" - ) - - obj.addProperty( - "App::PropertyFloat", - "Gravity_z", - "Gravity", - "Gravity direction: set the z-component of the normalized gravity vector" - ) - - obj.Gravity_x = 0.0 - obj.Gravity_y = 0.0 - obj.Gravity_z = -1.0 + self.addProperty(obj) # https://wiki.freecad.org/Scripted_objects#Property_Type # https://forum.freecad.org/viewtopic.php?f=18&t=13460&start=20#p109709 # https://forum.freecad.org/viewtopic.php?t=25524 # obj.setEditorMode("References", 1) # read only in PropertyEditor, but writeable by Python obj.setEditorMode("References", 2) # do not show in Editor + + def addProperty(self, obj): + obj.addProperty("App::PropertyAcceleration", + "GravityAcceleration", + "Gravity", + "Gravity acceleration") + obj.GravityAcceleration = constants.gravity() + + obj.addProperty("App::PropertyVector", + "GravityDirection", + "Gravity", + "Normalized gravity direction") + obj.GravityDirection = FreeCAD.Vector(0, 0, -1) + + obj.setPropertyStatus("NormalDirection", "Hidden") + + def onDocumentRestored(self, obj): + # migrate old App::PropertyFloat "Gravity_*" if exists + try: + grav_x = obj.getPropertyByName("Gravity_x") + grav_y = obj.getPropertyByName("Gravity_y") + grav_z = obj.getPropertyByName("Gravity_z") + grav = FreeCAD.Vector(grav_x, grav_y, grav_z) + + self.addProperty(obj) + obj.GravityAcceleration = constants.gravity() + obj.GravityAcceleration *= grav.Length + obj.GravityDirection = grav.normalize() + + obj.removeProperty("Gravity_x") + obj.removeProperty("Gravity_y") + obj.removeProperty("Gravity_z") + + return + + except: + return + + def execute(self, obj): + obj.GravityDirection.normalize() + + return False diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_selfweight.py b/src/Mod/Fem/femsolver/calculix/write_constraint_selfweight.py index a4eeeb495a..ee366df41c 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_selfweight.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_selfweight.py @@ -52,10 +52,10 @@ def write_constraint(f, femobj, selwei_obj, ccxwriter): "{},GRAV,{:.13G},{:.13G},{:.13G},{:.13G}\n" .format( ccxwriter.ccx_eall, - ccxwriter.gravity, # actual magnitude of gravity vector - selwei_obj.Gravity_x, # coordinate x of normalized gravity vector - selwei_obj.Gravity_y, # y - selwei_obj.Gravity_z # z + selwei_obj.GravityAcceleration.getValueAs("mm/s^2").Value, # actual magnitude of gravity vector + selwei_obj.GravityDirection.x, # coordinate x of normalized gravity vector + selwei_obj.GravityDirection.y, # y + selwei_obj.GravityDirection.z # z ) ) f.write("\n") diff --git a/src/Mod/Fem/femsolver/elmer/equations/deformation_writer.py b/src/Mod/Fem/femsolver/elmer/equations/deformation_writer.py index 080976218d..f76dd39fe0 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/deformation_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/deformation_writer.py @@ -148,7 +148,7 @@ class DeformationWriter: obj = self.write.getSingleMember("Fem::ConstraintSelfWeight") if obj is not None: for name in bodies: - gravity = self.write.convert(self.write.constsdef["Gravity"], "L/T^2") + gravity = self.write.convert(obj.GravityAcceleration.toStr(), "L/T^2") if self.write.getBodyMaterial(name) is None: raise general_writer.WriteError( "The body {} is not referenced in any material.\n\n".format(name) @@ -164,9 +164,9 @@ class DeformationWriter: dimension = "M/L^2" density = self.write.convert(densityQuantity, dimension) - force1 = gravity * obj.Gravity_x * density - force2 = gravity * obj.Gravity_y * density - force3 = gravity * obj.Gravity_z * density + force1 = gravity * obj.GravityDirection.x * density + force2 = gravity * obj.GravityDirection.y * density + force3 = gravity * obj.GravityDirection.z * density self.write.bodyForce(name, "Stress Bodyforce 1", force1) self.write.bodyForce(name, "Stress Bodyforce 2", force2) self.write.bodyForce(name, "Stress Bodyforce 3", force3) diff --git a/src/Mod/Fem/femsolver/elmer/equations/elasticity_writer.py b/src/Mod/Fem/femsolver/elmer/equations/elasticity_writer.py index bc71a67368..4424e903e7 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/elasticity_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/elasticity_writer.py @@ -364,7 +364,7 @@ class ElasticityWriter: obj = self.write.getSingleMember("Fem::ConstraintSelfWeight") if obj is not None: for name in bodies: - gravity = self.write.convert(self.write.constsdef["Gravity"], "L/T^2") + gravity = self.write.convert(obj.GravityAcceleration.toStr(), "L/T^2") if self.write.getBodyMaterial(name) is None: raise general_writer.WriteError( "The body {} is not referenced in any material.\n\n".format(name) @@ -380,9 +380,9 @@ class ElasticityWriter: dimension = "M/L^2" density = self.write.convert(densityQuantity, dimension) - force1 = gravity * obj.Gravity_x * density - force2 = gravity * obj.Gravity_y * density - force3 = gravity * obj.Gravity_z * density + force1 = gravity * obj.GravityDirection.x * density + force2 = gravity * obj.GravityDirection.y * density + force3 = gravity * obj.GravityDirection.z * density self.write.bodyForce(name, "Stress Bodyforce 1", force1) self.write.bodyForce(name, "Stress Bodyforce 2", force2) self.write.bodyForce(name, "Stress Bodyforce 3", force3) diff --git a/src/Mod/Fem/femtest/data/calculix/constraint_selfweight_cantilever.inp b/src/Mod/Fem/femtest/data/calculix/constraint_selfweight_cantilever.inp index 4fda9cf903..1721a498ea 100644 --- a/src/Mod/Fem/femtest/data/calculix/constraint_selfweight_cantilever.inp +++ b/src/Mod/Fem/femtest/data/calculix/constraint_selfweight_cantilever.inp @@ -2170,7 +2170,7 @@ ConstraintFixed,3 ** Self weight Constraint ** ConstraintSelfWeight *DLOAD -Eall,GRAV,9806,0,0,-1 +Eall,GRAV,9806.65,0,0,-1 *********************************************************** From d1297ebf851b344d3dab3883410836480e64a36d Mon Sep 17 00:00:00 2001 From: wandererfan Date: Fri, 19 Jan 2024 13:22:57 -0500 Subject: [PATCH 28/34] [TD]handle equal section line end points --- src/Mod/TechDraw/Gui/QGIViewPart.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index 5c32b1f9dd..50e1b88110 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -652,6 +652,16 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b } if (b) { + //find the ends of the section line + double scale = viewPart->getScale(); + std::pair sLineEnds = viewSection->sectionLineEnds(); + Base::Vector3d l1 = Rez::guiX(sLineEnds.first) * scale; + Base::Vector3d l2 = Rez::guiX(sLineEnds.second) * scale; + if (l1.IsEqual(l2, EWTOLERANCE) ) { + Base::Console().Message("QGIVP::drawSectionLine - line endpoints are equal. No section line created.\n"); + return; + } + QGISectionLine* sectionLine = new QGISectionLine(); addToGroup(sectionLine); sectionLine->setSymbol(const_cast(viewSection->SectionSymbol.getValue())); @@ -660,11 +670,6 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b sectionLine->setSectionColor(color.asValue()); sectionLine->setPathMode(false); - //find the ends of the section line - double scale = viewPart->getScale(); - std::pair sLineEnds = viewSection->sectionLineEnds(); - Base::Vector3d l1 = Rez::guiX(sLineEnds.first) * scale; - Base::Vector3d l2 = Rez::guiX(sLineEnds.second) * scale; //make the section line a little longer double fudge = 2.0 * Preferences::dimFontSizeMM(); Base::Vector3d lineDir = l2 - l1; @@ -722,6 +727,15 @@ void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, } auto dcs = static_cast(viewSection); + std::pair ends = dcs->sectionLineEnds(); + Base::Vector3d vStart = Rez::guiX(ends.first);//already scaled by dcs + Base::Vector3d vEnd = Rez::guiX(ends.second); + if (vStart.IsEqual(vEnd, EWTOLERANCE) ) { + Base::Console().Message("QGIVP::drawComplexSectionLine - line endpoints are equal. No section line created.\n"); + return; + } + + BaseGeomPtrVector edges = dcs->makeSectionLineGeometry(); QPainterPath wirePath; QPainterPath firstSeg = drawPainterPath(edges.front()); @@ -736,9 +750,6 @@ void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, wirePath.connectPath(edgePath); } - std::pair ends = dcs->sectionLineEnds(); - Base::Vector3d vStart = Rez::guiX(ends.first);//already scaled by dcs - Base::Vector3d vEnd = Rez::guiX(ends.second); QGISectionLine* sectionLine = new QGISectionLine(); addToGroup(sectionLine); From a4c55b9ec8ca0e8c22aca8339c959aa18dc169f3 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Fri, 19 Jan 2024 19:32:29 -0500 Subject: [PATCH 29/34] [TD]protect against stretch factor == 0 --- src/Mod/TechDraw/App/DrawViewSection.cpp | 8 ++++++++ src/Mod/TechDraw/App/DrawViewSection.h | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 3d527715ae..01ab923556 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -125,6 +125,13 @@ const char* DrawViewSection::SectionDirEnums[] = const char* DrawViewSection::CutSurfaceEnums[] = {"Hide", "Color", "SvgHatch", "PatHatch", nullptr}; +constexpr double stretchMinimum{EWTOLERANCE}; +constexpr double stretchMaximum{std::numeric_limits::max()}; +constexpr double stretchStep{0.1}; + +App::PropertyFloatConstraint::Constraints DrawViewSection::stretchRange = { + stretchMinimum, stretchMaximum, stretchStep}; + //=========================================================================== // DrawViewSection //=========================================================================== @@ -230,6 +237,7 @@ DrawViewSection::DrawViewSection() ADD_PROPERTY_TYPE(SectionLineStretch, (1.0), agroup, App::Prop_None, "Adjusts the length of the section line. 1.0 is normal length. 1.1 would be 10% longer, 0.9 would be 10% shorter."); + SectionLineStretch.setConstraints(&stretchRange); getParameters(); diff --git a/src/Mod/TechDraw/App/DrawViewSection.h b/src/Mod/TechDraw/App/DrawViewSection.h index 09eb87cfd7..ed311fe27b 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.h +++ b/src/Mod/TechDraw/App/DrawViewSection.h @@ -104,7 +104,7 @@ public: App::PropertyBool TrimAfterCut;//new v021 App::PropertyBool UsePreviousCut; // new v022 - App::PropertyFloat SectionLineStretch; // new v022 + App::PropertyFloatConstraint SectionLineStretch; // new v022 bool isReallyInBox(const Base::Vector3d v, const Base::BoundBox3d bb) const; @@ -205,6 +205,9 @@ protected: bool m_waitingForCut; TopoDS_Shape m_cuttingTool; double m_shapeSize; + + static App::PropertyFloatConstraint::Constraints stretchRange; + }; using DrawViewSectionPython = App::FeaturePythonT; From 04bc6f80063bbb5a964b61a3fd76f63c5ee4a783 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Fri, 5 Jan 2024 20:54:31 +0530 Subject: [PATCH 30/34] [Sketcher] Visualize B-spline in edit mode Instead of the control polygon, or "join the dots" for interpolated splines. --- .../Sketcher/Gui/DrawSketchHandlerBSpline.h | 43 +++++++++++++++++-- .../DrawSketchHandlerBSplineByInterpolation.h | 25 +++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h index 080ffac50b..2cae185c6e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h @@ -90,7 +90,7 @@ public: } else if (Mode == STATUS_SEEK_ADDITIONAL_CONTROLPOINTS) { - drawControlPolygonToPosition(onSketchPos); + drawBSplineToPosition(onSketchPos); drawCursorToPosition(onSketchPos); @@ -313,7 +313,7 @@ public: // run this in the end to draw lines and position text - drawControlPolygonToPosition(prevCursorPosition); + drawBSplineToPosition(prevCursorPosition); drawCursorToPosition(prevCursorPosition); } catch (const Base::Exception&) { @@ -414,13 +414,50 @@ private: void drawControlPolygonToPosition(Base::Vector2d position) { - std::vector editcurve(BSplinePoles); editcurve.push_back(position); drawEdit(editcurve); } + void drawBSplineToPosition(Base::Vector2d position) + { + std::vector editcurve; + for (auto& pole : BSplinePoles) { + editcurve.emplace_back(pole.x, pole.y, 0.0); + } + editcurve.emplace_back(position.x, position.y, 0.0); + size_t degree = std::min(editcurve.size() - 1, static_cast(SplineDegree)); + bool periodic = (ConstrMethod != 0); + + std::vector weights(editcurve.size(), 1.0); + std::vector knots; + std::vector mults; + if (!periodic) { + for (size_t i = 0; i < editcurve.size() - degree + 1; ++i) { + knots.push_back(i); + } + mults.resize(editcurve.size() - degree + 1, 1); + mults.front() = degree + 1; + mults.back() = degree + 1; + } + else { + for (size_t i = 0; i < editcurve.size() + 1; ++i) { + knots.push_back(i); + } + mults.resize(editcurve.size() + 1, 1); + } + + // TODO: This maybe optimized by storing the spline as an attribute. + Part::GeomBSplineCurve editBSpline(editcurve, weights, knots, mults, degree, periodic); + editBSpline.setPoles(editcurve); + + std::vector editBSplines; + editBSplines.push_back(&editBSpline); + + drawEdit(editBSplines); + } + void drawCursorToPosition(Base::Vector2d position) { if (!BSplinePoles.empty()) { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h index 593c5f9cf9..3880a0c741 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h @@ -90,7 +90,7 @@ public: } else if (Mode == STATUS_SEEK_ADDITIONAL_POINTS) { - drawControlPolygonToPosition(onSketchPos); + drawBSplineToPosition(onSketchPos); drawCursorToPosition(onSketchPos); @@ -311,7 +311,7 @@ public: // run this in the end to draw lines and position text - drawControlPolygonToPosition(prevCursorPosition); + drawBSplineToPosition(prevCursorPosition); drawCursorToPosition(prevCursorPosition); } catch (const Base::Exception&) { @@ -409,13 +409,32 @@ private: // NOTE: In this context, it is not a control polygon, but a 1-degree interpolation void drawControlPolygonToPosition(Base::Vector2d position) { - std::vector editcurve(BSplineKnots); editcurve.push_back(position); drawEdit(editcurve); } + void drawBSplineToPosition(Base::Vector2d position) + { + std::vector editcurve(BSplineKnots); + editcurve.push_back(position); + + std::vector editCurveForOCCT; + for (auto& p : editcurve) { + editCurveForOCCT.emplace_back(p.x, p.y, 0.0); + } + + // TODO: This maybe optimized by storing the spline as an attribute. + Part::GeomBSplineCurve editBSpline; + editBSpline.interpolate(editCurveForOCCT, ConstrMethod != 0); + + std::vector editBSplines; + editBSplines.push_back(&editBSpline); + + drawEdit(editBSplines); + } + void drawCursorToPosition(Base::Vector2d position) { if (!BSplineKnots.empty()) { From 336bf03ada63347ec850862ecfbbece1cc7b0e57 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sat, 20 Jan 2024 12:03:46 -0300 Subject: [PATCH 31/34] Fem: Call base class handleChangedProperyType function --- src/Mod/Fem/App/FemConstraintDisplacement.cpp | 3 +++ src/Mod/Fem/App/FemConstraintForce.cpp | 3 +++ src/Mod/Fem/App/FemConstraintInitialTemperature.cpp | 3 +++ src/Mod/Fem/App/FemConstraintPressure.cpp | 3 +++ src/Mod/Fem/App/FemConstraintTemperature.cpp | 3 +++ src/Mod/Fem/App/FemConstraintTransform.cpp | 3 +++ src/Mod/Fem/App/FemPostFilter.cpp | 3 +++ 7 files changed, 21 insertions(+) diff --git a/src/Mod/Fem/App/FemConstraintDisplacement.cpp b/src/Mod/Fem/App/FemConstraintDisplacement.cpp index 4fcb5f4f01..4ef6497c70 100644 --- a/src/Mod/Fem/App/FemConstraintDisplacement.cpp +++ b/src/Mod/Fem/App/FemConstraintDisplacement.cpp @@ -141,6 +141,9 @@ void ConstraintDisplacement::handleChangedPropertyType(Base::XMLReader& reader, zRotationProperty.Restore(reader); zRotation.setValue(zRotationProperty.getValue()); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintDisplacement::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemConstraintForce.cpp b/src/Mod/Fem/App/FemConstraintForce.cpp index 1a54f680aa..79b9d8c746 100644 --- a/src/Mod/Fem/App/FemConstraintForce.cpp +++ b/src/Mod/Fem/App/FemConstraintForce.cpp @@ -80,6 +80,9 @@ void ConstraintForce::handleChangedPropertyType(Base::XMLReader& reader, // e.g. "2.5" must become 2500 to result in 2.5 N Force.setValue(ForceProperty.getValue() * 1000); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintForce::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemConstraintInitialTemperature.cpp b/src/Mod/Fem/App/FemConstraintInitialTemperature.cpp index 32b3203c10..cb2af6aa78 100644 --- a/src/Mod/Fem/App/FemConstraintInitialTemperature.cpp +++ b/src/Mod/Fem/App/FemConstraintInitialTemperature.cpp @@ -74,6 +74,9 @@ void ConstraintInitialTemperature::handleChangedPropertyType(Base::XMLReader& re initialTemperatureProperty.Restore(reader); initialTemperature.setValue(initialTemperatureProperty.getValue()); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintInitialTemperature::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemConstraintPressure.cpp b/src/Mod/Fem/App/FemConstraintPressure.cpp index e6a06c4efb..911d555056 100644 --- a/src/Mod/Fem/App/FemConstraintPressure.cpp +++ b/src/Mod/Fem/App/FemConstraintPressure.cpp @@ -71,6 +71,9 @@ void ConstraintPressure::handleChangedPropertyType(Base::XMLReader& reader, // therefore we must convert the value with a factor 1000 Pressure.setValue(PressureProperty.getValue() * 1000.0); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintPressure::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemConstraintTemperature.cpp b/src/Mod/Fem/App/FemConstraintTemperature.cpp index dc4037482f..6c906333c8 100644 --- a/src/Mod/Fem/App/FemConstraintTemperature.cpp +++ b/src/Mod/Fem/App/FemConstraintTemperature.cpp @@ -86,6 +86,9 @@ void ConstraintTemperature::handleChangedPropertyType(Base::XMLReader& reader, CFluxProperty.Restore(reader); CFlux.setValue(CFluxProperty.getValue()); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintTemperature::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemConstraintTransform.cpp b/src/Mod/Fem/App/FemConstraintTransform.cpp index 6ee538c62f..53947104b2 100644 --- a/src/Mod/Fem/App/FemConstraintTransform.cpp +++ b/src/Mod/Fem/App/FemConstraintTransform.cpp @@ -110,6 +110,9 @@ void ConstraintTransform::handleChangedPropertyType(Base::XMLReader& reader, Z_rotProperty.Restore(reader); Z_rot.setValue(Z_rotProperty.getValue()); } + else { + Constraint::handleChangedPropertyType(reader, TypeName, prop); + } } void ConstraintTransform::onChanged(const App::Property* prop) diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index 3b5c600680..1e3a1ca27c 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -217,6 +217,9 @@ void FemPostDataAlongLineFilter::handleChangedPropertyType(Base::XMLReader& read Point2Property.Restore(reader); Point2.setValue(Point2Property.getValue()); } + else { + FemPostFilter::handleChangedPropertyType(reader, TypeName, prop); + } } void FemPostDataAlongLineFilter::onChanged(const Property* prop) From f178206a2fcd55fdae70cf2a09b6c31b50251ec8 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sat, 20 Jan 2024 12:00:23 -0500 Subject: [PATCH 32/34] [TD]handle View rotation in ExtensionPack circle centerlines --- src/Mod/TechDraw/Gui/CommandExtensionPack.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp index 8da7f5120c..c3008c25c2 100644 --- a/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp +++ b/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp @@ -194,7 +194,6 @@ void execCircleCenterLines(Gui::Command* cmd) if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Circle Centerlines"))) return; Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Circle Centerlines")); - double scale = objFeat->getScale(); const std::vector SubNames = selection[0].getSubNames(); for (const std::string& Name : SubNames) { int GeoId = TechDraw::DrawUtil::getIndexFromName(Name); @@ -203,15 +202,19 @@ void execCircleCenterLines(Gui::Command* cmd) if (GeoType == "Edge") { if (geom->getGeomType() == TechDraw::CIRCLE || geom->getGeomType() == TechDraw::ARCOFCIRCLE) { TechDraw::CirclePtr cgen = std::static_pointer_cast(geom); + // center is a scaled and rotated point Base::Vector3d center = cgen->center; center.y = -center.y; - float radius = cgen->radius; + center = CosmeticVertex::makeCanonicalPoint(objFeat, center); + double radius = cgen->radius / objFeat->getScale(); + // right, left, top, bottom are formed from a canonical point (center) + // so they do not need to be changed to canonical form. Base::Vector3d right(center.x + radius + 2.0, center.y, 0.0); Base::Vector3d top(center.x, center.y + radius + 2.0, 0.0); Base::Vector3d left(center.x - radius - 2.0, center.y, 0.0); Base::Vector3d bottom(center.x, center.y - radius - 2.0, 0.0); - std::string line1tag = objFeat->addCosmeticEdge(right / scale, left / scale); - std::string line2tag = objFeat->addCosmeticEdge(top / scale, bottom / scale); + std::string line1tag = objFeat->addCosmeticEdge(right, left); + std::string line2tag = objFeat->addCosmeticEdge(top, bottom); TechDraw::CosmeticEdge* horiz = objFeat->getCosmeticEdge(line1tag); _setLineAttributes(horiz); TechDraw::CosmeticEdge* vert = objFeat->getCosmeticEdge(line2tag); From de4639371149791a71bccd3516b74e866de42ec5 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 20 Jan 2024 20:06:12 -0600 Subject: [PATCH 33/34] Materials: Correct PreCompiled.h includes in App --- src/Mod/Material/App/MaterialConfigLoader.cpp | 9 ++++----- src/Mod/Material/App/MaterialLibrary.cpp | 4 ++-- src/Mod/Material/App/Materials.cpp | 4 ++-- src/Mod/Material/App/Model.cpp | 3 +-- src/Mod/Material/App/ModelLibrary.cpp | 3 +-- src/Mod/Material/App/ModelLoader.cpp | 4 ++-- src/Mod/Material/App/PreCompiled.h | 12 ++++++++++++ 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Mod/Material/App/MaterialConfigLoader.cpp b/src/Mod/Material/App/MaterialConfigLoader.cpp index fe2090f009..b16b14daa8 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.cpp +++ b/src/Mod/Material/App/MaterialConfigLoader.cpp @@ -24,18 +24,17 @@ #include #include #include -#endif - -#include - #include #include #include #include +#include +#include +#endif + #include #include -#include #include "Exceptions.h" diff --git a/src/Mod/Material/App/MaterialLibrary.cpp b/src/Mod/Material/App/MaterialLibrary.cpp index d1c30730f8..1a1573e388 100644 --- a/src/Mod/Material/App/MaterialLibrary.cpp +++ b/src/Mod/Material/App/MaterialLibrary.cpp @@ -22,10 +22,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include -#endif - #include #include +#endif + #include diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index a1d7592125..106bf43bdf 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -21,10 +21,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif - #include #include +#endif + #include #include diff --git a/src/Mod/Material/App/Model.cpp b/src/Mod/Material/App/Model.cpp index 2d30bdadc3..19a4ebb832 100644 --- a/src/Mod/Material/App/Model.cpp +++ b/src/Mod/Material/App/Model.cpp @@ -21,9 +21,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif - #include +#endif #include diff --git a/src/Mod/Material/App/ModelLibrary.cpp b/src/Mod/Material/App/ModelLibrary.cpp index 63d06f2d06..87a4387263 100644 --- a/src/Mod/Material/App/ModelLibrary.cpp +++ b/src/Mod/Material/App/ModelLibrary.cpp @@ -21,9 +21,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif - #include +#endif #include diff --git a/src/Mod/Material/App/ModelLoader.cpp b/src/Mod/Material/App/ModelLoader.cpp index 3976f2a28c..a24bea113a 100644 --- a/src/Mod/Material/App/ModelLoader.cpp +++ b/src/Mod/Material/App/ModelLoader.cpp @@ -22,13 +22,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include +#include #endif #include #include -#include -#include #include "Model.h" #include "ModelLoader.h" diff --git a/src/Mod/Material/App/PreCompiled.h b/src/Mod/Material/App/PreCompiled.h index c2ca3cd36e..e991f90cda 100644 --- a/src/Mod/Material/App/PreCompiled.h +++ b/src/Mod/Material/App/PreCompiled.h @@ -47,14 +47,26 @@ // STL #include +#include #include +#include #include #include #include // Qt #include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #endif //_PreComp_ From e11a65813cf15d68ee7324fcc9de52f8c7ccfb67 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Sat, 20 Jan 2024 20:21:34 -0600 Subject: [PATCH 34/34] Materials: Correct PreCompiled.h includes in Gui --- src/Mod/Material/Gui/Array2D.cpp | 3 +-- src/Mod/Material/Gui/Array3D.cpp | 3 +-- src/Mod/Material/Gui/ArrayDelegate.cpp | 3 +-- src/Mod/Material/Gui/ArrayModel.cpp | 3 +-- src/Mod/Material/Gui/BaseDelegate.cpp | 3 +-- src/Mod/Material/Gui/ImageEdit.cpp | 5 ++--- src/Mod/Material/Gui/ListDelegate.cpp | 3 +-- src/Mod/Material/Gui/ListEdit.cpp | 3 +-- src/Mod/Material/Gui/ListModel.cpp | 3 +-- src/Mod/Material/Gui/MaterialDelegate.cpp | 3 +-- src/Mod/Material/Gui/MaterialsEditor.cpp | 3 +-- src/Mod/Material/Gui/PreCompiled.h | 1 + src/Mod/Material/Gui/TextEdit.cpp | 3 +-- 13 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/Mod/Material/Gui/Array2D.cpp b/src/Mod/Material/Gui/Array2D.cpp index 359160ac13..234c608dfc 100644 --- a/src/Mod/Material/Gui/Array2D.cpp +++ b/src/Mod/Material/Gui/Array2D.cpp @@ -21,11 +21,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif -#include - #include #include diff --git a/src/Mod/Material/Gui/Array3D.cpp b/src/Mod/Material/Gui/Array3D.cpp index 37677a5f62..16cebf5931 100644 --- a/src/Mod/Material/Gui/Array3D.cpp +++ b/src/Mod/Material/Gui/Array3D.cpp @@ -21,12 +21,11 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif -#include - #include #include diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 4ad6bffe93..fa06605f19 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -30,9 +30,8 @@ #include #include #include -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/ArrayModel.cpp b/src/Mod/Material/Gui/ArrayModel.cpp index c7f581316e..5d1dbdd57d 100644 --- a/src/Mod/Material/Gui/ArrayModel.cpp +++ b/src/Mod/Material/Gui/ArrayModel.cpp @@ -21,10 +21,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif - #include #include +#endif #include #include diff --git a/src/Mod/Material/Gui/BaseDelegate.cpp b/src/Mod/Material/Gui/BaseDelegate.cpp index d018a80e68..3f75d52fb8 100644 --- a/src/Mod/Material/Gui/BaseDelegate.cpp +++ b/src/Mod/Material/Gui/BaseDelegate.cpp @@ -31,9 +31,8 @@ #include #include #include -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/ImageEdit.cpp b/src/Mod/Material/Gui/ImageEdit.cpp index 7ed319554c..b0c21b1258 100644 --- a/src/Mod/Material/Gui/ImageEdit.cpp +++ b/src/Mod/Material/Gui/ImageEdit.cpp @@ -21,17 +21,16 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include -#endif - #include #include #include +#include #include #include #include #include #include +#endif #include #include diff --git a/src/Mod/Material/Gui/ListDelegate.cpp b/src/Mod/Material/Gui/ListDelegate.cpp index 1932cb396f..52f0ca6d2c 100644 --- a/src/Mod/Material/Gui/ListDelegate.cpp +++ b/src/Mod/Material/Gui/ListDelegate.cpp @@ -30,9 +30,8 @@ #include #include #include -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/ListEdit.cpp b/src/Mod/Material/Gui/ListEdit.cpp index cc1a59bad8..b8df1722a7 100644 --- a/src/Mod/Material/Gui/ListEdit.cpp +++ b/src/Mod/Material/Gui/ListEdit.cpp @@ -21,11 +21,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif -#include - #include #include diff --git a/src/Mod/Material/Gui/ListModel.cpp b/src/Mod/Material/Gui/ListModel.cpp index edf56e2b68..e89a6dcadc 100644 --- a/src/Mod/Material/Gui/ListModel.cpp +++ b/src/Mod/Material/Gui/ListModel.cpp @@ -21,9 +21,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/MaterialDelegate.cpp b/src/Mod/Material/Gui/MaterialDelegate.cpp index 38e67cc5e1..d3787e6d46 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.cpp +++ b/src/Mod/Material/Gui/MaterialDelegate.cpp @@ -31,9 +31,8 @@ #include #include #include -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/MaterialsEditor.cpp b/src/Mod/Material/Gui/MaterialsEditor.cpp index 3c23ec20f8..d2c3cc2508 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.cpp +++ b/src/Mod/Material/Gui/MaterialsEditor.cpp @@ -31,9 +31,8 @@ #include #include #include -#endif - #include +#endif #include #include diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 36cb312a6f..9d0d6c1884 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -44,6 +44,7 @@ // standard #include #include +#include // STL #include diff --git a/src/Mod/Material/Gui/TextEdit.cpp b/src/Mod/Material/Gui/TextEdit.cpp index 93f46b77c3..95c1558855 100644 --- a/src/Mod/Material/Gui/TextEdit.cpp +++ b/src/Mod/Material/Gui/TextEdit.cpp @@ -21,11 +21,10 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #endif -#include - #include #include