diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b2e2b4e758..eede2a8aa7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,7 @@ files: | src/Mod/BIM| src/Mod/CAM| src/Mod/Cloud| + src/Mod/Draft| src/Mod/Fem| src/Mod/Help| src/Mod/Import| diff --git a/src/Mod/Draft/App/AppDraftUtils.cpp b/src/Mod/Draft/App/AppDraftUtils.cpp index a6742cd5fd..a56f6a42c1 100644 --- a/src/Mod/Draft/App/AppDraftUtils.cpp +++ b/src/Mod/Draft/App/AppDraftUtils.cpp @@ -26,7 +26,8 @@ #include -namespace DraftUtils { +namespace DraftUtils +{ extern PyObject* initModule(); } @@ -37,7 +38,7 @@ PyMOD_INIT_FUNC(DraftUtils) try { Base::Interpreter().loadModule("Part"); } - catch(const Base::Exception& e) { + catch (const Base::Exception& e) { PyErr_SetString(PyExc_ImportError, e.what()); PyMOD_Return(nullptr); } diff --git a/src/Mod/Draft/App/AppDraftUtilsPy.cpp b/src/Mod/Draft/App/AppDraftUtilsPy.cpp index a0ab38b580..831b7841c8 100644 --- a/src/Mod/Draft/App/AppDraftUtilsPy.cpp +++ b/src/Mod/Draft/App/AppDraftUtilsPy.cpp @@ -25,20 +25,25 @@ #include -namespace DraftUtils { -class Module : public Py::ExtensionModule +namespace DraftUtils +{ +class Module: public Py::ExtensionModule { public: - Module() : Py::ExtensionModule("DraftUtils") + Module() + : Py::ExtensionModule("DraftUtils") { - add_varargs_method("readDXF",&Module::readDXF, - "readDXF(filename,[document,ignore_errors]): " - "Imports a DXF file into the given document. " - "ignore_errors is True by default. " - "NOTE: DraftUtils.readDXF is removed. " - "Use Import.readDxf instead." - ); - initialize("The DraftUtils module contains utility functions for the Draft module."); // register with Python + add_varargs_method("readDXF", + &Module::readDXF, + "readDXF(filename,[document,ignore_errors]): " + "Imports a DXF file into the given document. " + "ignore_errors is True by default. " + "NOTE: DraftUtils.readDXF is removed. " + "Use Import.readDxf instead."); + initialize( + "The DraftUtils module contains utility functions for the Draft module."); // register + // with + // Python } private: @@ -55,4 +60,4 @@ PyObject* initModule() return Base::Interpreter().addModule(new Module); } -} // namespace DraftUtils +} // namespace DraftUtils diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 558dcfd68e..f32d14773b 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -35,6 +35,7 @@ import FreeCAD as App if App.GuiUp: import Draft_rc + gui = True # To prevent complaints from code checkers (flake8) True if Draft_rc.__name__ else False @@ -42,8 +43,9 @@ else: gui = False __title__ = "FreeCAD Draft Workbench" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Daniel Falck") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Daniel Falck" +) __url__ = "https://www.freecad.org" # --------------------------------------------------------------------------- @@ -51,80 +53,80 @@ __url__ = "https://www.freecad.org" # --------------------------------------------------------------------------- from draftutils.utils import ARROW_TYPES as arrowtypes -from draftutils.utils import (type_check, - typecheck, - precision, - tolerance) +from draftutils.utils import type_check, typecheck, precision, tolerance -from draftutils.utils import (get_real_name, - getRealName, - get_type, - getType, - get_objects_of_type, - getObjectsOfType, - is_clone, - isClone, - get_clone_base, - getCloneBase, - print_shape, - printShape, - compare_objects, - compareObjects, - shapify, - is_closed_edge) +from draftutils.utils import ( + get_real_name, + getRealName, + get_type, + getType, + get_objects_of_type, + getObjectsOfType, + is_clone, + isClone, + get_clone_base, + getCloneBase, + print_shape, + printShape, + compare_objects, + compareObjects, + shapify, + is_closed_edge, +) -from draftutils.utils import (string_encode_coin, - stringencodecoin, - load_svg_patterns, - loadSvgPatterns, - svg_patterns, - svgpatterns, - get_rgb, - getrgb, - argb_to_rgba, - rgba_to_argb, - get_rgba_tuple) +from draftutils.utils import ( + string_encode_coin, + stringencodecoin, + load_svg_patterns, + loadSvgPatterns, + svg_patterns, + svgpatterns, + get_rgb, + getrgb, + argb_to_rgba, + rgba_to_argb, + get_rgba_tuple, +) -from draftfunctions.svg import (get_svg, - getSVG) +from draftfunctions.svg import get_svg, getSVG -from draftfunctions.dxf import (get_dxf, - getDXF) +from draftfunctions.dxf import get_dxf, getDXF -from draftutils.gui_utils import (get3DView, - get_3d_view, - autogroup, - removeHidden, - remove_hidden, - get_diffuse_color, - apply_current_style, - restore_view_object, - formatObject, - format_object, - getSelection, - get_selection, - getSelectionEx, - get_selection_ex, - select, - loadTexture, - load_texture, - get_bbox, - end_all_events) +from draftutils.gui_utils import ( + get3DView, + get_3d_view, + autogroup, + removeHidden, + remove_hidden, + get_diffuse_color, + apply_current_style, + restore_view_object, + formatObject, + format_object, + getSelection, + get_selection, + getSelectionEx, + get_selection_ex, + select, + loadTexture, + load_texture, + get_bbox, + end_all_events, +) -from draftutils.gui_utils import (dim_symbol, - dimSymbol, - dim_dash, - dimDash) +from draftutils.gui_utils import dim_symbol, dimSymbol, dim_dash, dimDash -from draftutils.groups import (is_group, - get_group_names, - getGroupNames, - ungroup, - get_windows, - get_group_contents, - getGroupContents, - get_movable_children, - getMovableChildren) +from draftutils.groups import ( + is_group, + get_group_names, + getGroupNames, + ungroup, + get_windows, + get_group_contents, + getGroupContents, + get_movable_children, + getMovableChildren, +) # --------------------------------------------------------------------------- # Draft functions @@ -143,25 +145,13 @@ from draftfunctions.fuse import fuse from draftfunctions.heal import heal -from draftfunctions.move import (move, - move_vertex, - move_edge, - copy_moved_edge) +from draftfunctions.move import move, move_vertex, move_edge, copy_moved_edge -from draftfunctions.rotate import (rotate, - rotate_vertex, - rotate_edge, - copy_rotated_edge) +from draftfunctions.rotate import rotate, rotate_vertex, rotate_edge, copy_rotated_edge -from draftfunctions.scale import (scale, - scale_vertex, - scale_edge, - copy_scaled_edge) +from draftfunctions.scale import scale, scale_vertex, scale_edge, copy_scaled_edge -from draftfunctions.join import (join_wires, - joinWires, - join_two_wires, - joinTwoWires) +from draftfunctions.join import join_wires, joinWires, join_two_wires, joinTwoWires from draftfunctions.split import split @@ -177,178 +167,135 @@ from draftfunctions.upgrade import upgrade # --------------------------------------------------------------------------- # base object -from draftobjects.base import (DraftObject, - _DraftObject) +from draftobjects.base import DraftObject, _DraftObject # base viewprovider -from draftviewproviders.view_base import (ViewProviderDraft, - _ViewProviderDraft, - ViewProviderDraftAlt, - _ViewProviderDraftAlt, - ViewProviderDraftPart, - _ViewProviderDraftPart) +from draftviewproviders.view_base import ( + ViewProviderDraft, + _ViewProviderDraft, + ViewProviderDraftAlt, + _ViewProviderDraftAlt, + ViewProviderDraftPart, + _ViewProviderDraftPart, +) # App::Link support, used by the arrays -from draftobjects.draftlink import (DraftLink, - _DraftLink) -from draftviewproviders.view_draftlink import (ViewProviderDraftLink, - _ViewProviderDraftLink) +from draftobjects.draftlink import DraftLink, _DraftLink +from draftviewproviders.view_draftlink import ViewProviderDraftLink, _ViewProviderDraftLink # circle -from draftobjects.circle import (Circle, - _Circle) -from draftmake.make_circle import (make_circle, - makeCircle) +from draftobjects.circle import Circle, _Circle +from draftmake.make_circle import make_circle, makeCircle # arcs from draftmake.make_arc_3points import make_arc_3points - # ellipse -from draftobjects.ellipse import (Ellipse, - _Ellipse) -from draftmake.make_ellipse import (make_ellipse, - makeEllipse) +from draftobjects.ellipse import Ellipse, _Ellipse +from draftmake.make_ellipse import make_ellipse, makeEllipse # rectangle -from draftobjects.rectangle import (Rectangle, - _Rectangle) -from draftmake.make_rectangle import (make_rectangle, - makeRectangle) +from draftobjects.rectangle import Rectangle, _Rectangle +from draftmake.make_rectangle import make_rectangle, makeRectangle if App.GuiUp: - from draftviewproviders.view_rectangle import (ViewProviderRectangle, - _ViewProviderRectangle) + from draftviewproviders.view_rectangle import ViewProviderRectangle, _ViewProviderRectangle # polygon -from draftobjects.polygon import (Polygon, - _Polygon) -from draftmake.make_polygon import (make_polygon, - makePolygon) +from draftobjects.polygon import Polygon, _Polygon +from draftmake.make_polygon import make_polygon, makePolygon # wire and line -from draftobjects.wire import (Wire, - _Wire) +from draftobjects.wire import Wire, _Wire -from draftmake.make_line import (make_line, - makeLine) -from draftmake.make_wire import (make_wire, - makeWire) +from draftmake.make_line import make_line, makeLine +from draftmake.make_wire import make_wire, makeWire if App.GuiUp: - from draftviewproviders.view_wire import (ViewProviderWire, - _ViewProviderWire) + from draftviewproviders.view_wire import ViewProviderWire, _ViewProviderWire # bspline -from draftobjects.bspline import (BSpline, - _BSpline) -from draftmake.make_bspline import (make_bspline, - makeBSpline) +from draftobjects.bspline import BSpline, _BSpline +from draftmake.make_bspline import make_bspline, makeBSpline if App.GuiUp: - from draftviewproviders.view_bspline import (ViewProviderBSpline, - _ViewProviderBSpline) + from draftviewproviders.view_bspline import ViewProviderBSpline, _ViewProviderBSpline # bezcurve -from draftobjects.bezcurve import (BezCurve, - _BezCurve) -from draftmake.make_bezcurve import (make_bezcurve, - makeBezCurve) +from draftobjects.bezcurve import BezCurve, _BezCurve +from draftmake.make_bezcurve import make_bezcurve, makeBezCurve if App.GuiUp: - from draftviewproviders.view_bezcurve import (ViewProviderBezCurve, - _ViewProviderBezCurve) + from draftviewproviders.view_bezcurve import ViewProviderBezCurve, _ViewProviderBezCurve # copy from draftmake.make_copy import make_copy from draftmake.make_copy import make_copy as makeCopy # clone -from draftobjects.clone import (Clone, - _Clone) -from draftmake.make_clone import (make_clone, - clone) +from draftobjects.clone import Clone, _Clone +from draftmake.make_clone import make_clone, clone if App.GuiUp: - from draftviewproviders.view_clone import (ViewProviderClone, - _ViewProviderClone) + from draftviewproviders.view_clone import ViewProviderClone, _ViewProviderClone # point -from draftobjects.point import (Point, - _Point) -from draftmake.make_point import (make_point, - makePoint) +from draftobjects.point import Point, _Point +from draftmake.make_point import make_point, makePoint if App.GuiUp: - from draftviewproviders.view_point import (ViewProviderPoint, - _ViewProviderPoint) + from draftviewproviders.view_point import ViewProviderPoint, _ViewProviderPoint # arrays -from draftobjects.array import (Array, - _Array) -from draftmake.make_array import (make_array, - makeArray) -from draftmake.make_orthoarray import (make_ortho_array, - make_ortho_array2d, - make_rect_array, - make_rect_array2d) +from draftobjects.array import Array, _Array +from draftmake.make_array import make_array, makeArray +from draftmake.make_orthoarray import ( + make_ortho_array, + make_ortho_array2d, + make_rect_array, + make_rect_array2d, +) from draftmake.make_polararray import make_polar_array from draftmake.make_circulararray import make_circular_array -from draftobjects.patharray import (PathArray, - _PathArray) -from draftmake.make_patharray import (make_path_array, - makePathArray, - make_path_twisted_array) +from draftobjects.patharray import PathArray, _PathArray +from draftmake.make_patharray import make_path_array, makePathArray, make_path_twisted_array -from draftobjects.pointarray import (PointArray, - _PointArray) -from draftmake.make_pointarray import (make_point_array, - makePointArray) +from draftobjects.pointarray import PointArray, _PointArray +from draftmake.make_pointarray import make_point_array, makePointArray if App.GuiUp: - from draftviewproviders.view_array import (ViewProviderDraftArray, - _ViewProviderDraftArray) + from draftviewproviders.view_array import ViewProviderDraftArray, _ViewProviderDraftArray # facebinder -from draftobjects.facebinder import (Facebinder, - _Facebinder) -from draftmake.make_facebinder import (make_facebinder, - makeFacebinder) +from draftobjects.facebinder import Facebinder, _Facebinder +from draftmake.make_facebinder import make_facebinder, makeFacebinder if App.GuiUp: - from draftviewproviders.view_facebinder import (ViewProviderFacebinder, - _ViewProviderFacebinder) + from draftviewproviders.view_facebinder import ViewProviderFacebinder, _ViewProviderFacebinder # shapestring -from draftobjects.block import (Block, - _Block) -from draftmake.make_block import (make_block, - makeBlock) +from draftobjects.block import Block, _Block +from draftmake.make_block import make_block, makeBlock # shapestring -from draftobjects.shapestring import (ShapeString, - _ShapeString) -from draftmake.make_shapestring import (make_shapestring, - makeShapeString) +from draftobjects.shapestring import ShapeString, _ShapeString +from draftmake.make_shapestring import make_shapestring, makeShapeString + if App.GuiUp: from draftviewproviders.view_shapestring import ViewProviderShapeString # shape 2d view -from draftobjects.shape2dview import (Shape2DView, - _Shape2DView) -from draftmake.make_shape2dview import (make_shape2dview, - makeShape2DView) +from draftobjects.shape2dview import Shape2DView, _Shape2DView +from draftmake.make_shape2dview import make_shape2dview, makeShape2DView # sketch -from draftmake.make_sketch import (make_sketch, - makeSketch) +from draftmake.make_sketch import make_sketch, makeSketch # working plane proxy from draftobjects.wpproxy import WorkingPlaneProxy -from draftmake.make_wpproxy import (make_workingplaneproxy, - makeWorkingPlaneProxy) +from draftmake.make_wpproxy import make_workingplaneproxy, makeWorkingPlaneProxy if App.GuiUp: from draftviewproviders.view_wpproxy import ViewProviderWorkingPlaneProxy @@ -359,59 +306,49 @@ from draftmake.make_fillet import make_fillet if App.GuiUp: from draftviewproviders.view_fillet import ViewProviderFillet -from draftobjects.layer import (Layer, - _VisGroup, - get_layer) +from draftobjects.layer import Layer, _VisGroup, get_layer from draftmake.make_layer import make_layer if App.GuiUp: - from draftviewproviders.view_layer import (ViewProviderLayer, - _ViewProviderVisGroup) + from draftviewproviders.view_layer import ViewProviderLayer, _ViewProviderVisGroup # Annotation objects -from draftobjects.dimension import (LinearDimension, - _Dimension, - AngularDimension, - _AngularDimension) -from draftmake.make_dimension import (make_dimension, - makeDimension, - make_linear_dimension, - make_linear_dimension_obj, - make_radial_dimension_obj, - make_angular_dimension, - makeAngularDimension) +from draftobjects.dimension import LinearDimension, _Dimension, AngularDimension, _AngularDimension +from draftmake.make_dimension import ( + make_dimension, + makeDimension, + make_linear_dimension, + make_linear_dimension_obj, + make_radial_dimension_obj, + make_angular_dimension, + makeAngularDimension, +) if App.GuiUp: - from draftviewproviders.view_dimension \ - import (ViewProviderLinearDimension, - _ViewProviderDimension, - ViewProviderAngularDimension, - _ViewProviderAngularDimension) + from draftviewproviders.view_dimension import ( + ViewProviderLinearDimension, + _ViewProviderDimension, + ViewProviderAngularDimension, + _ViewProviderAngularDimension, + ) -from draftobjects.label import (Label, - DraftLabel) -from draftmake.make_label import (make_label, - makeLabel) +from draftobjects.label import Label, DraftLabel +from draftmake.make_label import make_label, makeLabel if App.GuiUp: - from draftviewproviders.view_label import (ViewProviderLabel, - ViewProviderDraftLabel) + from draftviewproviders.view_label import ViewProviderLabel, ViewProviderDraftLabel -from draftobjects.text import (Text, - DraftText) -from draftmake.make_text import (make_text, - makeText, - convert_draft_texts, - convertDraftTexts) +from draftobjects.text import Text, DraftText +from draftmake.make_text import make_text, makeText, convert_draft_texts, convertDraftTexts if App.GuiUp: - from draftviewproviders.view_text import (ViewProviderText, - ViewProviderDraftText) + from draftviewproviders.view_text import ViewProviderText, ViewProviderDraftText + +from draftobjects.hatch import Hatch +from draftmake.make_hatch import make_hatch -from draftobjects.hatch import (Hatch) -from draftmake.make_hatch import (make_hatch) if App.GuiUp: - from draftviewproviders.view_hatch import (ViewProviderDraftHatch) + from draftviewproviders.view_hatch import ViewProviderDraftHatch ## @} diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index 0f76da33cb..227cca9fcc 100644 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -40,130 +40,130 @@ __author__ = "Yorik van Havre, Jacques-Antoine Gaudin, Ken Cline" __url__ = ["https://www.freecad.org"] # Doesn't need requisites -from draftgeoutils.linear_algebra import (linearFromPoints, - determinant) +from draftgeoutils.linear_algebra import linearFromPoints, determinant # Needs math, Part, and vector tools from draftgeoutils.general import NORM -from draftgeoutils.general import (precision, - vec, - edg, - getVerts, - v1, - isNull, - isPtOnEdge, - hasCurves, - isAligned, - getQuad, - areColinear, - hasOnlyWires, - geomType, - isValidPath, - findClosest, - getBoundaryAngles) +from draftgeoutils.general import ( + precision, + vec, + edg, + getVerts, + v1, + isNull, + isPtOnEdge, + hasCurves, + isAligned, + getQuad, + areColinear, + hasOnlyWires, + geomType, + isValidPath, + findClosest, + getBoundaryAngles, +) # Needs general functions -from draftgeoutils.geometry import (findPerpendicular, - findDistance, - getSplineNormal, - get_spline_normal, - getNormal, - get_normal, - get_shape_normal, - getRotation, - isPlanar, - is_planar, - calculatePlacement, - mirror, - are_coplanar, - is_straight_line, - mirror_matrix, - uv_vectors_from_face, - placement_from_face, - placement_from_points, - distance_to_plane, - project_point_on_plane) +from draftgeoutils.geometry import ( + findPerpendicular, + findDistance, + getSplineNormal, + get_spline_normal, + getNormal, + get_normal, + get_shape_normal, + getRotation, + isPlanar, + is_planar, + calculatePlacement, + mirror, + are_coplanar, + is_straight_line, + mirror_matrix, + uv_vectors_from_face, + placement_from_face, + placement_from_points, + distance_to_plane, + project_point_on_plane, +) -from draftgeoutils.edges import (findEdge, - orientEdge, - isSameLine, - isLine, - is_line, - invert, - findMidpoint, - getTangent, - get_referenced_edges) +from draftgeoutils.edges import ( + findEdge, + orientEdge, + isSameLine, + isLine, + is_line, + invert, + findMidpoint, + getTangent, + get_referenced_edges, +) -from draftgeoutils.faces import (concatenate, - getBoundary, - isCoplanar, - is_coplanar, - bind, - cleanFaces, - removeSplitter) +from draftgeoutils.faces import ( + concatenate, + getBoundary, + isCoplanar, + is_coplanar, + bind, + cleanFaces, + removeSplitter, +) -from draftgeoutils.arcs import (isClockwise, - isWideAngle, - arcFrom2Pts, - arcFromSpline) +from draftgeoutils.arcs import isClockwise, isWideAngle, arcFrom2Pts, arcFromSpline -from draftgeoutils.cuboids import (isCubic, - getCubicDimensions) +from draftgeoutils.cuboids import isCubic, getCubicDimensions # Needs geometry functions -from draftgeoutils.circle_inversion import (pointInversion, - polarInversion, - circleInversion) +from draftgeoutils.circle_inversion import pointInversion, polarInversion, circleInversion # Needs edges functions -from draftgeoutils.sort_edges import (sortEdges, - sortEdgesOld) +from draftgeoutils.sort_edges import sortEdges, sortEdgesOld -from draftgeoutils.intersections import (findIntersection, - wiresIntersect, - connect, - angleBisection) +from draftgeoutils.intersections import findIntersection, wiresIntersect, connect, angleBisection -from draftgeoutils.wires import (findWires, - findWiresOld, - findWiresOld2, - flattenWire, - superWire, - isReallyClosed, - curvetowire, - curvetosegment, - rebaseWire, - removeInterVertices, - cleanProjection, - tessellateProjection, - get_placement_perpendicular_to_wire, - get_extended_wire) +from draftgeoutils.wires import ( + findWires, + findWiresOld, + findWiresOld2, + flattenWire, + superWire, + isReallyClosed, + curvetowire, + curvetosegment, + rebaseWire, + removeInterVertices, + cleanProjection, + tessellateProjection, + get_placement_perpendicular_to_wire, + get_extended_wire, +) # Needs wires functions -from draftgeoutils.fillets import (fillet, - filletWire) +from draftgeoutils.fillets import fillet, filletWire # Needs intersections functions -from draftgeoutils.offsets import (pocket2d, - offset, - offsetWire) +from draftgeoutils.offsets import pocket2d, offset, offsetWire -from draftgeoutils.circles import (findClosestCircle, - getCircleFromSpline, - circlefrom1Line2Points, - circlefrom2Lines1Point, - circleFrom2LinesRadius, - circleFrom3LineTangents, - circleFromPointLineRadius, - circleFrom2PointsRadius, - findHomotheticCenterOfCircles, - findRadicalAxis, - findRadicalCenter) +from draftgeoutils.circles import ( + findClosestCircle, + getCircleFromSpline, + circlefrom1Line2Points, + circlefrom2Lines1Point, + circleFrom2LinesRadius, + circleFrom3LineTangents, + circleFromPointLineRadius, + circleFrom2PointsRadius, + findHomotheticCenterOfCircles, + findRadicalAxis, + findRadicalCenter, +) -from draftgeoutils.circles_apollonius import (outerSoddyCircle, - innerSoddyCircle, - circleFrom3CircleTangents) +from draftgeoutils.circles_apollonius import ( + outerSoddyCircle, + innerSoddyCircle, + circleFrom3CircleTangents, +) # Needs circles_apollonius functions # These functions are not imported because they are incomplete; diff --git a/src/Mod/Draft/DraftGlobal.h b/src/Mod/Draft/DraftGlobal.h index 645fdca2e8..25f942fcbf 100644 --- a/src/Mod/Draft/DraftGlobal.h +++ b/src/Mod/Draft/DraftGlobal.h @@ -29,10 +29,10 @@ // Draft #ifndef DraftUtilsExport #ifdef DraftUtils_EXPORTS -# define DraftUtilsExport FREECAD_DECL_EXPORT +#define DraftUtilsExport FREECAD_DECL_EXPORT #else -# define DraftUtilsExport FREECAD_DECL_IMPORT +#define DraftUtilsExport FREECAD_DECL_IMPORT #endif #endif -#endif //DRAFT_GLOBAL_H +#endif // DRAFT_GLOBAL_H diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index d11ed0598d..e8d8861db0 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -1,26 +1,26 @@ # -*- coding: utf8 -*- -#*************************************************************************** -#* Copyright (c) 2009 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * Copyright (c) 2009 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** -__title__ = "FreeCAD Draft Workbench - GUI part" +__title__ = "FreeCAD Draft Workbench - GUI part" __author__ = "Yorik van Havre " __url__ = "https://www.freecad.org" @@ -55,41 +55,52 @@ from draftutils.todo import todo from draftutils.translate import translate from draftutils.units import display_external + def _get_incmd_shortcut(itm): return params.get_param("inCommandShortcut" + itm).upper() -#--------------------------------------------------------------------------- +# --------------------------------------------------------------------------- # Customized widgets -#--------------------------------------------------------------------------- +# --------------------------------------------------------------------------- + class DraftBaseWidget(QtWidgets.QWidget): - def __init__(self,parent = None): + def __init__(self, parent=None): super().__init__(parent) + def eventFilter(self, widget, event): - if (event.type() == QtCore.QEvent.KeyPress - and event.text().upper() == _get_incmd_shortcut("CycleSnap")): - if hasattr(FreeCADGui,"Snapper"): + if event.type() == QtCore.QEvent.KeyPress and event.text().upper() == _get_incmd_shortcut( + "CycleSnap" + ): + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.cycleSnapObject() return True return super().eventFilter(widget, event) + class DraftDockWidget(DraftBaseWidget): """custom Widget that emits a resized() signal when resized""" - def __init__(self,parent = None): + + def __init__(self, parent=None): super().__init__(parent) - def resizeEvent(self,event): + + def resizeEvent(self, event): self.emit(QtCore.SIGNAL("resized()")) + def changeEvent(self, event): if event.type() == QtCore.QEvent.LanguageChange: self.emit(QtCore.SIGNAL("retranslate()")) else: super().changeEvent(event) + class DraftLineEdit(QtWidgets.QLineEdit): """custom QLineEdit widget that has the power to catch Escape keypress""" + def __init__(self, parent=None): super().__init__(parent) + def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.emit(QtCore.SIGNAL("escaped()")) @@ -100,24 +111,28 @@ class DraftLineEdit(QtWidgets.QLineEdit): else: super().keyPressEvent(event) + class DraftTaskPanel: - def __init__(self,widget,extra=None): + def __init__(self, widget, extra=None): if extra: - if isinstance(extra,list): + if isinstance(extra, list): self.form = [widget] + extra else: - self.form = [widget,extra] + self.form = [widget, extra] else: self.form = widget + def getStandardButtons(self): return QtWidgets.QDialogButtonBox.Close + def accept(self): - if hasattr(FreeCADGui,"draftToolBar"): + if hasattr(FreeCADGui, "draftToolBar"): return FreeCADGui.draftToolBar.validatePoint() else: if FreeCADGui.ActiveDocument: FreeCADGui.ActiveDocument.resetEdit() return True + def reject(self): # https://github.com/FreeCAD/FreeCAD/issues/17027 # Function can be called multiple times if Esc is pressed during mouse @@ -129,9 +144,11 @@ class DraftTaskPanel: if FreeCADGui.ActiveDocument: FreeCADGui.ActiveDocument.resetEdit() return True + def isAllowedAlterDocument(self): return False + class DraftToolBar: """The Draft Task panel UI Draft Toolbar is the main ui of the Draft Module. Once displayed as a @@ -141,6 +158,7 @@ class DraftToolBar: Draft Ui Commands call and get information such as point coordinates, subcommands activation, continue mode, etc. from Task Panel Ui """ + def __init__(self): self.tray = None self.sourceCmd = None @@ -150,8 +168,12 @@ class DraftToolBar: self.pointcallback = None # OBSOLETE BUT STILL USED BY SOME ADDONS AND MACROS - 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.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") @@ -171,7 +193,7 @@ class DraftToolBar: self.x = 0 # coord of the point as displayed in the task panel (global/local and relative/absolute) self.y = 0 # idem self.z = 0 # idem - self.new_point = None # global point value + self.new_point = None # global point value self.last_point = None # idem self.lvalue = 0 self.pvalue = 90 @@ -183,12 +205,12 @@ class DraftToolBar: self.autogroup = None self.isCenterPlane = False self.input_fields = { - "xValue":{"value":"x","unit":"Length"}, - "yValue":{"value":"y","unit":"Length"}, - "zValue":{"value":"z","unit":"Length"}, - "lengthValue":{"value":"lvalue","unit":"Length"}, - "radiusValue":{"value":"radius","unit":"Length"}, - "angleValue":{"value":"avalue","unit":"Angle"} + "xValue": {"value": "x", "unit": "Length"}, + "yValue": {"value": "y", "unit": "Length"}, + "zValue": {"value": "z", "unit": "Length"}, + "lengthValue": {"value": "lvalue", "unit": "Length"}, + "radiusValue": {"value": "radius", "unit": "Length"}, + "angleValue": {"value": "avalue", "unit": "Angle"}, } # add only a dummy widget, since widgets are created on demand @@ -206,12 +228,13 @@ class DraftToolBar: self.tray.hide() self.display_point_active = False # prevent cyclic processing of point values -#--------------------------------------------------------------------------- -# General UI setup -#--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + # General UI setup + # --------------------------------------------------------------------------- - def _pushbutton(self,name, layout, hide=True, icon=None, - width=None, checkable=False, square=False): + def _pushbutton( + self, name, layout, hide=True, icon=None, width=None, checkable=False, square=False + ): if square: button = QtWidgets.QToolButton(self.baseWidget) if width is not None: @@ -226,40 +249,43 @@ class DraftToolBar: if icon.endswith(".svg"): button.setIcon(QtGui.QIcon(icon)) else: - button.setIcon(QtGui.QIcon.fromTheme( - icon, QtGui.QIcon(':/icons/'+icon+'.svg'))) + button.setIcon(QtGui.QIcon.fromTheme(icon, QtGui.QIcon(":/icons/" + icon + ".svg"))) if checkable: button.setCheckable(True) button.setChecked(False) layout.addWidget(button) return button - def _label (self,name, layout, hide=True, wrap=False): + def _label(self, name, layout, hide=True, wrap=False): label = QtWidgets.QLabel(self.baseWidget) label.setObjectName(name) if wrap: label.setWordWrap(True) - if hide: label.hide() + if hide: + label.hide() layout.addWidget(label) return label - def _lineedit (self,name, layout, hide=True, width=None): + def _lineedit(self, name, layout, hide=True, width=None): bsize = params.get_param("ToolbarIconSize", path="General") - 2 lineedit = DraftLineEdit(self.baseWidget) lineedit.setObjectName(name) - if hide: lineedit.hide() - #if not width: width = 800 - #lineedit.setMaximumSize(QtCore.QSize(width,bsize)) + if hide: + lineedit.hide() + # if not width: width = 800 + # lineedit.setMaximumSize(QtCore.QSize(width,bsize)) layout.addWidget(lineedit) return lineedit - def _inputfield (self,name, layout, hide=True, width=None): + def _inputfield(self, name, layout, hide=True, width=None): inputfield = self.uiloader.createWidget("Gui::InputField") inputfield.setObjectName(name) - if hide: inputfield.hide() + if hide: + inputfield.hide() if not width: sizePolicy = QtWidgets.QSizePolicy( - QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred + ) inputfield.setSizePolicy(sizePolicy) inputfield.setMinimumWidth(110) else: @@ -267,36 +293,40 @@ class DraftToolBar: layout.addWidget(inputfield) return inputfield - def _spinbox (self,name, layout, val=None, vmax=None, - hide=True, double=False, size=None): + def _spinbox(self, name, layout, val=None, vmax=None, hide=True, double=False, size=None): if double: sbox = QtWidgets.QDoubleSpinBox(self.baseWidget) sbox.setDecimals(params.get_param("Decimals", path="Units")) else: sbox = QtWidgets.QSpinBox(self.baseWidget) sbox.setObjectName(name) - if vmax: sbox.setMaximum(vmax) - if val: sbox.setValue(val) - #if size: sbox.setMaximumSize(QtCore.QSize(size[0],size[1])) - if hide: sbox.hide() + if vmax: + sbox.setMaximum(vmax) + if val: + sbox.setValue(val) + # if size: sbox.setMaximumSize(QtCore.QSize(size[0],size[1])) + if hide: + sbox.hide() layout.addWidget(sbox) return sbox - def _checkbox (self,name, layout, checked=True, hide=True): + def _checkbox(self, name, layout, checked=True, hide=True): chk = QtWidgets.QCheckBox(self.baseWidget) chk.setChecked(checked) chk.setObjectName(name) - if hide: chk.hide() + if hide: + chk.hide() layout.addWidget(chk) return chk - def _combo (self,name,layout,hide=True): + def _combo(self, name, layout, hide=True): cb = QtWidgets.QComboBox(self.baseWidget) cb.setObjectName(name) - if hide: cb.hide() + if hide: + cb.hide() layout.addWidget(cb) - def setupToolBar(self,task=False): + def setupToolBar(self, task=False): """sets the draft toolbar up""" # command @@ -318,17 +348,21 @@ class DraftToolBar: self.layout.addLayout(zl) self.layout.addLayout(bl) self.labelx = self._label("labelx", xl) - self.xValue = self._inputfield("xValue", xl) #width=60 + self.xValue = self._inputfield("xValue", xl) # width=60 self.xValue.installEventFilter(self.baseWidget) - self.xValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.xValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.labely = self._label("labely", yl) self.yValue = self._inputfield("yValue", yl) - self.yValue.installEventFilter(self.baseWidget) # Required to detect snap cycling in case of Y constraining. - self.yValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.yValue.installEventFilter( + self.baseWidget + ) # Required to detect snap cycling in case of Y constraining. + self.yValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.labelz = self._label("labelz", zl) self.zValue = self._inputfield("zValue", zl) - self.zValue.installEventFilter(self.baseWidget) # Required to detect snap cycling in case of Z constraining. - self.zValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.zValue.installEventFilter( + self.baseWidget + ) # Required to detect snap cycling in case of Z constraining. + self.zValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.pointButton = self._pushbutton("addButton", bl, icon="Draft_AddPoint") # text @@ -350,12 +384,14 @@ class DraftToolBar: self.layout.addLayout(al) self.labellength = self._label("labellength", ll) self.lengthValue = self._inputfield("lengthValue", ll) - self.lengthValue.installEventFilter(self.baseWidget) # Required to detect snap cycling if focusOnLength is True. - self.lengthValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.lengthValue.installEventFilter( + self.baseWidget + ) # Required to detect snap cycling if focusOnLength is True. + self.lengthValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.labelangle = self._label("labelangle", al) - self.angleLock = self._checkbox("angleLock",al,checked=self.alock) + self.angleLock = self._checkbox("angleLock", al, checked=self.alock) self.angleValue = self._inputfield("angleValue", al) - self.angleValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) + self.angleValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Angle).UserString) # options @@ -369,37 +405,36 @@ class DraftToolBar: self.layout.addLayout(rl) self.labelRadius = self._label("labelRadius", rl) self.radiusValue = self._inputfield("radiusValue", rl) - self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.radiusValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.undoButton = self._pushbutton("undoButton", bl, icon='Draft_Rotate') + self.undoButton = self._pushbutton("undoButton", bl, icon="Draft_Rotate") bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.finishButton = self._pushbutton("finishButton", bl, icon='Draft_Finish') + self.finishButton = self._pushbutton("finishButton", bl, icon="Draft_Finish") bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.closeButton = self._pushbutton("closeButton", bl, icon='Draft_Lock') + self.closeButton = self._pushbutton("closeButton", bl, icon="Draft_Lock") bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.wipeButton = self._pushbutton("wipeButton", bl, icon='Draft_Wipe') + self.wipeButton = self._pushbutton("wipeButton", bl, icon="Draft_Wipe") bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.orientWPButton = self._pushbutton("orientWPButton", bl, icon='Draft_SelectPlane') + self.orientWPButton = self._pushbutton("orientWPButton", bl, icon="Draft_SelectPlane") bl = QtWidgets.QHBoxLayout() self.layout.addLayout(bl) - self.selectButton = self._pushbutton("selectButton", bl, icon='view-select') + self.selectButton = self._pushbutton("selectButton", bl, icon="view-select") # update modes from parameters: self.relativeMode = params.get_param("RelativeMode") self.globalMode = params.get_param("GlobalMode") self.makeFaceMode = params.get_param("MakeFaceMode") - if getattr(FreeCAD, "activeDraftCommand", None) \ - and getattr(FreeCAD.activeDraftCommand, "featureName", None): + if getattr(FreeCAD, "activeDraftCommand", None) and getattr( + FreeCAD.activeDraftCommand, "featureName", None + ): self.continueMode = params.get_param( - FreeCAD.activeDraftCommand.featureName, - "Mod/ContinueMode", - silent=True + FreeCAD.activeDraftCommand.featureName, "Mod/ContinueMode", silent=True ) self.chainedMode = params.get_param("ChainedMode") @@ -411,10 +446,16 @@ class DraftToolBar: self.isRelative = self._checkbox("isRelative", self.layout, checked=self.relativeMode) self.isGlobal = self._checkbox("isGlobal", self.layout, checked=self.globalMode) self.makeFace = self._checkbox("makeFace", self.layout, checked=self.makeFaceMode) - self.continueCmd = self._checkbox("continueCmd", self.layout, checked=bool(self.continueMode)) - self.chainedModeCmd = self._checkbox("chainedModeCmd", self.layout, checked=self.chainedMode) + self.continueCmd = self._checkbox( + "continueCmd", self.layout, checked=bool(self.continueMode) + ) + self.chainedModeCmd = self._checkbox( + "chainedModeCmd", self.layout, checked=self.chainedMode + ) - self.chainedModeCmd.setEnabled(not (hasattr(self.sourceCmd, "contMode") and self.continueMode)) + self.chainedModeCmd.setEnabled( + not (hasattr(self.sourceCmd, "contMode") and self.continueMode) + ) self.continueCmd.setEnabled(not (hasattr(self.sourceCmd, "chain") and self.chainedMode)) # update checkboxes without parameters and without internal modes: @@ -422,16 +463,15 @@ class DraftToolBar: # update checkboxes with parameters but without internal modes: # self.isCopy is also updated in modUi ("CopyMode") and offsetUi ("OffsetCopyMode") - self.isCopy = self._checkbox("isCopy", - self.layout, - checked=params.get_param("CopyMode")) - self.isSubelementMode = self._checkbox("isSubelementMode", - self.layout, - checked=params.get_param("SubelementMode")) + self.isCopy = self._checkbox("isCopy", self.layout, checked=params.get_param("CopyMode")) + self.isSubelementMode = self._checkbox( + "isSubelementMode", self.layout, checked=params.get_param("SubelementMode") + ) # spacer - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, - QtWidgets.QSizePolicy.Expanding) + spacerItem = QtWidgets.QSpacerItem( + 20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding + ) self.layout.addItem(spacerItem) self.xValue.valueChanged.connect(self.changeXValue) @@ -439,9 +479,9 @@ class DraftToolBar: self.zValue.valueChanged.connect(self.changeZValue) self.lengthValue.valueChanged.connect(self.changeLengthValue) self.angleValue.valueChanged.connect(self.changeAngleValue) - if hasattr(self.angleLock, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.angleLock, "checkStateChanged"): # Qt version >= 6.7.0 self.angleLock.checkStateChanged.connect(self.toggleAngle) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.angleLock.stateChanged.connect(self.toggleAngle) self.radiusValue.valueChanged.connect(self.changeRadiusValue) self.xValue.returnPressed.connect(self.checkx) @@ -467,7 +507,7 @@ class DraftToolBar: self.orientWPButton.clicked.connect(self.orientWP) self.undoButton.clicked.connect(self.undoSegment) self.selectButton.clicked.connect(self.selectEdge) - if hasattr(self.continueCmd, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.continueCmd, "checkStateChanged"): # Qt version >= 6.7.0 self.continueCmd.checkStateChanged.connect(self.setContinue) self.chainedModeCmd.checkStateChanged.connect(self.setChainedMode) self.isCopy.checkStateChanged.connect(self.setCopymode) @@ -475,7 +515,7 @@ class DraftToolBar: self.isRelative.checkStateChanged.connect(self.setRelative) self.isGlobal.checkStateChanged.connect(self.setGlobal) self.makeFace.checkStateChanged.connect(self.setMakeFace) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.continueCmd.stateChanged.connect(self.setContinue) self.chainedModeCmd.stateChanged.connect(self.setChainedMode) self.isCopy.stateChanged.connect(self.setCopymode) @@ -488,20 +528,26 @@ class DraftToolBar: """sets draft tray buttons up""" self.wplabel = self._pushbutton( - "wplabel", self.toptray, icon='Draft_SelectPlane', - hide=False,width=120) + "wplabel", self.toptray, icon="Draft_SelectPlane", hide=False, width=120 + ) self.styleButton = self._pushbutton( - "stylebutton", self.toptray, icon='Draft_Apply', hide=False, - width=120) + "stylebutton", self.toptray, icon="Draft_Apply", hide=False, width=120 + ) self.setStyleButton() self.constrButton = self._pushbutton( - "constrButton", self.toptray, hide=False, icon='Draft_Construction', - width=self.styleButton.sizeHint().height(), checkable=True, square=True) + "constrButton", + self.toptray, + hide=False, + icon="Draft_Construction", + width=self.styleButton.sizeHint().height(), + checkable=True, + square=True, + ) self.constrColor = QtGui.QColor(self.paramconstr) self.autoGroupButton = self._pushbutton( - "autoGroup", self.bottomtray,icon=":/icons/button_invalid.svg", - hide=False, width=120) + "autoGroup", self.bottomtray, icon=":/icons/button_invalid.svg", hide=False, width=120 + ) self.autoGroupButton.setText(translate("draft", "None")) self.autoGroupButton.setFlat(True) @@ -510,23 +556,24 @@ class DraftToolBar: self.constrButton.toggled.connect(self.toggleConstrMode) self.autoGroupButton.clicked.connect(self.runAutoGroup) - QtCore.QTimer.singleShot(2000,self.retranslateTray) # delay so translations get a chance to load + QtCore.QTimer.singleShot( + 2000, self.retranslateTray + ) # delay so translations get a chance to load def setupStyle(self): style = "#constrButton:Checked {background-color: " - style += self.getDefaultColor("constr",rgb=True)+" } " + style += self.getDefaultColor("constr", rgb=True) + " } " style += "#addButton:Checked, #delButton:checked, " style += "#sharpButton:Checked, " style += "#tangentButton:Checked, #symmetricButton:checked {" style += "background-color: rgb(20,100,250) }" self.baseWidget.setStyleSheet(style) - #if hasattr(self,"tray"): + # if hasattr(self,"tray"): # self.tray.setStyleSheet(style) - -#--------------------------------------------------------------------------- -# language tools -#--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + # language tools + # --------------------------------------------------------------------------- def retranslateUi(self, widget=None): self.promptlabel.setText(translate("draft", "active command:")) @@ -539,75 +586,138 @@ class DraftToolBar: self.yValue.setToolTip(translate("draft", "Y coordinate of the point")) self.zValue.setToolTip(translate("draft", "Z coordinate of the point")) self.pointButton.setText(translate("draft", "Enter Point")) - self.pointButton.setToolTip(translate( - "draft","Enter a point with given coordinates")) + self.pointButton.setToolTip(translate("draft", "Enter a point with given coordinates")) self.labellength.setText(translate("draft", "Length")) self.labelangle.setText(translate("draft", "Angle")) self.lengthValue.setToolTip(translate("draft", "Length of the current segment")) self.angleValue.setToolTip(translate("draft", "Angle of the current segment")) - self.angleLock.setToolTip(translate( - "draft", "Locks the current angle")\ - + " (" + _get_incmd_shortcut("Length") + ")") + self.angleLock.setToolTip( + translate("draft", "Locks the current angle") + + " (" + + _get_incmd_shortcut("Length") + + ")" + ) self.labelRadius.setText(translate("draft", "Radius")) self.radiusValue.setToolTip(translate("draft", "Radius of the circle")) - self.isRelative.setText(translate( - "draft", "Relative") + " (" + _get_incmd_shortcut("Relative") + ")") - self.isRelative.setToolTip(translate( - "draft", "Coordinates relative to last point or to coordinate system " - + "origin\nif is the first point to set")) - self.isGlobal.setText(translate( - "draft", "Global") + " (" + _get_incmd_shortcut("Global") + ")") - self.isGlobal.setToolTip(translate( - "draft", "Coordinates relative to global coordinate system." - + "\nUncheck to use working plane coordinate system")) - self.makeFace.setText(translate( - "draft", "Make face") + " (" + _get_incmd_shortcut("MakeFace") + ")") - self.makeFace.setToolTip(translate( - "draft", "If checked, the object will be filled with a face." - + "\nNot available if the 'Use Part Primitives' preference is enabled")) - self.finishButton.setText(translate( - "draft", "Finish") + " (" + _get_incmd_shortcut("Exit") + ")") - self.finishButton.setToolTip(translate( - "draft", "Finishes the current drawing or editing operation")) - self.continueCmd.setText(translate( - "draft", "Continue") + " (" + _get_incmd_shortcut("Continue") + ")") - self.continueCmd.setToolTip(translate( - "draft", "If checked, the command will not finish until pressing " - + "the command button again")) + self.isRelative.setText( + translate("draft", "Relative") + " (" + _get_incmd_shortcut("Relative") + ")" + ) + self.isRelative.setToolTip( + translate( + "draft", + "Coordinates relative to last point or to coordinate system " + + "origin\nif is the first point to set", + ) + ) + self.isGlobal.setText( + translate("draft", "Global") + " (" + _get_incmd_shortcut("Global") + ")" + ) + self.isGlobal.setToolTip( + translate( + "draft", + "Coordinates relative to global coordinate system." + + "\nUncheck to use working plane coordinate system", + ) + ) + self.makeFace.setText( + translate("draft", "Make face") + " (" + _get_incmd_shortcut("MakeFace") + ")" + ) + self.makeFace.setToolTip( + translate( + "draft", + "If checked, the object will be filled with a face." + + "\nNot available if the 'Use Part Primitives' preference is enabled", + ) + ) + self.finishButton.setText( + translate("draft", "Finish") + " (" + _get_incmd_shortcut("Exit") + ")" + ) + self.finishButton.setToolTip( + translate("draft", "Finishes the current drawing or editing operation") + ) + self.continueCmd.setText( + translate("draft", "Continue") + " (" + _get_incmd_shortcut("Continue") + ")" + ) + self.continueCmd.setToolTip( + translate( + "draft", + "If checked, the command will not finish until pressing " + + "the command button again", + ) + ) self.chainedModeCmd.setText(translate("draft", "Chained mode")) - self.chainedModeCmd.setToolTip(translate("draft", "If checked, the next dimension will be placed in a chain" \ - " with the previously placed Dimension")) + self.chainedModeCmd.setToolTip( + translate( + "draft", + "If checked, the next dimension will be placed in a chain" + " with the previously placed Dimension", + ) + ) self.occOffset.setText(translate("draft", "OCC-style offset")) - self.occOffset.setToolTip(translate( - "draft", "If checked, an OCC-style offset will be performed" - + " instead of the classic offset")) - self.undoButton.setText(translate("draft", "Undo") + " (" + _get_incmd_shortcut("Undo") + ")") + self.occOffset.setToolTip( + translate( + "draft", + "If checked, an OCC-style offset will be performed" + + " instead of the classic offset", + ) + ) + self.undoButton.setText( + translate("draft", "Undo") + " (" + _get_incmd_shortcut("Undo") + ")" + ) self.undoButton.setToolTip(translate("draft", "Undo the last segment")) - self.closeButton.setText(translate("draft", "Close") + " (" + _get_incmd_shortcut("Close") + ")") + self.closeButton.setText( + translate("draft", "Close") + " (" + _get_incmd_shortcut("Close") + ")" + ) self.closeButton.setToolTip(translate("draft", "Finishes and closes the current line")) - self.wipeButton.setText(translate("draft", "Wipe") + " (" + _get_incmd_shortcut("Wipe") + ")") - self.wipeButton.setToolTip(translate("draft", "Wipes the existing segments of this line and starts again from the last point")) - self.orientWPButton.setText(translate("draft", "Set Working Plane") + " (" + _get_incmd_shortcut("SetWP") + ")") - self.orientWPButton.setToolTip(translate("draft", "Reorients the working plane on the last segment")) - self.selectButton.setText(translate("draft", "Select Edge") + " (" + _get_incmd_shortcut("SelectEdge") + ")") - self.selectButton.setToolTip(translate("draft", "Selects an existing edge to be measured by this dimension")) + self.wipeButton.setText( + translate("draft", "Wipe") + " (" + _get_incmd_shortcut("Wipe") + ")" + ) + self.wipeButton.setToolTip( + translate( + "draft", + "Wipes the existing segments of this line and starts again from the last point", + ) + ) + self.orientWPButton.setText( + translate("draft", "Set Working Plane") + " (" + _get_incmd_shortcut("SetWP") + ")" + ) + self.orientWPButton.setToolTip( + translate("draft", "Reorients the working plane on the last segment") + ) + self.selectButton.setText( + translate("draft", "Select Edge") + " (" + _get_incmd_shortcut("SelectEdge") + ")" + ) + self.selectButton.setToolTip( + translate("draft", "Selects an existing edge to be measured by this dimension") + ) self.numFacesLabel.setText(translate("draft", "Sides")) self.numFaces.setToolTip(translate("draft", "Number of sides")) self.isCopy.setText(translate("draft", "Copy") + " (" + _get_incmd_shortcut("Copy") + ")") - self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved")) - self.isSubelementMode.setText(translate("draft", "Modify subelements") + " (" + _get_incmd_shortcut("SubelementMode") + ")") - self.isSubelementMode.setToolTip(translate("draft", "If checked, subelements will be modified instead of entire objects")) + self.isCopy.setToolTip( + translate("draft", "If checked, objects will be copied instead of moved") + ) + self.isSubelementMode.setText( + translate("draft", "Modify subelements") + + " (" + + _get_incmd_shortcut("SubelementMode") + + ")" + ) + self.isSubelementMode.setToolTip( + translate("draft", "If checked, subelements will be modified instead of entire objects") + ) self.textOkButton.setText(translate("draft", "Create Text")) - self.textOkButton.setToolTip(translate("draft", "Creates the text object and finishes the command")) + self.textOkButton.setToolTip( + translate("draft", "Creates the text object and finishes the command") + ) self.retranslateTray(widget) # Update the maximum width of the push buttons - maxwidth = 66 # that's the default + maxwidth = 66 # that's the default pb = [] for i in range(self.layout.count()): w = self.layout.itemAt(i).widget() - if w is not None and w.inherits('QPushButton'): + if w is not None and w.inherits("QPushButton"): pb.append(w) for i in pb: @@ -615,27 +725,26 @@ class DraftToolBar: fw = fm.width(i.text()) fw = max(fw, maxwidth) - maxwidth = maxwidth + 16 +10 # add icon width and a margin + maxwidth = maxwidth + 16 + 10 # add icon width and a margin for i in pb: i.setMaximumWidth(maxwidth) - def retranslateTray(self,widget=None): + def retranslateTray(self, widget=None): self.styleButton.setToolTip(translate("draft", "Changes the default style for new objects")) self.constrButton.setToolTip(translate("draft", "Toggles construction mode")) self.autoGroupButton.setToolTip(translate("draft", "Autogroup off")) - -#--------------------------------------------------------------------------- -# Interface modes -#--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + # Interface modes + # --------------------------------------------------------------------------- def _show_dialog(self, panel): task = FreeCADGui.Control.showDialog(panel) task.setDocumentName(FreeCADGui.ActiveDocument.Document.Name) task.setAutoCloseOnDeletedDocument(True) - def taskUi(self,title="Draft", extra=None, icon="Draft_Draft"): + def taskUi(self, title="Draft", extra=None, icon="Draft_Draft"): # reset InputField values self.reset_ui_values() self.isTaskOn = True @@ -663,37 +772,34 @@ class DraftToolBar: else: axis = WorkingPlane.get_working_plane(update=False).axis constraint_dir = FreeCAD.Vector( - 1 if f == "x" else 0, - 1 if f == "y" else 0, - 1 if f == "z" else 0 + 1 if f == "x" else 0, 1 if f == "y" else 0, 1 if f == "z" else 0 ) # Using a high tolerance: - if axis.isEqual(constraint_dir, 0.1) \ - or axis.isEqual(-constraint_dir, 0.1): + if axis.isEqual(constraint_dir, 0.1) or axis.isEqual(-constraint_dir, 0.1): force_xyz = True if not force_xyz and params.get_param("focusOnLength") and self.lengthValue.isVisible(): self.lengthValue.setFocus() - self.lengthValue.setSelection(0,self.number_length(self.lengthValue.text())) + self.lengthValue.setSelection(0, self.number_length(self.lengthValue.text())) elif not force_xyz and self.angleLock.isVisible() and self.angleLock.isChecked(): self.lengthValue.setFocus() - self.lengthValue.setSelection(0,self.number_length(self.lengthValue.text())) + self.lengthValue.setSelection(0, self.number_length(self.lengthValue.text())) elif f == "x": self.xValue.setFocus() - self.xValue.setSelection(0,self.number_length(self.xValue.text())) + self.xValue.setSelection(0, self.number_length(self.xValue.text())) elif f == "y": self.yValue.setFocus() - self.yValue.setSelection(0,self.number_length(self.yValue.text())) + self.yValue.setSelection(0, self.number_length(self.yValue.text())) elif f == "z": self.zValue.setFocus() - self.zValue.setSelection(0,self.number_length(self.zValue.text())) + self.zValue.setSelection(0, self.number_length(self.zValue.text())) elif f == "radius": self.radiusValue.setFocus() - self.radiusValue.setSelection(0,self.number_length(self.radiusValue.text())) + self.radiusValue.setSelection(0, self.number_length(self.radiusValue.text())) else: # f is None self.xValue.setFocus() - self.xValue.setSelection(0,self.number_length(self.xValue.text())) + self.xValue.setSelection(0, self.number_length(self.xValue.text())) def number_length(self, str): nl = 0 @@ -703,7 +809,7 @@ class DraftToolBar: return nl def extraLineUi(self): - '''shows length and angle controls''' + """shows length and angle controls""" self.labellength.show() self.lengthValue.show() self.labelangle.show() @@ -712,7 +818,7 @@ class DraftToolBar: self.angleLock.setChecked(False) def hideXYZ(self): - ''' turn off all the point entry widgets ''' + """turn off all the point entry widgets""" self.labelx.hide() self.labely.hide() self.labelz.hide() @@ -728,16 +834,30 @@ class DraftToolBar: self.isRelative.hide() self.isGlobal.hide() - def lineUi(self, title=translate("draft", "Line"), cancel=None, extra=None, - getcoords=None,rel=False,icon="Draft_Line"): + def lineUi( + self, + title=translate("draft", "Line"), + cancel=None, + extra=None, + getcoords=None, + rel=False, + icon="Draft_Line", + ): self.pointUi(title, cancel, extra, getcoords, rel, icon) self.extraLineUi() self.xValue.setEnabled(True) self.yValue.setEnabled(True) self.continueCmd.show() - def wireUi(self, title=translate("draft", "DWire"), cancel=None, extra=None, - getcoords=None, rel=False, icon="Draft_Wire"): + def wireUi( + self, + title=translate("draft", "DWire"), + cancel=None, + extra=None, + getcoords=None, + rel=False, + icon="Draft_Wire", + ): self.pointUi(title, cancel, extra, getcoords, rel, icon) self.xValue.setEnabled(True) self.yValue.setEnabled(True) @@ -754,25 +874,34 @@ class DraftToolBar: self.continueCmd.show() def circleUi(self): - self.pointUi(translate("draft", "Circle"),icon="Draft_Circle") + self.pointUi(translate("draft", "Circle"), icon="Draft_Circle") self.extUi() self.isRelative.hide() def arcUi(self): - self.pointUi(translate("draft", "Arc"),icon="Draft_Arc") + self.pointUi(translate("draft", "Arc"), icon="Draft_Arc") self.continueCmd.show() self.isRelative.hide() def rotateSetCenterUi(self): - self.pointUi(translate("draft", "Rotate"),icon="Draft_Rotate") + self.pointUi(translate("draft", "Rotate"), icon="Draft_Rotate") self.modUi() self.isRelative.hide() - def pointUi(self, title=translate("draft","Point"), cancel=None, extra=None, - getcoords=None, rel=False, icon="Draft_Draft"): - if cancel: self.cancel = cancel - if getcoords: self.pointcallback = getcoords - self.taskUi(title,extra,icon) + def pointUi( + self, + title=translate("draft", "Point"), + cancel=None, + extra=None, + getcoords=None, + rel=False, + icon="Draft_Draft", + ): + if cancel: + self.cancel = cancel + if getcoords: + self.pointcallback = getcoords + self.taskUi(title, extra, icon) self.xValue.setEnabled(True) self.yValue.setEnabled(True) self.isRelative.show() @@ -785,24 +914,26 @@ class DraftToolBar: self.yValue.show() self.zValue.show() # reset UI to (0,0,0) on start - self.xValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) - self.yValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) - self.zValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.xValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) + self.yValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) + self.zValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.x = 0 self.y = 0 self.z = 0 self.new_point = None self.last_point = None self.pointButton.show() - if rel: self.isRelative.show() + if rel: + self.isRelative.show() todo.delay(self.setFocus, None) - def labelUi(self,title=translate("draft","Label"),callback=None): + def labelUi(self, title=translate("draft", "Label"), callback=None): w = QtWidgets.QWidget() - w.setWindowTitle(translate("draft","Label Type")) + w.setWindowTitle(translate("draft", "Label Type")) l = QtWidgets.QVBoxLayout(w) combo = QtWidgets.QComboBox() from draftobjects.label import get_label_types + types = get_label_types() for s in types: combo.addItem(translate("Draft", s), userData=s) @@ -815,18 +946,18 @@ class DraftToolBar: pass def offsetUi(self): - self.taskUi(translate("draft","Offset"), icon="Draft_Offset") + self.taskUi(translate("draft", "Offset"), icon="Draft_Offset") self.radiusUi() self.isCopy.show() self.isCopy.setChecked(params.get_param("OffsetCopyMode")) self.occOffset.show() - self.labelRadius.setText(translate("draft","Distance")) + self.labelRadius.setText(translate("draft", "Distance")) self.radiusValue.setToolTip(translate("draft", "Offset distance")) - self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.radiusValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) todo.delay(self.setFocus, "radius") def offUi(self): - todo.delay(FreeCADGui.Control.closeDialog,None) + todo.delay(FreeCADGui.Control.closeDialog, None) self.cancel = None self.sourceCmd = None self.pointcallback = None @@ -834,12 +965,12 @@ class DraftToolBar: self.isTaskOn = False self.baseWidget = QtWidgets.QWidget() - def trimUi(self,title=translate("draft","Trimex")): + def trimUi(self, title=translate("draft", "Trimex")): self.taskUi(title, icon="Draft_Trimex") self.radiusUi() - self.labelRadius.setText(translate("draft","Distance")) + self.labelRadius.setText(translate("draft", "Distance")) self.radiusValue.setToolTip(translate("draft", "Offset distance")) - self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.radiusValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) todo.delay(self.setFocus, "radius") def radiusUi(self): @@ -847,7 +978,7 @@ class DraftToolBar: self.labelRadius.setText(translate("draft", "Radius")) self.radiusValue.setToolTip(translate("draft", "Radius of Circle")) self.labelRadius.show() - self.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Length).UserString) + self.radiusValue.setText(FreeCAD.Units.Quantity(0, FreeCAD.Units.Length).UserString) self.radiusValue.show() todo.delay(self.setFocus, "radius") @@ -855,15 +986,15 @@ class DraftToolBar: self.hideXYZ() self.textValue.show() self.textOkButton.show() - self.textValue.setText('') - todo.delay(self.textValue.setFocus,None) - self.textbuffer=[] - self.textline=0 + self.textValue.setText("") + todo.delay(self.textValue.setFocus, None) + self.textbuffer = [] + self.textline = 0 self.continueCmd.show() # Change the checkbox label as the in-command shortcut cannot be used: self.continueCmd.setText(translate("draft", "Continue")) - def switchUi(self,store=True): + def switchUi(self, store=True): if store: self.state = [] self.state.append(self.labelx.isVisible()) @@ -875,19 +1006,25 @@ class DraftToolBar: self.hideXYZ() else: if self.state: - if self.state[0]:self.labelx.show() - if self.state[1]:self.labely.show() - if self.state[2]:self.labelz.show() - if self.state[3]:self.xValue.show() - if self.state[4]:self.yValue.show() - if self.state[5]:self.zValue.show() + if self.state[0]: + self.labelx.show() + if self.state[1]: + self.labely.show() + if self.state[2]: + self.labelz.show() + if self.state[3]: + self.xValue.show() + if self.state[4]: + self.yValue.show() + if self.state[5]: + self.zValue.show() self.state = None - def setTitle(self,title,icon="Draft_Draft"): + def setTitle(self, title, icon="Draft_Draft"): self.baseWidget.setWindowTitle(title) - self.baseWidget.setWindowIcon(QtGui.QIcon(":/icons/"+icon+".svg")) + self.baseWidget.setWindowIcon(QtGui.QIcon(":/icons/" + icon + ".svg")) - def selectUi(self,extra=None, on_close_call=None): + def selectUi(self, extra=None, on_close_call=None): self.makeDumbTask(extra, on_close_call) def editUi(self): @@ -910,7 +1047,9 @@ class DraftToolBar: def checkLocal(self): """checks if x,y,z coords must be displayed as local or global""" if not self.globalMode and self.relativeMode: - self.labelx.setText(translate("draft", "Local {}").format("\u0394X")) # \u0394 = ∆ (Greek delta) + self.labelx.setText( + translate("draft", "Local {}").format("\u0394X") + ) # \u0394 = ∆ (Greek delta) self.labely.setText(translate("draft", "Local {}").format("\u0394Y")) self.labelz.setText(translate("draft", "Local {}").format("\u0394Z")) elif not self.globalMode and not self.relativeMode: @@ -932,6 +1071,7 @@ class DraftToolBar: return True else: return False + if self.isTaskOn: if isThere(self.xValue): self.setFocus() @@ -947,28 +1087,35 @@ class DraftToolBar: def makeDumbTask(self, extra=None, on_close_call=None): """create a dumb taskdialog to prevent deleting the temp object""" + class TaskPanel: def __init__(self, extra=None, callback=None): if extra: self.form = [extra] self.callback = callback + def getStandardButtons(self): return QtWidgets.QDialogButtonBox.Close + def reject(self): if self.callback: self.callback() return True + todo.delay(FreeCADGui.Control.closeDialog, None) panel = TaskPanel(extra, on_close_call) todo.delay(self._show_dialog, panel) - -#--------------------------------------------------------------------------- -# Processing functions -#--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + # Processing functions + # --------------------------------------------------------------------------- def setContinue(self, val): - params.set_param(FreeCAD.activeDraftCommand.featureName, bool(getattr(val, "value", val)), "Mod/Draft/ContinueMode") + params.set_param( + FreeCAD.activeDraftCommand.featureName, + bool(getattr(val, "value", val)), + "Mod/Draft/ContinueMode", + ) self.continueMode = bool(getattr(val, "value", val)) self.chainedModeCmd.setEnabled(not bool(getattr(val, "value", val))) @@ -990,9 +1137,9 @@ class DraftToolBar: def setRelative(self, val=-1): val = getattr(val, "value", val) if val < 0: - if hasattr(self.isRelative, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.isRelative, "checkStateChanged"): # Qt version >= 6.7.0 self.isRelative.checkStateChanged.disconnect(self.setRelative) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.isRelative.stateChanged.disconnect(self.setRelative) if val == -1: self.isRelative.setChecked(True) @@ -1001,9 +1148,9 @@ class DraftToolBar: val = params.get_param("RelativeMode") self.isRelative.setChecked(val) self.relativeMode = val - if hasattr(self.isRelative, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.isRelative, "checkStateChanged"): # Qt version >= 6.7.0 self.isRelative.checkStateChanged.connect(self.setRelative) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.isRelative.stateChanged.connect(self.setRelative) else: params.set_param("RelativeMode", bool(val)) @@ -1040,7 +1187,7 @@ class DraftToolBar: def checkx(self): if self.yValue.isEnabled(): self.yValue.setFocus() - self.yValue.setSelection(0,self.number_length(self.yValue.text())) + self.yValue.setSelection(0, self.number_length(self.yValue.text())) self.updateSnapper() else: self.checky() @@ -1048,7 +1195,7 @@ class DraftToolBar: def checky(self): if self.zValue.isEnabled(): self.zValue.setFocus() - self.zValue.setSelection(0,self.number_length(self.zValue.text())) + self.zValue.setSelection(0, self.number_length(self.zValue.text())) self.updateSnapper() else: self.validatePoint() @@ -1056,7 +1203,7 @@ class DraftToolBar: def checklength(self): if self.angleValue.isEnabled(): self.angleValue.setFocus() - self.angleValue.setSelection(0,self.number_length(self.angleValue.text())) + self.angleValue.setSelection(0, self.number_length(self.angleValue.text())) self.updateSnapper() else: self.validatePoint() @@ -1124,15 +1271,15 @@ class DraftToolBar: def selectEdge(self): """allows the dimension command to select an edge""" - if hasattr(self.sourceCmd,"selectEdge"): + if hasattr(self.sourceCmd, "selectEdge"): self.sourceCmd.selectEdge() def undoSegment(self): """undo last line segment""" - if hasattr(self.sourceCmd,"undolast"): + if hasattr(self.sourceCmd, "undolast"): self.sourceCmd.undolast() - def checkSpecialChars(self,txt): + def checkSpecialChars(self, txt): """checks for special characters in the entered coords that must be treated as shortcuts """ @@ -1188,11 +1335,11 @@ class DraftToolBar: if self.closeButton.isVisible(): self.closeLine() elif txt == _get_incmd_shortcut("AddHold"): - if hasattr(FreeCADGui,"Snapper"): + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.addHoldPoint() spec = True elif txt == _get_incmd_shortcut("Recenter"): - if hasattr(FreeCADGui,"Snapper"): + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.recenter_workingplane() spec = True elif txt == _get_incmd_shortcut("Snap"): @@ -1237,7 +1384,7 @@ class DraftToolBar: value = getattr(self, field["value"]) unit = getattr(FreeCAD.Units, field["unit"]) v = FreeCAD.Units.Quantity(value, unit).getUserPreferred()[0] - widget.setProperty("text",v) + widget.setProperty("text", v) widget.setFocus() widget.selectAll() self.updateSnapper() @@ -1246,9 +1393,11 @@ class DraftToolBar: """updates the snapper track line if applicable""" if not self.xValue.isVisible(): return - if hasattr(FreeCADGui,"Snapper") \ - and FreeCADGui.Snapper.trackLine \ - and FreeCADGui.Snapper.trackLine.Visible: + if ( + hasattr(FreeCADGui, "Snapper") + and FreeCADGui.Snapper.trackLine + and FreeCADGui.Snapper.trackLine.Visible + ): point = self.get_new_point(FreeCAD.Vector(self.x, self.y, self.z)) FreeCADGui.Snapper.trackLine.p2(point) @@ -1268,8 +1417,7 @@ class DraftToolBar: self.mouse = False recorded_input_start = self.mouse_delay_input_start QtCore.QTimer.singleShot( - delay * 1000, - lambda: self.setMouseMode(True, recorded_input_start) + delay * 1000, lambda: self.setMouseMode(True, recorded_input_start) ) def checkEnterText(self): @@ -1282,11 +1430,13 @@ class DraftToolBar: """this function sends the entered text to the active draft command if enter has been pressed twice. Otherwise it blanks the line. """ - self.sourceCmd.text = self.textValue.toPlainText()\ - .replace("\\","\\\\")\ - .replace("\"","\\\"")\ - .replace("\'","\\\'")\ + self.sourceCmd.text = ( + self.textValue.toPlainText() + .replace("\\", "\\\\") + .replace('"', '\\"') + .replace("'", "\\'") .splitlines() + ) self.sourceCmd.createObject() def displayPoint(self, point=None, last=None, plane=None, mask=None): @@ -1328,11 +1478,11 @@ class DraftToolBar: self.lvalue = length self.avalue = phi - self.xValue.setText(display_external(delta.x,None,'Length')) - self.yValue.setText(display_external(delta.y,None,'Length')) - self.zValue.setText(display_external(delta.z,None,'Length')) - self.lengthValue.setText(display_external(length,None,'Length')) - self.angleValue.setText(display_external(phi,None,'Angle')) + self.xValue.setText(display_external(delta.x, None, "Length")) + self.yValue.setText(display_external(delta.y, None, "Length")) + self.zValue.setText(display_external(delta.z, None, "Length")) + self.lengthValue.setText(display_external(length, None, "Length")) + self.angleValue.setText(display_external(phi, None, "Angle")) # set masks if (mask == "x") or (self.mask == "x"): @@ -1370,7 +1520,9 @@ class DraftToolBar: if typ == "snap": r, g, b, _ = utils.get_rgba_tuple(params.get_param("snapcolor")) elif typ == "ui": - print("draft: deprecation warning: Do not use getDefaultColor(\"ui\") anymore - use getDefaultColor(\"line\") instead.") + print( + 'draft: deprecation warning: Do not use getDefaultColor("ui") anymore - use getDefaultColor("line") instead.' + ) r = float(self.color.red() / 255.0) g = float(self.color.green() / 255.0) b = float(self.color.blue() / 255.0) @@ -1385,36 +1537,40 @@ class DraftToolBar: else: print("draft: error: couldn't get a color for ", typ, " typ.") if rgb: - return("rgb(" + str(int(r * 255)) + "," + str(int(g * 255)) + "," + str(int(b * 255)) + ")") + return ( + "rgb(" + str(int(r * 255)) + "," + str(int(g * 255)) + "," + str(int(b * 255)) + ")" + ) else: - return (r,g,b) + return (r, g, b) - def cross(self,on=True): + def cross(self, on=True): """deprecated""" pass - def toggleConstrMode(self,checked): + def toggleConstrMode(self, checked): self.baseWidget.setStyleSheet( "#constrButton:Checked {background-color: " - + self.getDefaultColor("constr",rgb=True)+" }") + + self.getDefaultColor("constr", rgb=True) + + " }" + ) self.constrMode = checked def toggleContinue(self): FreeCAD.Console.PrintMessage("toggle continue\n") self.continueMode = not self.continueMode try: - if hasattr(self,"continueCmd"): + if hasattr(self, "continueCmd"): if self.continueCmd.isVisible(): self.continueCmd.toggle() - if hasattr(self,"panel"): - if hasattr(self.panel,"form"): - if isinstance(self.panel.form,list): + if hasattr(self, "panel"): + if hasattr(self.panel, "form"): + if isinstance(self.panel.form, list): for w in self.panel.form: - c = w.findChild(QtWidgets.QCheckBox,"ContinueCmd") + c = w.findChild(QtWidgets.QCheckBox, "ContinueCmd") if c: c.toggle() else: - c = self.panel.form.findChild(QtWidgets.QCheckBox,"ContinueCmd") + c = self.panel.form.findChild(QtWidgets.QCheckBox, "ContinueCmd") if c: c.toggle() except Exception: @@ -1433,22 +1589,25 @@ class DraftToolBar: "sets icon and text on the style button" linecolor = QtGui.QColor(utils.rgba_to_argb(params.get_param_view("DefaultShapeLineColor"))) facecolor = QtGui.QColor(utils.rgba_to_argb(params.get_param_view("DefaultShapeColor"))) - im = QtGui.QImage(32,32,QtGui.QImage.Format_ARGB32) + im = QtGui.QImage(32, 32, QtGui.QImage.Format_ARGB32) im.fill(QtCore.Qt.transparent) pt = QtGui.QPainter(im) pt.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine, QtCore.Qt.FlatCap)) pt.setBrush(QtGui.QBrush(linecolor, QtCore.Qt.SolidPattern)) - pts = [QtCore.QPointF(4.0,4.0), QtCore.QPointF(4.0,26.0), QtCore.QPointF(26.0,4.0)] + pts = [QtCore.QPointF(4.0, 4.0), QtCore.QPointF(4.0, 26.0), QtCore.QPointF(26.0, 4.0)] pt.drawPolygon(pts, QtCore.Qt.OddEvenFill) pt.setBrush(QtGui.QBrush(facecolor, QtCore.Qt.SolidPattern)) - pts = [QtCore.QPointF(28.0,28.0),QtCore.QPointF(8.0,28.0),QtCore.QPointF(28.0,8.0)] - pt.drawPolygon(pts,QtCore.Qt.OddEvenFill) + pts = [QtCore.QPointF(28.0, 28.0), QtCore.QPointF(8.0, 28.0), QtCore.QPointF(28.0, 8.0)] + pt.drawPolygon(pts, QtCore.Qt.OddEvenFill) pt.end() icon = QtGui.QIcon(QtGui.QPixmap.fromImage(im)) linewidth = params.get_param_view("DefaultShapeLineWidth") fontsize = params.get_param("textheight") - txt = str(linewidth) + "px | "\ - + FreeCAD.Units.Quantity(fontsize,FreeCAD.Units.Length).UserString + txt = ( + str(linewidth) + + "px | " + + FreeCAD.Units.Quantity(fontsize, FreeCAD.Units.Length).UserString + ) self.styleButton.setIcon(icon) self.styleButton.setText(txt) @@ -1458,17 +1617,17 @@ class DraftToolBar: self.linewidth = linewidth self.fontsize = fontsize - def popupMenu(self,llist,ilist=None,pos=None): + def popupMenu(self, llist, ilist=None, pos=None): """pops up a menu filled with the given list "---" in llist inserts a separator """ self.groupmenu = QtWidgets.QMenu() - for i,l in enumerate(llist): + for i, l in enumerate(llist): if "---" in l: self.groupmenu.addSeparator() elif ilist: - self.groupmenu.addAction(ilist[i],l) + self.groupmenu.addAction(ilist[i], l) else: self.groupmenu.addAction(l) if not pos: @@ -1476,15 +1635,15 @@ class DraftToolBar: self.groupmenu.popup(pos) self.groupmenu.triggered.connect(self.popupTriggered) - def getIcon(self,iconpath): + def getIcon(self, iconpath): return QtGui.QIcon(iconpath) - def popupTriggered(self,action): + def popupTriggered(self, action): self.sourceCmd.proceed(str(action.text())) - def setRadiusValue(self,val,unit=None): + def setRadiusValue(self, val, unit=None): # print("DEBUG: setRadiusValue val: ", val, " unit: ", unit) - if not isinstance(val, (int, float)): # some code passes strings + if not isinstance(val, (int, float)): # some code passes strings t = val elif unit: t = display_external(val, None, unit) @@ -1496,12 +1655,15 @@ class DraftToolBar: def runAutoGroup(self): FreeCADGui.runCommand("Draft_AutoGroup") - def setAutoGroup(self,value=None): + def setAutoGroup(self, value=None): if value is None: self.autogroup = None self.autoGroupButton.setText(translate("draft", "None")) - self.autoGroupButton.setIcon(QtGui.QIcon.fromTheme('Draft_AutoGroup_off', - QtGui.QIcon(':/icons/button_invalid.svg'))) + self.autoGroupButton.setIcon( + QtGui.QIcon.fromTheme( + "Draft_AutoGroup_off", QtGui.QIcon(":/icons/button_invalid.svg") + ) + ) self.autoGroupButton.setToolTip(translate("draft", "Autogroup off")) self.autoGroupButton.setDown(False) else: @@ -1515,41 +1677,44 @@ class DraftToolBar: else: self.autogroup = None self.autoGroupButton.setText(translate("draft", "None")) - self.autoGroupButton.setIcon(QtGui.QIcon.fromTheme('Draft_AutoGroup_off', - QtGui.QIcon(':/icons/button_invalid.svg'))) + self.autoGroupButton.setIcon( + QtGui.QIcon.fromTheme( + "Draft_AutoGroup_off", QtGui.QIcon(":/icons/button_invalid.svg") + ) + ) self.autoGroupButton.setToolTip(translate("draft", "Autogroup off")) self.autoGroupButton.setDown(False) - def getXPM(self,iconname,size=16): - i = QtGui.QIcon(":/icons/"+iconname+".svg") - p = i.pixmap(size,size) + def getXPM(self, iconname, size=16): + i = QtGui.QIcon(":/icons/" + iconname + ".svg") + p = i.pixmap(size, size) a = QtCore.QByteArray() b = QtCore.QBuffer(a) b.open(QtCore.QIODevice.WriteOnly) - p.save(b,"XPM") + p.save(b, "XPM") b.close() return str(a) def togglesnap(self): FreeCADGui.doCommand('FreeCADGui.runCommand("Draft_Snap_Lock")') - def toggleradius(self,val): - if hasattr(FreeCADGui,"Snapper"): + def toggleradius(self, val): + if hasattr(FreeCADGui, "Snapper"): par = params.get_param("snapRange") - params.set_param("snapRange", max(0, par+val)) + params.set_param("snapRange", max(0, par + val)) FreeCADGui.Snapper.showradius() - def constrain(self,val): + def constrain(self, val): if val == "angle": - self.alock = not(self.alock) + self.alock = not (self.alock) self.angleLock.setChecked(self.alock) elif self.mask == val: self.mask = None - if hasattr(FreeCADGui,"Snapper"): + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.mask = None else: self.mask = val - if hasattr(FreeCADGui,"Snapper"): + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.mask = val self.new_point = FreeCADGui.Snapper.constrain(self.new_point, self.get_last_point()) @@ -1612,7 +1777,7 @@ class DraftToolBar: angle_vec = self.angle FreeCADGui.Snapper.setAngle(angle_vec) - def toggleAngle(self,b): + def toggleAngle(self, b): self.alock = self.angleLock.isChecked() self.update_cartesian_coords() self.updateSnapper() @@ -1628,24 +1793,26 @@ class DraftToolBar: self.angle = None def update_spherical_coords(self): - length, theta, phi = DraftVecUtils.get_spherical_coords( - self.x,self.y,self.z) + length, theta, phi = DraftVecUtils.get_spherical_coords(self.x, self.y, self.z) self.lvalue = length self.pvalue = math.degrees(theta) self.avalue = math.degrees(phi) - self.angle = FreeCAD.Vector(DraftVecUtils.get_cartesian_coords( - 1, theta, phi)) - self.lengthValue.setText(display_external(self.lvalue,None,'Length')) - self.angleValue.setText(display_external(self.avalue,None,'Angle')) + self.angle = FreeCAD.Vector(DraftVecUtils.get_cartesian_coords(1, theta, phi)) + self.lengthValue.setText(display_external(self.lvalue, None, "Length")) + self.angleValue.setText(display_external(self.avalue, None, "Angle")) def update_cartesian_coords(self): self.x, self.y, self.z = DraftVecUtils.get_cartesian_coords( - self.lvalue,math.radians(self.pvalue),math.radians(self.avalue)) - self.angle = FreeCAD.Vector(DraftVecUtils.get_cartesian_coords( - 1, math.radians(self.pvalue), math.radians(self.avalue))) - self.xValue.setText(display_external(self.x,None,'Length')) - self.yValue.setText(display_external(self.y,None,'Length')) - self.zValue.setText(display_external(self.z,None,'Length')) + self.lvalue, math.radians(self.pvalue), math.radians(self.avalue) + ) + self.angle = FreeCAD.Vector( + DraftVecUtils.get_cartesian_coords( + 1, math.radians(self.pvalue), math.radians(self.avalue) + ) + ) + self.xValue.setText(display_external(self.x, None, "Length")) + self.yValue.setText(display_external(self.y, None, "Length")) + self.zValue.setText(display_external(self.z, None, "Length")) def get_last_point(self): """Get the last point in the GCS.""" @@ -1673,51 +1840,70 @@ class DraftToolBar: base_point = self.get_last_point() return base_point + delta -#--------------------------------------------------------------------------- -# TaskView operations -#--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + # TaskView operations + # --------------------------------------------------------------------------- def setWatchers(self): class DraftCreateWatcher: def __init__(self): - self.commands = ["Draft_Line","Draft_Wire", - "Draft_Rectangle","Draft_Arc", - "Draft_Circle","Draft_BSpline", - "Draft_Text","Draft_Dimension", - "Draft_ShapeString","Draft_BezCurve"] + self.commands = [ + "Draft_Line", + "Draft_Wire", + "Draft_Rectangle", + "Draft_Arc", + "Draft_Circle", + "Draft_BSpline", + "Draft_Text", + "Draft_Dimension", + "Draft_ShapeString", + "Draft_BezCurve", + ] self.title = "Create objects" + def shouldShow(self): - return (FreeCAD.ActiveDocument is not None) and (not FreeCADGui.Selection.getSelection()) + return (FreeCAD.ActiveDocument is not None) and ( + not FreeCADGui.Selection.getSelection() + ) class DraftModifyWatcher: def __init__(self): - self.commands = ["Draft_Move","Draft_Rotate", - "Draft_Scale","Draft_Offset", - "Draft_Trimex","Draft_Upgrade", - "Draft_Downgrade","Draft_Edit"] + self.commands = [ + "Draft_Move", + "Draft_Rotate", + "Draft_Scale", + "Draft_Offset", + "Draft_Trimex", + "Draft_Upgrade", + "Draft_Downgrade", + "Draft_Edit", + ] self.title = translate("draft", "Modify Objects") - def shouldShow(self): - return (FreeCAD.ActiveDocument is not None) and (FreeCADGui.Selection.getSelection() != []) - FreeCADGui.Control.addTaskWatcher([DraftCreateWatcher(),DraftModifyWatcher()]) + def shouldShow(self): + return (FreeCAD.ActiveDocument is not None) and ( + FreeCADGui.Selection.getSelection() != [] + ) + + FreeCADGui.Control.addTaskWatcher([DraftCreateWatcher(), DraftModifyWatcher()]) def changeEvent(self, event): if event.type() == QtCore.QEvent.LanguageChange: - #print("Language changed!") + # print("Language changed!") self.ui.retranslateUi(self) def Activated(self): self.setWatchers() - if hasattr(self,"tray"): + if hasattr(self, "tray"): todo.delay(self.tray.show, None) def Deactivated(self): - if (FreeCAD.activeDraftCommand is not None): + if FreeCAD.activeDraftCommand is not None: self.continueMode = False FreeCAD.activeDraftCommand.finish() FreeCADGui.Control.clearTaskWatcher() - #self.tray = None - if hasattr(self,"tray"): + # self.tray = None + if hasattr(self, "tray"): todo.delay(self.tray.hide, None) def reset_ui_values(self): @@ -1736,7 +1922,8 @@ class DraftToolBar: class FacebinderTaskPanel: - '''A TaskPanel for the facebinder''' + """A TaskPanel for the facebinder""" + def __init__(self): self.obj = None @@ -1751,7 +1938,7 @@ class FacebinderTaskPanel: self.tree = QtWidgets.QTreeWidget(self.form) self.grid.addWidget(self.tree, 1, 0, 1, 2) self.tree.setColumnCount(2) - self.tree.setHeaderLabels(["Name","Subelement"]) + self.tree.setHeaderLabels(["Name", "Subelement"]) # buttons self.addButton = QtWidgets.QPushButton(self.form) @@ -1782,17 +1969,17 @@ class FacebinderTaskPanel: self.tree.clear() if self.obj: for f in self.obj.Faces: - if isinstance(f[1],tuple): + if isinstance(f[1], tuple): for subf in f[1]: item = QtWidgets.QTreeWidgetItem(self.tree) - item.setText(0,f[0].Name) + item.setText(0, f[0].Name) item.setIcon(0, QtGui.QIcon(":/icons/Part_3D_object.svg")) - item.setText(1,subf) + item.setText(1, subf) else: item = QtWidgets.QTreeWidgetItem(self.tree) - item.setText(0,f[0].Name) + item.setText(0, f[0].Name) item.setIcon(0, QtGui.QIcon(":/icons/Part_3D_object.svg")) - item.setText(1,f[1]) + item.setText(1, f[1]) self.retranslateUi(self.form) def addElement(self): @@ -1805,16 +1992,16 @@ class FacebinderTaskPanel: flist = self.obj.Faces found = False for face in flist: - if (face[0] == obj.Name): - if isinstance(face[1],tuple): + if face[0] == obj.Name: + if isinstance(face[1], tuple): for subf in face[1]: if subf == elt: found = True else: - if (face[1] == elt): + if face[1] == elt: found = True if not found: - flist.append((obj,elt)) + flist.append((obj, elt)) self.obj.Faces = flist FreeCAD.ActiveDocument.recompute() self.update() @@ -1827,15 +2014,15 @@ class FacebinderTaskPanel: elt = str(it.text(1)) flist = [] for face in self.obj.Faces: - if (face[0].Name != obj.Name): + if face[0].Name != obj.Name: flist.append(face) else: - if isinstance(face[1],tuple): + if isinstance(face[1], tuple): for subf in face[1]: if subf != elt: - flist.append((obj,subf)) + flist.append((obj, subf)) else: - if (face[1] != elt): + if face[1] != elt: flist.append(face) self.obj.Faces = flist FreeCAD.ActiveDocument.recompute() @@ -1852,7 +2039,8 @@ class FacebinderTaskPanel: self.addButton.setText(QtWidgets.QApplication.translate("draft", "Add", None)) self.title.setText(QtWidgets.QApplication.translate("draft", "Facebinder Elements", None)) -#def translateWidget(w, context=None, disAmb=None): + +# def translateWidget(w, context=None, disAmb=None): # '''translator for items where retranslateUi() is unavailable. # translates widget w and children.''' # #handle w itself @@ -1889,6 +2077,6 @@ class FacebinderTaskPanel: ## msg = "TranslateWidget: Can not translate widget: {0} type: {1}\n".format(w.objectName(),w.metaObject().className()) ## FreeCAD.Console.PrintMessage(msg) -if not hasattr(FreeCADGui,"draftToolBar"): +if not hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar = DraftToolBar() -#----End of Python Features Definitions----# +# ----End of Python Features Definitions----# diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index a767de16ba..fa5ba57d86 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -61,8 +61,7 @@ True if Draft_rc.__name__ else False True if DraftGui.__name__ else False __title__ = "FreeCAD Draft Workbench GUI Tools" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin") +__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin" __url__ = "https://www.freecad.org" if not hasattr(FreeCADGui, "Snapper"): diff --git a/src/Mod/Draft/DraftVecUtils.py b/src/Mod/Draft/DraftVecUtils.py index 57c83f612b..8bd3edb24e 100644 --- a/src/Mod/Draft/DraftVecUtils.py +++ b/src/Mod/Draft/DraftVecUtils.py @@ -50,6 +50,7 @@ __url__ = "https://www.freecad.org" ## \addtogroup DRAFTVECUTILS # @{ + # @deprecated("use Draft.precision() instead.") def precision(): """ @@ -65,11 +66,16 @@ def precision(): Return the number of fractional decimal digits as configured in Draft preferences. """ - warnings.warn("Call to deprecated function 'DraftVecUtils.precision()'." - + " Please consider using Draft.precision().", - DeprecationWarning, stacklevel=2) - messages._wrn("DraftVecUtils.precision() called, which is deprecated." - + " Please consider using Draft.precision(). ") + warnings.warn( + "Call to deprecated function 'DraftVecUtils.precision()'." + + " Please consider using Draft.precision().", + DeprecationWarning, + stacklevel=2, + ) + messages._wrn( + "DraftVecUtils.precision() called, which is deprecated." + + " Please consider using Draft.precision(). " + ) return draft_precision() @@ -237,7 +243,7 @@ def scale(u, scalar): The new vector with each of its elements multiplied by `scalar`. """ typecheck([(u, Vector), (scalar, (int, int, float))], "scale") - return Vector(u.x*scalar, u.y*scalar, u.z*scalar) + return Vector(u.x * scalar, u.y * scalar, u.z * scalar) def scaleTo(u, l): @@ -270,8 +276,8 @@ def scaleTo(u, l): if u.Length == 0: return Vector(u) else: - a = l/u.Length - return Vector(u.x*a, u.y*a, u.z*a) + a = l / u.Length + return Vector(u.x * a, u.y * a, u.z * a) def dist(u, v): @@ -338,7 +344,7 @@ def angle(u, v=Vector(1, 0, 0), normal=Vector(0, 0, 1)): return 0 # The dot product indicates the projection of one vector over the other - dp = u.dot(v)/ll + dp = u.dot(v) / ll # Due to rounding errors, the dot product could be outside # the range [-1, 1], so let's force it to be within this range. @@ -390,7 +396,7 @@ def project(u, v): return Vector(0, 0, 0) # to avoid division by zero # Why specifically this value? This should be an else? if dp != 15: - return scale(v, u.dot(v)/dp) + return scale(v, u.dot(v) / dp) # Return a null vector if the magnitude squared is 15, why? return Vector(0, 0, 0) @@ -476,9 +482,9 @@ def rotate(u, angle, axis=Vector(0, 0, 1)): # Unit components, so that x**2 + y**2 + z**2 = 1 L = axis.Length - x = axis.x/L - y = axis.y/L - z = axis.z/L + x = axis.x / L + y = axis.y / L + z = axis.z / L c = math.cos(angle) s = math.sin(angle) @@ -571,7 +577,7 @@ def isNull(vector, precision=None): x = round(vector.x, precision) y = round(vector.y, precision) z = round(vector.z, precision) - return (x == 0 and y == 0 and z == 0) + return x == 0 and y == 0 and z == 0 def find(vector, vlist, precision=None): @@ -724,7 +730,7 @@ def isColinear(vlist, precision=None): return True -def rounded(v,precision=None): +def rounded(v, precision=None): """Return a vector rounded to the `precision` in the parameter database or to the given decimals value @@ -736,7 +742,7 @@ def rounded(v,precision=None): v : Base::Vector3 The input vector. precision : int | None - mathematical precision - if None use configured draft + mathematical precision - if None use configured draft precision @@ -752,7 +758,7 @@ def rounded(v,precision=None): return Vector(round(v.x, precision), round(v.y, precision), round(v.z, precision)) -def getPlaneRotation(u, v, _ = None): +def getPlaneRotation(u, v, _=None): """Return a rotation matrix defining the (u,v,w) coordinate system. The rotation matrix uses the elements from each vector. @@ -840,12 +846,13 @@ def removeDoubles(vlist, precision=None): # Iterate until the penultimate element, and test for equality # with the element in front for i in range(len(vlist) - 1): - if not equals(vlist[i], vlist[i+1], precision): + if not equals(vlist[i], vlist[i + 1], precision): nlist.append(vlist[i]) # Add the last element nlist.append(vlist[-1]) return nlist + def get_spherical_coords(x, y, z, precision=None): """Get the Spherical coordinates of the vector represented by Cartesian coordinates (x, y, z). @@ -853,7 +860,7 @@ def get_spherical_coords(x, y, z, precision=None): Parameters ---------- vector : Base::Vector3 - The input vector. + The input vector. precision : int | None mathematical precision - if None use configured draft precision @@ -877,23 +884,23 @@ def get_spherical_coords(x, y, z, precision=None): if precision is None: precision = params.get_param("precision") - v = Vector(x,y,z) - x_axis = Vector(1,0,0) - z_axis = Vector(0,0,1) - y_axis = Vector(0,1,0) + v = Vector(x, y, z) + x_axis = Vector(1, 0, 0) + z_axis = Vector(0, 0, 1) + y_axis = Vector(0, 1, 0) rad = v.Length if not bool(round(rad, precision)): - return (0, math.pi/2, 0) + return (0, math.pi / 2, 0) theta = v.getAngle(z_axis) - v.projectToPlane(Vector(0,0,0), z_axis) + v.projectToPlane(Vector(0, 0, 0), z_axis) phi = v.getAngle(x_axis) if math.isnan(phi): return (rad, theta, 0) # projected vector is on 3rd or 4th quadrant if v.dot(Vector(y_axis)) < 0: - phi = -1*phi + phi = -1 * phi return (rad, theta, phi) @@ -917,9 +924,9 @@ def get_cartesian_coords(radius, theta, phi): Tuple (x, y, z) with the Cartesian coordinates. """ - x = radius*math.sin(theta)*math.cos(phi) - y = radius*math.sin(theta)*math.sin(phi) - z = radius*math.cos(theta) + x = radius * math.sin(theta) * math.cos(phi) + y = radius * math.sin(theta) * math.sin(phi) + z = radius * math.cos(theta) return (x, y, z) diff --git a/src/Mod/Draft/DxfImportDialog.py b/src/Mod/Draft/DxfImportDialog.py index c260b6fd92..bd9a992b04 100644 --- a/src/Mod/Draft/DxfImportDialog.py +++ b/src/Mod/Draft/DxfImportDialog.py @@ -2,10 +2,12 @@ import FreeCAD import FreeCADGui from PySide import QtCore, QtGui + class DxfImportDialog: """ A controller class that creates, manages, and shows the DXF import dialog. """ + def __init__(self, entity_counts, parent=None): # Step 1: Load the UI from the resource file. This returns a new QDialog instance. self.dialog = FreeCADGui.PySideUic.loadUi(":/ui/preferences-dxf-import.ui") @@ -21,7 +23,9 @@ class DxfImportDialog: def setup_ui(self): """Perform initial UI setup.""" - self.dialog.label_Summary.setText(f"File contains approximately {self.total_entities} geometric entities.") + self.dialog.label_Summary.setText( + f"File contains approximately {self.total_entities} geometric entities." + ) self.dialog.label_Warning.hide() def connect_signals(self): @@ -42,14 +46,18 @@ class DxfImportDialog: def on_accept(self): """Custom slot to debug the OK button click.""" - FreeCAD.Console.PrintLog("DxfImportDialog: 'OK' button clicked. Calling self.dialog.accept().\n") + FreeCAD.Console.PrintLog( + "DxfImportDialog: 'OK' button clicked. Calling self.dialog.accept().\n" + ) # Manually call the original slot self.dialog.accept() FreeCAD.Console.PrintLog("DxfImportDialog: self.dialog.accept() has been called.\n") def on_reject(self): """Custom slot to debug the Cancel button click.""" - FreeCAD.Console.PrintLog("DxfImportDialog: 'Cancel' button clicked. Calling self.dialog.reject().\n") + FreeCAD.Console.PrintLog( + "DxfImportDialog: 'Cancel' button clicked. Calling self.dialog.reject().\n" + ) # Manually call the original slot self.dialog.reject() FreeCAD.Console.PrintLog("DxfImportDialog: self.dialog.reject() has been called.\n") @@ -89,26 +97,40 @@ class DxfImportDialog: current_mode = self.get_selected_mode() if self.total_entities > 5000 and (current_mode == 0 or current_mode == 1): - self.dialog.label_Warning.setText("Warning: Importing over 5000 entities as editable objects can be very slow.") + self.dialog.label_Warning.setText( + "Warning: Importing over 5000 entities as editable objects can be very slow." + ) self.dialog.label_Warning.show() elif self.total_entities > 20000 and current_mode == 2: - self.dialog.label_Warning.setText("Warning: Importing over 20,000 entities as individual shapes may be slow.") + self.dialog.label_Warning.setText( + "Warning: Importing over 20,000 entities as individual shapes may be slow." + ) self.dialog.label_Warning.show() def exec_(self): FreeCAD.Console.PrintLog("DxfImportDialog: Calling self.dialog.exec_()...\n") result = self.dialog.exec_() - FreeCAD.Console.PrintLog("DxfImportDialog: self.dialog.exec_() returned with result: {}\n".format(result)) + FreeCAD.Console.PrintLog( + "DxfImportDialog: self.dialog.exec_() returned with result: {}\n".format(result) + ) # QDialog.Accepted is usually 1, Rejected is 0. - FreeCAD.Console.PrintLog("(Note: QDialog.Accepted = {}, QDialog.Rejected = {})\n".format(QtGui.QDialog.Accepted, QtGui.QDialog.Rejected)) + FreeCAD.Console.PrintLog( + "(Note: QDialog.Accepted = {}, QDialog.Rejected = {})\n".format( + QtGui.QDialog.Accepted, QtGui.QDialog.Rejected + ) + ) return result def get_selected_mode(self): """Return the integer value of the selected import mode.""" - if self.dialog.radio_ImportAs_Draft.isChecked(): return 0 - if self.dialog.radio_ImportAs_Primitives.isChecked(): return 1 - if self.dialog.radio_ImportAs_Fused.isChecked(): return 3 - if self.dialog.radio_ImportAs_Shapes.isChecked(): return 2 + if self.dialog.radio_ImportAs_Draft.isChecked(): + return 0 + if self.dialog.radio_ImportAs_Primitives.isChecked(): + return 1 + if self.dialog.radio_ImportAs_Fused.isChecked(): + return 3 + if self.dialog.radio_ImportAs_Shapes.isChecked(): + return 2 return 2 def get_show_dialog_again(self): diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 7f014ea05c..8a7c7d0711 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -39,9 +39,7 @@ class DraftWorkbench(FreeCADGui.Workbench): __dirname__ = os.path.join(FreeCAD.getResourceDir(), "Mod", "Draft") _tooltip = "The Draft workbench is used for 2D drafting on a grid" - self.__class__.Icon = os.path.join(__dirname__, - "Resources", "icons", - "DraftWorkbench.svg") + self.__class__.Icon = os.path.join(__dirname__, "Resources", "icons", "DraftWorkbench.svg") self.__class__.MenuText = QT_TRANSLATE_NOOP("draft", "Draft") self.__class__.ToolTip = QT_TRANSLATE_NOOP("draft", _tooltip) @@ -55,21 +53,26 @@ class DraftWorkbench(FreeCADGui.Workbench): dependencies_OK = False try: from pivy import coin + if FreeCADGui.getSoDBVersion() != coin.SoDB.getVersion(): - raise AssertionError("FreeCAD and Pivy use different versions " - "of Coin. " - "This will lead to unexpected behaviour.") + raise AssertionError( + "FreeCAD and Pivy use different versions " + "of Coin. " + "This will lead to unexpected behaviour." + ) except AssertionError: - FreeCAD.Console.PrintWarning("Error: FreeCAD and Pivy " - "use different versions of Coin. " - "This will lead to unexpected " - "behaviour.\n") + FreeCAD.Console.PrintWarning( + "Error: FreeCAD and Pivy " + "use different versions of Coin. " + "This will lead to unexpected " + "behaviour.\n" + ) except ImportError: - FreeCAD.Console.PrintWarning("Error: Pivy not found, " - "Draft Workbench will be disabled.\n") + FreeCAD.Console.PrintWarning( + "Error: Pivy not found, " "Draft Workbench will be disabled.\n" + ) except Exception: - FreeCAD.Console.PrintWarning("Error: Unknown error " - "while trying to load Pivy.\n") + FreeCAD.Console.PrintWarning("Error: Unknown error " "while trying to load Pivy.\n") else: dependencies_OK = True @@ -81,16 +84,20 @@ class DraftWorkbench(FreeCADGui.Workbench): import Draft_rc import DraftTools import DraftGui + FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addIconPath(":/icons") except Exception as exc: FreeCAD.Console.PrintError(exc) - FreeCAD.Console.PrintError("Error: Initializing one or more " - "of the Draft modules failed, " - "Draft will not work as expected.\n") + FreeCAD.Console.PrintError( + "Error: Initializing one or more " + "of the Draft modules failed, " + "Draft will not work as expected.\n" + ) # Set up command lists import draftutils.init_tools as it + self.drawing_commands = it.get_draft_drawing_commands() self.annotation_commands = it.get_draft_annotation_commands() self.modification_commands = it.get_draft_modification_commands() @@ -99,51 +106,60 @@ class DraftWorkbench(FreeCADGui.Workbench): self.context_commands = it.get_draft_context_commands() # Set up toolbars - it.init_toolbar(self, - QT_TRANSLATE_NOOP("Workbench", "Draft Creation"), - self.drawing_commands) - it.init_toolbar(self, - QT_TRANSLATE_NOOP("Workbench", "Draft Annotation"), - self.annotation_commands) - it.init_toolbar(self, - QT_TRANSLATE_NOOP("Workbench", "Draft Modification"), - self.modification_commands) - it.init_toolbar(self, - QT_TRANSLATE_NOOP("Workbench", "Draft Utility"), - self.utility_commands_toolbar) - it.init_toolbar(self, - QT_TRANSLATE_NOOP("Workbench", "Draft Snap"), - it.get_draft_snap_commands()) + it.init_toolbar( + self, QT_TRANSLATE_NOOP("Workbench", "Draft Creation"), self.drawing_commands + ) + it.init_toolbar( + self, QT_TRANSLATE_NOOP("Workbench", "Draft Annotation"), self.annotation_commands + ) + it.init_toolbar( + self, QT_TRANSLATE_NOOP("Workbench", "Draft Modification"), self.modification_commands + ) + it.init_toolbar( + self, QT_TRANSLATE_NOOP("Workbench", "Draft Utility"), self.utility_commands_toolbar + ) + it.init_toolbar( + self, QT_TRANSLATE_NOOP("Workbench", "Draft Snap"), it.get_draft_snap_commands() + ) # Set up menus - it.init_menu(self, - [QT_TRANSLATE_NOOP("Workbench", "&Drafting")], - self.drawing_commands) - it.init_menu(self, - [QT_TRANSLATE_NOOP("Workbench", "&Annotation")], - self.annotation_commands) - it.init_menu(self, - [QT_TRANSLATE_NOOP("Workbench", "&Modification")], - self.modification_commands) - it.init_menu(self, - [QT_TRANSLATE_NOOP("Workbench", "&Utilities")], - self.utility_commands_menu) + it.init_menu(self, [QT_TRANSLATE_NOOP("Workbench", "&Drafting")], self.drawing_commands) + it.init_menu( + self, [QT_TRANSLATE_NOOP("Workbench", "&Annotation")], self.annotation_commands + ) + it.init_menu( + self, [QT_TRANSLATE_NOOP("Workbench", "&Modification")], self.modification_commands + ) + it.init_menu( + self, [QT_TRANSLATE_NOOP("Workbench", "&Utilities")], self.utility_commands_menu + ) # Set up preferences pages if hasattr(FreeCADGui, "draftToolBar"): if not hasattr(FreeCADGui.draftToolBar, "loadedPreferences"): from draftutils import params + params._param_observer_start() - FreeCADGui.addPreferencePage(":/ui/preferences-draft.ui", QT_TRANSLATE_NOOP("QObject", "Draft")) - FreeCADGui.addPreferencePage(":/ui/preferences-draftinterface.ui", QT_TRANSLATE_NOOP("QObject", "Draft")) - FreeCADGui.addPreferencePage(":/ui/preferences-draftsnap.ui", QT_TRANSLATE_NOOP("QObject", "Draft")) - FreeCADGui.addPreferencePage(":/ui/preferences-draftvisual.ui", QT_TRANSLATE_NOOP("QObject", "Draft")) - FreeCADGui.addPreferencePage(":/ui/preferences-drafttexts.ui", QT_TRANSLATE_NOOP("QObject", "Draft")) + FreeCADGui.addPreferencePage( + ":/ui/preferences-draft.ui", QT_TRANSLATE_NOOP("QObject", "Draft") + ) + FreeCADGui.addPreferencePage( + ":/ui/preferences-draftinterface.ui", QT_TRANSLATE_NOOP("QObject", "Draft") + ) + FreeCADGui.addPreferencePage( + ":/ui/preferences-draftsnap.ui", QT_TRANSLATE_NOOP("QObject", "Draft") + ) + FreeCADGui.addPreferencePage( + ":/ui/preferences-draftvisual.ui", QT_TRANSLATE_NOOP("QObject", "Draft") + ) + FreeCADGui.addPreferencePage( + ":/ui/preferences-drafttexts.ui", QT_TRANSLATE_NOOP("QObject", "Draft") + ) FreeCADGui.draftToolBar.loadedPreferences = True FreeCADGui.getMainWindow().mainWindowClosed.connect(self.Deactivated) - FreeCAD.Console.PrintLog('Loading Draft workbench, done.\n') + FreeCAD.Console.PrintLog("Loading Draft workbench, done.\n") def Activated(self): """When entering the workbench.""" @@ -152,10 +168,13 @@ class DraftWorkbench(FreeCADGui.Workbench): if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.show() from draftutils import init_draft_statusbar + init_draft_statusbar.show_draft_statusbar() import WorkingPlane + WorkingPlane._view_observer_start() # Updates the draftToolBar when switching views. from draftutils import grid_observer + grid_observer._view_observer_setup() FreeCAD.Console.PrintLog("Draft workbench activated.\n") @@ -166,10 +185,13 @@ class DraftWorkbench(FreeCADGui.Workbench): if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.hide() from draftutils import init_draft_statusbar + init_draft_statusbar.hide_draft_statusbar() import WorkingPlane + WorkingPlane._view_observer_stop() from draftutils import grid_observer + grid_observer._view_observer_setup() FreeCAD.Console.PrintLog("Draft workbench deactivated.\n") @@ -186,7 +208,12 @@ class DraftWorkbench(FreeCADGui.Workbench): from draftguitools import gui_hyperlink hyperlinks_search = gui_hyperlink.Draft_Hyperlink() - if hyperlinks_search.has_hyperlinks() and sys.platform in ["win32", "cygwin", "darwin", "linux"]: + if hyperlinks_search.has_hyperlinks() and sys.platform in [ + "win32", + "cygwin", + "darwin", + "linux", + ]: self.appendContextMenu("", ["Draft_Hyperlink"]) self.appendContextMenu("Utilities", self.context_commands) @@ -202,9 +229,18 @@ FreeCADGui.addWorkbench(DraftWorkbench) # are independent of the loading of the workbench and can be loaded at startup import Draft_rc from PySide.QtCore import QT_TRANSLATE_NOOP -FreeCADGui.addPreferencePage(":/ui/preferences-dxf.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export")) -FreeCADGui.addPreferencePage(":/ui/preferences-dwg.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export")) -FreeCADGui.addPreferencePage(":/ui/preferences-svg.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export")) -FreeCADGui.addPreferencePage(":/ui/preferences-oca.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export")) + +FreeCADGui.addPreferencePage( + ":/ui/preferences-dxf.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export") +) +FreeCADGui.addPreferencePage( + ":/ui/preferences-dwg.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export") +) +FreeCADGui.addPreferencePage( + ":/ui/preferences-svg.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export") +) +FreeCADGui.addPreferencePage( + ":/ui/preferences-oca.ui", QT_TRANSLATE_NOOP("QObject", "Import-Export") +) FreeCAD.__unit_test__ += ["TestDraftGui"] diff --git a/src/Mod/Draft/Resources/ui/preferences-dxf-import.ui b/src/Mod/Draft/Resources/ui/preferences-dxf-import.ui index a6b6b883e6..41ceef7d97 100644 --- a/src/Mod/Draft/Resources/ui/preferences-dxf-import.ui +++ b/src/Mod/Draft/Resources/ui/preferences-dxf-import.ui @@ -151,4 +151,4 @@ shape. Best for viewing very large files with maximum performance. - \ No newline at end of file + diff --git a/src/Mod/Draft/SVGPath.py b/src/Mod/Draft/SVGPath.py index de596412c5..e5a58a310e 100644 --- a/src/Mod/Draft/SVGPath.py +++ b/src/Mod/Draft/SVGPath.py @@ -16,15 +16,16 @@ from Part import ( Edge, Wire, Compound, - OCCError + OCCError, ) -def _tolerance(precision): - return 10**(-precision) -def _arc_end_to_center(lastvec, currentvec, rx, ry, - x_rotation=0.0, correction=False): - '''Calculate the possible centers for an arc in endpoint parameterization. +def _tolerance(precision): + return 10 ** (-precision) + + +def _arc_end_to_center(lastvec, currentvec, rx, ry, x_rotation=0.0, correction=False): + """Calculate the possible centers for an arc in endpoint parameterization. Calculate (positive and negative) possible centers for an arc given in ``endpoint parametrization``. @@ -63,7 +64,7 @@ def _arc_end_to_center(lastvec, currentvec, rx, ry, The first element of the list is the positive tuple, consisting of center, angle, and angle increment; the second element is the negative tuple. - ''' + """ # scalefacsign = 1 if (largeflag != sweepflag) else -1 rx = float(rx) ry = float(ry) @@ -84,11 +85,11 @@ def _arc_end_to_center(lastvec, currentvec, rx, ry, # If the division is very small, set the scaling factor to zero, # otherwise try to calculate it by taking the square root - if abs(numer/denom) < 1.0e-7: + if abs(numer / denom) < 1.0e-7: scalefacpos = 0 else: try: - scalefacpos = math.sqrt(numer/denom) + scalefacpos = math.sqrt(numer / denom) except ValueError: _msg("sqrt({0}/{1})".format(numer, denom)) scalefacpos = 0 @@ -97,7 +98,7 @@ def _arc_end_to_center(lastvec, currentvec, rx, ry, for scalefacsign in (1, -1): scalefac = scalefacpos * scalefacsign # Step2 eq. 5.2 - vcx1 = Vector(v1.y * rx/ry, -v1.x * ry/rx, 0).multiply(scalefac) + vcx1 = Vector(v1.y * rx / ry, -v1.x * ry / rx, 0).multiply(scalefac) m2 = Matrix() m2.rotateZ(x_rotation) centeroff = currentvec.add(lastvec) @@ -112,16 +113,13 @@ def _arc_end_to_center(lastvec, currentvec, rx, ry, # (-v1.y - vcx1.y)/ry, # 0)) # eq. 5.6 # we need the right sign for the angle - angle1 = angle(Vector(1, 0, 0), - Vector((v1.x - vcx1.x)/rx, - (v1.y - vcx1.y)/ry, - 0)) # eq. 5.5 - angledelta = angle(Vector((v1.x - vcx1.x)/rx, - (v1.y - vcx1.y)/ry, - 0), - Vector((-v1.x - vcx1.x)/rx, - (-v1.y - vcx1.y)/ry, - 0)) # eq. 5.6 + angle1 = angle( + Vector(1, 0, 0), Vector((v1.x - vcx1.x) / rx, (v1.y - vcx1.y) / ry, 0) + ) # eq. 5.5 + angledelta = angle( + Vector((v1.x - vcx1.x) / rx, (v1.y - vcx1.y) / ry, 0), + Vector((-v1.x - vcx1.x) / rx, (-v1.y - vcx1.y) / ry, 0), + ) # eq. 5.6 results.append((vcenter, angle1, angledelta)) if rx < 0 or ry < 0: @@ -131,7 +129,7 @@ def _arc_end_to_center(lastvec, currentvec, rx, ry, def _arc_center_to_end(center, rx, ry, angle1, angledelta, xrotation=0.0): - '''Calculate start and end points, and flags of an arc. + """Calculate start and end points, and flags of an arc. Calculate start and end points, and flags of an arc given in ``center parametrization``. @@ -158,11 +156,9 @@ def _arc_center_to_end(center, rx, ry, angle1, angledelta, xrotation=0.0): Tuple indicating the end points of the arc, and two boolean values indicating whether the arc is less than 180 degrees or not, and whether the angledelta is negative. - ''' + """ vr1 = Vector(rx * math.cos(angle1), ry * math.sin(angle1), 0) - vr2 = Vector(rx * math.cos(angle1 + angledelta), - ry * math.sin(angle1 + angledelta), - 0) + vr2 = Vector(rx * math.cos(angle1 + angledelta), ry * math.sin(angle1 + angledelta), 0) mxrot = Matrix() mxrot.rotateZ(xrotation) v1 = mxrot.multiply(vr1).add(center) @@ -192,8 +188,8 @@ def _approx_bspline( return curve -def _make_wire(path : list[Edge], precision : int, checkclosed : bool=False, donttry : bool=False): - '''Try to make a wire out of the list of edges. +def _make_wire(path: list[Edge], precision: int, checkclosed: bool = False, donttry: bool = False): + """Try to make a wire out of the list of edges. If the wire functions fail or the wire is not closed, if required the TopoShapeCompoundPy::connectEdgesToWires() @@ -215,7 +211,7 @@ def _make_wire(path : list[Edge], precision : int, checkclosed : bool=False, don A wire created from the ordered edges. Part::Compound A compound made of the edges, but unable to form a wire. - ''' + """ if not donttry: try: sh = Wire(path) @@ -239,26 +235,25 @@ def _make_wire(path : list[Edge], precision : int, checkclosed : bool=False, don class FaceTreeNode: - ''' - Building Block of a tree structure holding one-closed-wire faces + """ + Building Block of a tree structure holding one-closed-wire faces sorted after their enclosure of each other. This class only works with faces that have exactly one closed wire - ''' - face : Face - children : list - name : str + """ + + face: Face + children: list + name: str - def __init__(self, face=None, name="root"): super().__init__() self.face = face self.name = name - self.children = [] + self.children = [] - - def insert (self, face, name): - ''' - takes a single-wire named face, and inserts it into the tree + def insert(self, face, name): + """ + takes a single-wire named face, and inserts it into the tree depending on its enclosure in/of already added faces. Parameters @@ -266,42 +261,45 @@ class FaceTreeNode: face : Face single closed wire face to be added to the tree name : str - face identifier - ''' + face identifier + """ for node in self.children: - if node.face.Area > face.Area: + if node.face.Area > face.Area: # new face could be encompassed - if (face.distToShape(node.face)[0] == 0.0 and - face.Wires[0].distToShape(node.face.Wires[0])[0] != 0.0): + if ( + face.distToShape(node.face)[0] == 0.0 + and face.Wires[0].distToShape(node.face.Wires[0])[0] != 0.0 + ): # it is encompassed - enter next tree layer node.insert(face, name) return else: # new face could encompass - if (node.face.distToShape(face)[0] == 0.0 and - node.face.Wires[0].distToShape(face.Wires[0])[0] != 0.0): + if ( + node.face.distToShape(face)[0] == 0.0 + and node.face.Wires[0].distToShape(face.Wires[0])[0] != 0.0 + ): # it does encompass the current child nodes face # create new node from face new = FaceTreeNode(face, name) - # swap the new one with the child node + # swap the new one with the child node self.children.remove(node) self.children.append(new) # add former child node as child to the new node new.children.append(node) return # the face is not encompassing and is not encompassed (from) any - # other face, we add it as new child + # other face, we add it as new child new = FaceTreeNode(face, name) self.children.append(new) - def makeCuts(self): - ''' - recursively traverse the tree and cuts all faces in even - numbered tree levels with their direct childrens faces. - Additionally the tree is shrunk by removing the odd numbered - tree levels. - ''' + """ + recursively traverse the tree and cuts all faces in even + numbered tree levels with their direct childrens faces. + Additionally the tree is shrunk by removing the odd numbered + tree levels. + """ result = self.face if not result: for node in self.children: @@ -316,29 +314,27 @@ class FaceTreeNode: self.children = new_children self.face = result - def flatten(self): - ''' creates a flattened list of face-name tuples from the facetree - content - ''' + """creates a flattened list of face-name tuples from the facetree + content + """ result = [] result.append((self.name, self.face)) for node in self.children: result.extend(node.flatten()) - return result - - - + return result + + class SvgPathElement: - path : list[dict] + path: list[dict] - def __init__(self, precision : int, interpol_pts : int, origin : Vector = Vector(0, 0, 0)): + def __init__(self, precision: int, interpol_pts: int, origin: Vector = Vector(0, 0, 0)): self.precision = precision self.interpol_pts = interpol_pts - self.path = [{"type": "start", "last_v": origin }] - - def add_move(self, x : float, y : float, relative : bool) -> None: + self.path = [{"type": "start", "last_v": origin}] + + def add_move(self, x: float, y: float, relative: bool) -> None: if relative: last_v = self.path[-1]["last_v"].add(Vector(x, -y, 0)) else: @@ -380,8 +376,14 @@ class SvgPathElement: def add_arcs(self, args: list[float], relative: bool) -> None: p_iter = zip( - args[0::7], args[1::7], args[2::7], args[3::7], - args[4::7], args[5::7], args[6::7], strict=False, + args[0::7], + args[1::7], + args[2::7], + args[3::7], + args[4::7], + args[5::7], + args[6::7], + strict=False, ) for rx, ry, x_rotation, large_flag, sweep_flag, x, y in p_iter: # support for large-arc and x-rotation is missing @@ -389,31 +391,43 @@ class SvgPathElement: last_v = self.path[-1]["last_v"].add(Vector(x, -y, 0)) else: last_v = Vector(x, -y, 0) - self.path.append({ - "type": "arc", - "rx": rx, - "ry": ry, - "x_rotation": x_rotation, - "large_flag": large_flag != 0, - "sweep_flag": sweep_flag != 0, - "last_v": last_v - }) + self.path.append( + { + "type": "arc", + "rx": rx, + "ry": ry, + "x_rotation": x_rotation, + "large_flag": large_flag != 0, + "sweep_flag": sweep_flag != 0, + "last_v": last_v, + } + ) def add_cubic_beziers(self, args: list[float], relative: bool, smooth: bool) -> None: last_v = self.path[-1]["last_v"] if smooth: p_iter = list( zip( - args[2::4], args[3::4], - args[0::4], args[1::4], - args[2::4], args[3::4], strict=False ) + args[2::4], + args[3::4], + args[0::4], + args[1::4], + args[2::4], + args[3::4], + strict=False, + ) ) else: p_iter = list( zip( - args[0::6], args[1::6], - args[2::6], args[3::6], - args[4::6], args[5::6], strict=False ) + args[0::6], + args[1::6], + args[2::6], + args[3::6], + args[4::6], + args[5::6], + strict=False, + ) ) for p1x, p1y, p2x, p2y, x, y in p_iter: if smooth: @@ -433,21 +447,14 @@ class SvgPathElement: pole2 = Vector(p2x, -p2y, 0) last_v = Vector(x, -y, 0) - self.path.append({ - "type": "cbezier", - "pole1": pole1, - "pole2": pole2, - "last_v": last_v - }) + self.path.append({"type": "cbezier", "pole1": pole1, "pole2": pole2, "last_v": last_v}) def add_quadratic_beziers(self, args: list[float], relative: bool, smooth: bool): last_v = self.path[-1]["last_v"] if smooth: - p_iter = list( zip( args[1::2], args[1::2], - args[0::2], args[1::2], strict=False ) ) + p_iter = list(zip(args[1::2], args[1::2], args[0::2], args[1::2], strict=False)) else: - p_iter = list( zip( args[0::4], args[1::4], - args[2::4], args[3::4], strict=False ) ) + p_iter = list(zip(args[0::4], args[1::4], args[2::4], args[3::4], strict=False)) for px, py, x, y in p_iter: if smooth: if self.path[-1]["type"] == "qbezier": @@ -464,14 +471,10 @@ class SvgPathElement: else: last_v = Vector(x, -y, 0) - self.path.append({ - "type": "qbezier", - "pole": pole, - "last_v": last_v - }) + self.path.append({"type": "qbezier", "pole": pole, "last_v": last_v}) def add_close(self): - last_v = self.path[-1]["last_v"] + last_v = self.path[-1]["last_v"] first_v = self.__get_last_start() if not equals(last_v, first_v, self.precision): self.path.append({"type": "line", "last_v": first_v}) @@ -489,17 +492,16 @@ class SvgPathElement: def __correct_last_v(self, pds: dict, last_v: Vector) -> None: """ - Correct the endpoint of the given path dataset to the + Correct the endpoint of the given path dataset to the given vector and move possibly associated members accordingly. """ delta = last_v.sub(pds["last_v"]) - # we won't move last_v if it's already correct or if the delta + # we won't move last_v if it's already correct or if the delta # is substantially greater than what rounding errors could accumulate, - # so we assume the path is intended to be open. - if (delta.x == 0 and delta.y == 0 and delta.z == 0 or - not isNull(delta, self.precision)): + # so we assume the path is intended to be open. + if delta.x == 0 and delta.y == 0 and delta.z == 0 or not isNull(delta, self.precision): return - + # for cbeziers we also relocate the second pole if pds["type"] == "cbezier": pds["pole2"] = pds["pole2"].add(delta) @@ -509,10 +511,9 @@ class SvgPathElement: # all data types have last_v pds["last_v"] = last_v - def correct_endpoints(self): - """ - Correct the endpoints of all subpaths and move possibly + """ + Correct the endpoints of all subpaths and move possibly associated members accordingly. """ start = None @@ -522,7 +523,7 @@ class SvgPathElement: if start: # there is already a start if last: - # and there are edges behind us. + # and there are edges behind us. # we correct the last to the start vector self.__correct_last_v(last, start["last_v"]) last = None @@ -532,10 +533,9 @@ class SvgPathElement: if start and last and start != last: self.__correct_last_v(last, start["last_v"]) - def create_edges(self) -> list[list[Edge]]: """ - Creates shapes from prepared path datasets and returns them in an + Creates shapes from prepared path datasets and returns them in an ordered list of lists of edges, where each 1st order list entry represents a single continuous (and probably closed) sub-path. """ @@ -546,7 +546,7 @@ class SvgPathElement: next_v = pds["last_v"] match pds["type"]: case "start": - if edges and len(edges) > 0 : + if edges and len(edges) > 0: result.append(edges) edges = [] case "line": @@ -565,10 +565,7 @@ class SvgPathElement: # in 'endpoint parameterization'. _x_rot = math.radians(-x_rotation) (solution, (rx, ry)) = _arc_end_to_center( - last_v, next_v, - rx, ry, - _x_rot, - correction=True + last_v, next_v, rx, ry, _x_rot, correction=True ) # Choose one of the two solutions neg_sol = large_flag != sweep_flag @@ -633,57 +630,55 @@ class SvgPathElement: seg = _approx_bspline(b, self.interpol_pts).toShape() edges.append(seg) case _: - _msg("Illegal path_data type. {}".format(pds['type'])) + _msg("Illegal path_data type. {}".format(pds["type"])) return [] last_v = next_v - if not edges is None and len(edges) > 0 : + if not edges is None and len(edges) > 0: result.append(edges) return result - class SvgPathParser: """Parse SVG path data and create FreeCAD Shapes.""" - commands : list[tuple] - pointsre : re.Pattern - data : dict - shapes : list[list[Shape]] - faces : FaceTreeNode - name : str + commands: list[tuple] + pointsre: re.Pattern + data: dict + shapes: list[list[Shape]] + faces: FaceTreeNode + name: str def __init__(self, data, name): super().__init__() """Evaluate path data and initialize.""" - _op = '([mMlLhHvVaAcCqQsStTzZ])' - _op2 = '([^mMlLhHvVaAcCqQsStTzZ]*)' - _command = '\\s*?' + _op + '\\s*?' + _op2 + '\\s*?' + _op = "([mMlLhHvVaAcCqQsStTzZ])" + _op2 = "([^mMlLhHvVaAcCqQsStTzZ]*)" + _command = "\\s*?" + _op + "\\s*?" + _op2 + "\\s*?" pathcommandsre = re.compile(_command, re.DOTALL) - - _num = '[-+]?[0-9]*\\.?[0-9]+' - _exp = '([eE][-+]?[0-9]+)?' - _arg = '(' + _num + _exp + ')' - self.commands = pathcommandsre.findall(' '.join(data['d'])) + + _num = "[-+]?[0-9]*\\.?[0-9]+" + _exp = "([eE][-+]?[0-9]+)?" + _arg = "(" + _num + _exp + ")" + self.commands = pathcommandsre.findall(" ".join(data["d"])) self.argsre = re.compile(_arg, re.DOTALL) self.data = data self.paths = [] self.shapes = [] self.faces = None self.name = name - - + def parse(self): - ''' - Creates lists of SvgPathElements from raw svg path + """ + Creates lists of SvgPathElements from raw svg path data. It's supposed to be called direct after SvgPath Object creation. - ''' + """ path = SvgPathElement(svg_precision(), 10) self.paths = [] for d, argsstr in self.commands: relative = d.islower() - - _args = self.argsre.findall(argsstr.replace(',', ' ')) + + _args = self.argsre.findall(argsstr.replace(",", " ")) args = [float(number) for number, exponent in _args] if d in "Mm": @@ -706,38 +701,36 @@ class SvgPathParser: path.add_quadratic_beziers(args, relative, True) elif d in "Zz": path.add_close() - - path.correct_endpoints(); + + path.correct_endpoints() self.shapes = path.create_edges() - - + def create_faces(self, fill=True, add_wire_for_invalid_face=False): - ''' + """ Generate Faces from lists of Shapes. - If shapes form a closed wire and the fill Attribute is set, we + If shapes form a closed wire and the fill Attribute is set, we generate a closed Face. Otherwise we treat the shape as pure wire. - + Parameters ---------- fill : Object/bool if True or not None Faces are generated from closed shapes. - ''' + """ precision = svg_precision() - cnt = -1; + cnt = -1 openShapes = [] self.faces = FaceTreeNode() for sh in self.shapes: cnt += 1 add_wire = True wr = _make_wire(sh, precision, checkclosed=True) - wrcpy = wr.copy(); + wrcpy = wr.copy() wire_reason = "" if cnt > 0: face_name = self.name + "_" + str(cnt) else: - face_name = self.name + face_name = self.name - if not fill: wire_reason = " no-fill" if not wr.Wires[0].isClosed(): @@ -752,37 +745,39 @@ class SvgPathParser: res = "succeed" else: res = "fail" - _wrn("Invalid Face '{}' created. Attempt to fix - {}ed." - .format(face_name, res)) + _wrn( + "Invalid Face '{}' created. Attempt to fix - {}ed.".format( + face_name, res + ) + ) else: add_wire = False if not (face.Area < 10 * (_tolerance(precision) ** 2)): self.faces.insert(face, face_name) except: - _wrn("Failed to make a shape from '{}'. ".format(face_name) - + "This Path will be discarded.") + _wrn( + "Failed to make a shape from '{}'. ".format(face_name) + + "This Path will be discarded." + ) if add_wire: if wrcpy.Length > _tolerance(precision): - _msg("Adding wire for '{}' - reason: {}." - .format(face_name, wire_reason)) + _msg("Adding wire for '{}' - reason: {}.".format(face_name, wire_reason)) openShapes.append((face_name + "_w", wrcpy)) self.shapes = openShapes - def doCuts(self): - ''' Exposes the FaceTreeNode.makeCuts function of the tree containing - closed wire faces. - This function is called after creating closed Faces with - 'createFaces' in order to hollow faces encompassing others. - ''' + """Exposes the FaceTreeNode.makeCuts function of the tree containing + closed wire faces. + This function is called after creating closed Faces with + 'createFaces' in order to hollow faces encompassing others. + """ self.faces.makeCuts() - def getShapeList(self): - ''' Returns the resulting list of tuples containing name and face of - each created element. - ''' + """Returns the resulting list of tuples containing name and face of + each created element. + """ result = self.faces.flatten() - result.extend(self.shapes) + result.extend(self.shapes) return result diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 5713f87fd4..b61a1b770a 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -83,9 +83,9 @@ class PlaneBase: Note that the u, v and w vectors are not checked for validity. """ - def __init__(self, - u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1), - pos=Vector(0, 0, 0)): + def __init__( + self, u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1), pos=Vector(0, 0, 0) + ): if isinstance(u, PlaneBase): self.match(u) @@ -297,7 +297,7 @@ class PlaneBase: """ if face.Surface.isPlanar() is False: return False - axis = face.normalAt(0,0) + axis = face.normalAt(0, 0) point = edge.Vertexes[0].Point vec = edge.Vertexes[-1].Point.sub(point) return self.align_to_point_and_axis(point, axis, offset, axis.cross(vec)) @@ -426,44 +426,44 @@ class PlaneBase: self.axis = Vector(axis).normalize() ref_vec = Vector(0.0, 1.0, 0.0) - if ((abs(axis.x) > abs(axis.y)) and (abs(axis.y) > abs(axis.z))): - ref_vec = Vector(0.0, 0., 1.0) + if (abs(axis.x) > abs(axis.y)) and (abs(axis.y) > abs(axis.z)): + ref_vec = Vector(0.0, 0.0, 1.0) self.u = axis.negative().cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "Case new" - elif ((abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x))): + elif (abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x)): ref_vec = Vector(1.0, 0.0, 0.0) self.u = axis.negative().cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "Y>Z, View Y" - elif ((abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z))): - ref_vec = Vector(0.0, 0., 1.0) + elif (abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z)): + ref_vec = Vector(0.0, 0.0, 1.0) self.u = axis.cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "ehem. XY, Case XY" - elif ((abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y))): + elif (abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y)): self.u = axis.cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "X>Z, View X" - elif ((abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x))): - ref_vec = Vector(1.0, 0., 0.0) + elif (abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x)): + ref_vec = Vector(1.0, 0.0, 0.0) self.u = axis.cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "Y>X, Case YZ" else: self.u = axis.negative().cross(ref_vec) self.u.normalize() - self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis) + self.v = DraftVecUtils.rotate(self.u, math.pi / 2, self.axis) # projcase = "else" # spat_vec = self.u.cross(self.v) @@ -545,16 +545,18 @@ class PlaneBase: def is_global(self): """Return `True` if the WP matches the global coordinate system exactly.""" - return self.u == Vector(1, 0, 0) \ - and self.v == Vector(0, 1, 0) \ - and self.axis == Vector(0, 0, 1) \ + return ( + self.u == Vector(1, 0, 0) + and self.v == Vector(0, 1, 0) + and self.axis == Vector(0, 0, 1) and self.position == Vector() + ) def is_ortho(self): """Return `True` if all WP axes are parallel to a global axis.""" rot = FreeCAD.Rotation(self.u, self.v, self.axis, "ZYX") ypr = [round(ang, 6) for ang in rot.getYawPitchRoll()] - return all([ang%90 == 0 for ang in ypr]) + return all([ang % 90 == 0 for ang in ypr]) def project_point(self, point, direction=None, force_projection=True): """Project a point onto the WP and return the global coordinates of the @@ -575,11 +577,9 @@ class PlaneBase: ------- Base.Vector """ - return DraftGeomUtils.project_point_on_plane(point, - self.position, - self.axis, - direction, - force_projection) + return DraftGeomUtils.project_point_on_plane( + point, self.position, self.axis, direction, force_projection + ) def set_to_top(self, offset=0): """Set the WP to the top position with an optional offset.""" @@ -613,15 +613,12 @@ class PlaneBase: near multiples of 45 degrees. """ ypr = [round(ang, 3) for ang in rot.getYawPitchRoll()] - if all([ang%45 == 0 for ang in ypr]): + if all([ang % 45 == 0 for ang in ypr]): rot.setEulerAngles("YawPitchRoll", *ypr) return self._axes_from_rotation(rot) def _get_prop_list(self): - return ["u", - "v", - "axis", - "position"] + return ["u", "v", "axis", "position"] class Plane(PlaneBase): @@ -660,10 +657,14 @@ class Plane(PlaneBase): Placeholder for a stored state. """ - def __init__(self, - u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1), - pos=Vector(0, 0, 0), - weak=True): + def __init__( + self, + u=Vector(1, 0, 0), + v=Vector(0, 1, 0), + w=Vector(0, 0, 1), + pos=Vector(0, 0, 0), + weak=True, + ): if isinstance(u, Plane): self.match(u) @@ -837,16 +838,20 @@ class Plane(PlaneBase): if isinstance(geom, Part.Shape): geom_is_shape = True if not geom_is_shape: - _wrn(translate( - "draft", - "Object without Part.Shape geometry:'{}'".format( - obj.ObjectName)) + "\n") + _wrn( + translate( + "draft", "Object without Part.Shape geometry:'{}'".format(obj.ObjectName) + ) + + "\n" + ) return False if geom.isNull(): - _wrn(translate( - "draft", - "Object with null Part.Shape geometry:'{}'".format( - obj.ObjectName)) + "\n") + _wrn( + translate( + "draft", "Object with null Part.Shape geometry:'{}'".format(obj.ObjectName) + ) + + "\n" + ) return False if obj.HasSubObjects: shapes.extend(obj.SubObjects) @@ -858,8 +863,7 @@ class Plane(PlaneBase): normal = None for n in range(len(shapes)): if not DraftGeomUtils.is_planar(shapes[n]): - _wrn(translate( - "draft", "'{}' object is not planar".format(names[n])) + "\n") + _wrn(translate("draft", "'{}' object is not planar".format(names[n])) + "\n") return False if not normal: normal = DraftGeomUtils.get_normal(shapes[n]) @@ -869,9 +873,12 @@ class Plane(PlaneBase): if normal: for n in range(len(shapes)): if not DraftGeomUtils.are_coplanar(shapes[shape_ref], shapes[n]): - _wrn(translate( - "draft", "{} and {} are not coplanar".format( - names[shape_ref],names[n])) + "\n") + _wrn( + translate( + "draft", "{} and {} are not coplanar".format(names[shape_ref], names[n]) + ) + + "\n" + ) return False else: # suppose all geometries are straight lines or points @@ -879,25 +886,23 @@ class Plane(PlaneBase): if len(points) >= 3: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly): - _wrn(translate( - "draft", "All shapes must be coplanar") + "\n") + _wrn(translate("draft", "All shapes must be coplanar") + "\n") return False normal = DraftGeomUtils.get_normal(poly) else: normal = None if not normal: - _wrn(translate( - "draft", "Selected shapes must define a plane") + "\n") + _wrn(translate("draft", "Selected shapes must define a plane") + "\n") return False # set center of mass - ctr_mass = Vector(0,0,0) - ctr_pts = Vector(0,0,0) + ctr_mass = Vector(0, 0, 0) + ctr_pts = Vector(0, 0, 0) mass = 0 for shape in shapes: if hasattr(shape, "CenterOfMass"): - ctr_mass += shape.CenterOfMass*shape.Mass + ctr_mass += shape.CenterOfMass * shape.Mass mass += shape.Mass else: ctr_pts += shape.Point @@ -905,7 +910,7 @@ class Plane(PlaneBase): ctr_mass /= mass # all shapes are vertexes else: - ctr_mass = ctr_pts/len(shapes) + ctr_mass = ctr_pts / len(shapes) super().align_to_point_and_axis(ctr_mass, normal, offset) self.weak = False @@ -970,9 +975,10 @@ class Plane(PlaneBase): self.weak = False if FreeCAD.GuiUp: from draftutils.translate import translate - if hasattr(FreeCADGui,"Snapper"): + + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.setGrid() - if hasattr(FreeCADGui,"draftToolBar"): + if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Top")) def setFront(self): @@ -981,9 +987,10 @@ class Plane(PlaneBase): self.weak = False if FreeCAD.GuiUp: from draftutils.translate import translate - if hasattr(FreeCADGui,"Snapper"): + + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.setGrid() - if hasattr(FreeCADGui,"draftToolBar"): + if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Front")) def setSide(self): @@ -999,9 +1006,10 @@ class Plane(PlaneBase): self.weak = False if FreeCAD.GuiUp: from draftutils.translate import translate - if hasattr(FreeCADGui,"Snapper"): + + if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.setGrid() - if hasattr(FreeCADGui,"draftToolBar"): + if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.wplabel.setText(translate("draft", "Side")) def getRotation(self): @@ -1152,15 +1160,12 @@ class Plane(PlaneBase): data: dict dictionary of the form: {"u":x, "v":v, "axis":axis, "position":position, "weak":weak} - """ + """ super().set_parameters(data) def _get_prop_list(self): - return ["u", - "v", - "axis", - "position", - "weak"] + return ["u", "v", "axis", "position", "weak"] + plane = Plane @@ -1220,13 +1225,17 @@ class PlaneGui(PlaneBase): Dictionary that holds up to 10 stored states. """ - def __init__(self, - u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1), - pos=Vector(0, 0, 0), - auto=True, - icon=":/icons/view-axonometric.svg", - label=QT_TRANSLATE_NOOP("draft", "Auto"), - tip=QT_TRANSLATE_NOOP("draft", "Current working plane: Auto")): + def __init__( + self, + u=Vector(1, 0, 0), + v=Vector(0, 1, 0), + w=Vector(0, 0, 1), + pos=Vector(0, 0, 0), + auto=True, + icon=":/icons/view-axonometric.svg", + label=QT_TRANSLATE_NOOP("draft", "Auto"), + tip=QT_TRANSLATE_NOOP("draft", "Current working plane: Auto"), + ): if isinstance(u, PlaneGui): self.match(u) @@ -1287,13 +1296,20 @@ class PlaneGui(PlaneBase): if len(objs) != 1: ret = False - if all([obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Vertex"] for obj in objs]): + if all( + [ + obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Vertex"] + for obj in objs + ] + ): ret = self.align_to_edges_vertexes([obj[0] for obj in objs], offset, _hist_add) - elif all([obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Face"] for obj in objs]): - edges = [obj[0] for obj in objs if obj[0].ShapeType == "Edge"] - faces = [obj[0] for obj in objs if obj[0].ShapeType == "Face"] - if faces and edges: - ret = self.align_to_face_and_edge(faces[0], edges[0], offset, _hist_add) + elif all( + [obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Face"] for obj in objs] + ): + edges = [obj[0] for obj in objs if obj[0].ShapeType == "Edge"] + faces = [obj[0] for obj in objs if obj[0].ShapeType == "Face"] + if faces and edges: + ret = self.align_to_face_and_edge(faces[0], edges[0], offset, _hist_add) if ret is False: _wrn(translate("draft", "Selected shapes do not define a plane")) return ret @@ -1310,7 +1326,7 @@ class PlaneGui(PlaneBase): ret = self.align_to_wp_proxy(obj, offset, place * obj.Placement, _hist_add) elif typ == "IfcBuildingStorey": pl = FreeCAD.Placement(obj.Placement) - pl.move(FreeCAD.Vector(0,0,obj.Elevation.Value)) + pl.move(FreeCAD.Vector(0, 0, obj.Elevation.Value)) ret = self.align_to_wp_proxy(obj, offset, place * pl, _hist_add) elif shape.isNull(): ret = self.align_to_obj_placement(obj, offset, place, _hist_add) @@ -1411,10 +1427,12 @@ class PlaneGui(PlaneBase): self.auto = False if utils.get_type(obj) == "WorkingPlaneProxy": self.icon = ":/icons/Draft_PlaneProxy.svg" - elif FreeCAD.GuiUp \ - and hasattr(obj, "ViewObject") \ - and hasattr(obj.ViewObject, "Proxy") \ - and hasattr(obj.ViewObject.Proxy, "getIcon"): + elif ( + FreeCAD.GuiUp + and hasattr(obj, "ViewObject") + and hasattr(obj.ViewObject, "Proxy") + and hasattr(obj.ViewObject.Proxy, "getIcon") + ): self.icon = obj.ViewObject.Proxy.getIcon() else: self.icon = ":/icons/Std_Placement.svg" @@ -1438,19 +1456,18 @@ class PlaneGui(PlaneBase): vobj = obj.ViewObject - if hasattr(vobj, "AutoWorkingPlane") \ - and vobj.AutoWorkingPlane is True: + if hasattr(vobj, "AutoWorkingPlane") and vobj.AutoWorkingPlane is True: self.auto = True - if hasattr(vobj, "CutView") \ - and hasattr(vobj, "AutoCutView") \ - and vobj.AutoCutView is True: + if hasattr(vobj, "CutView") and hasattr(vobj, "AutoCutView") and vobj.AutoCutView is True: vobj.CutView = True - if hasattr(vobj, "RestoreView") \ - and vobj.RestoreView is True \ - and hasattr(vobj, "ViewData") \ - and len(vobj.ViewData) >= 12: + if ( + hasattr(vobj, "RestoreView") + and vobj.RestoreView is True + and hasattr(vobj, "ViewData") + and len(vobj.ViewData) >= 12 + ): vdat = vobj.ViewData if self._view is not None: try: @@ -1475,14 +1492,16 @@ class PlaneGui(PlaneBase): except Exception: pass - if hasattr(vobj, "RestoreState") \ - and vobj.RestoreState is True \ - and hasattr(vobj, "VisibilityMap") \ - and vobj.VisibilityMap: + if ( + hasattr(vobj, "RestoreState") + and vobj.RestoreState is True + and hasattr(vobj, "VisibilityMap") + and vobj.VisibilityMap + ): for name, vis in vobj.VisibilityMap.items(): obj = FreeCADGui.ActiveDocument.getObject(name) if obj: - obj.Visibility = (vis == "True") + obj.Visibility = vis == "True" return True @@ -1509,7 +1528,7 @@ class PlaneGui(PlaneBase): elif default_wp == 3: self.set_to_side() - def set_to_auto(self): # Similar to Plane.reset. + def set_to_auto(self): # Similar to Plane.reset. """Set the WP to auto.""" self.auto = True self.auto_align() @@ -1633,9 +1652,11 @@ class PlaneGui(PlaneBase): if self._view is not None: try: cam = self._view.getCameraNode() - pos = self.project_point(Vector(cam.position.getValue().getValue()), - direction=self._view.getViewDirection(), - force_projection=False) + pos = self.project_point( + Vector(cam.position.getValue().getValue()), + direction=self._view.getViewDirection(), + force_projection=False, + ) if pos is not None: self.position = pos except Exception: @@ -1647,7 +1668,9 @@ class PlaneGui(PlaneBase): try: default_cam_dist = abs(params.get_param_view("NewDocumentCameraScale")) cam = self._view.getCameraNode() - cur_cam_dist = abs(self.get_local_coords(Vector(cam.position.getValue().getValue())).z) + cur_cam_dist = abs( + self.get_local_coords(Vector(cam.position.getValue().getValue())).z + ) cam_dist = max(default_cam_dist, cur_cam_dist) cam.position.setValue(self.position + DraftVecUtils.scaleTo(self.axis, cam_dist)) cam.orientation.setValue(self.get_placement().Rotation.Q) @@ -1683,14 +1706,7 @@ class PlaneGui(PlaneBase): return bool(self._history) and self._history["idx"] != len(self._history["data_list"]) - 1 def _get_prop_list(self): - return ["u", - "v", - "axis", - "position", - "auto", - "icon", - "label", - "tip"] + return ["u", "v", "axis", "position", "auto", "icon", "label", "tip"] def _get_label(self, label): if self.auto or self.position.isEqual(Vector(), 0): @@ -1745,36 +1761,35 @@ class PlaneGui(PlaneBase): return max_len = 10 # Max. length of data_list. - self._history["data_list"] = self._history["data_list"][(idx - (max_len - 2)):(idx + 1)] + self._history["data_list"] = self._history["data_list"][(idx - (max_len - 2)) : (idx + 1)] self._history["data_list"].append(data) self._history["idx"] = len(self._history["data_list"]) - 1 def _update_old_plane(self): - """ Update the old DraftWorkingPlane for compatibility. + """Update the old DraftWorkingPlane for compatibility. The tracker and snapper code currently still depend on it. """ if not hasattr(FreeCAD, "DraftWorkingPlane"): FreeCAD.DraftWorkingPlane = Plane() for prop in ["u", "v", "axis", "position"]: - setattr(FreeCAD.DraftWorkingPlane, - prop, - self._copy_value(getattr(self, prop))) + setattr(FreeCAD.DraftWorkingPlane, prop, self._copy_value(getattr(self, prop))) FreeCAD.DraftWorkingPlane.weak = self.auto def _update_grid(self): # Check for draftToolBar because the trackers (grid) depend on it for its colors. - if FreeCAD.GuiUp \ - and hasattr(FreeCADGui, "draftToolBar") \ - and hasattr(FreeCADGui, "Snapper") \ - and self._view is not None: + if ( + FreeCAD.GuiUp + and hasattr(FreeCADGui, "draftToolBar") + and hasattr(FreeCADGui, "Snapper") + and self._view is not None + ): FreeCADGui.Snapper.setGrid() FreeCADGui.Snapper.restack() # Required?? def _update_gui(self): - if FreeCAD.GuiUp \ - and hasattr(FreeCADGui, "draftToolBar") \ - and self._view is not None: + if FreeCAD.GuiUp and hasattr(FreeCADGui, "draftToolBar") and self._view is not None: from PySide import QtGui + button = FreeCADGui.draftToolBar.wplabel button.setIcon(QtGui.QIcon(self.icon)) button.setText(self.label) @@ -1800,7 +1815,9 @@ def get_working_plane(update=True): wp = PlaneGui() if FreeCAD.GuiUp: - wp._view = view # Update _view before call to set_to_default, set_to_auto requires a 3D view. + wp._view = ( + view # Update _view before call to set_to_default, set_to_auto requires a 3D view. + ) wp.set_to_default() if view is not None: FreeCAD.draft_working_planes[0].append(view) diff --git a/src/Mod/Draft/draftfunctions/array.py b/src/Mod/Draft/draftfunctions/array.py index 4222b7e953..8cb3ea65fa 100644 --- a/src/Mod/Draft/draftfunctions/array.py +++ b/src/Mod/Draft/draftfunctions/array.py @@ -63,52 +63,65 @@ def array(objectslist, arg1, arg2, arg3, arg4=None, arg5=None, arg6=None): if arg6: rectArray2(objectslist, arg1, arg2, arg3, arg4, arg5, arg6) elif arg4: - rectArray(objectslist, arg1,arg2, arg3, arg4) + rectArray(objectslist, arg1, arg2, arg3, arg4) else: polarArray(objectslist, arg1, arg2, arg3) -def rectArray(objectslist,xvector,yvector,xnum,ynum): - utils.type_check([(xvector, App.Vector), - (yvector, App.Vector), - (xnum,int), (ynum,int)], - "rectArray") - if not isinstance(objectslist,list): objectslist = [objectslist] +def rectArray(objectslist, xvector, yvector, xnum, ynum): + utils.type_check( + [(xvector, App.Vector), (yvector, App.Vector), (xnum, int), (ynum, int)], "rectArray" + ) + if not isinstance(objectslist, list): + objectslist = [objectslist] for xcount in range(xnum): - currentxvector=App.Vector(xvector).multiply(xcount) - if not xcount==0: - move.move(objectslist,currentxvector,True) + currentxvector = App.Vector(xvector).multiply(xcount) + if not xcount == 0: + move.move(objectslist, currentxvector, True) for ycount in range(ynum): - currentxvector=App.Vector(currentxvector) - currentyvector=currentxvector.add(App.Vector(yvector).multiply(ycount)) - if not ycount==0: - move.move(objectslist,currentyvector,True) + currentxvector = App.Vector(currentxvector) + currentyvector = currentxvector.add(App.Vector(yvector).multiply(ycount)) + if not ycount == 0: + move.move(objectslist, currentyvector, True) -def rectArray2(objectslist,xvector,yvector,zvector,xnum,ynum,znum): - utils.type_check([(xvector,App.Vector), (yvector,App.Vector), (zvector,App.Vector),(xnum,int), (ynum,int),(znum,int)], "rectArray2") - if not isinstance(objectslist,list): objectslist = [objectslist] +def rectArray2(objectslist, xvector, yvector, zvector, xnum, ynum, znum): + utils.type_check( + [ + (xvector, App.Vector), + (yvector, App.Vector), + (zvector, App.Vector), + (xnum, int), + (ynum, int), + (znum, int), + ], + "rectArray2", + ) + if not isinstance(objectslist, list): + objectslist = [objectslist] for xcount in range(xnum): - currentxvector=App.Vector(xvector).multiply(xcount) - if not xcount==0: - move.move(objectslist,currentxvector,True) + currentxvector = App.Vector(xvector).multiply(xcount) + if not xcount == 0: + move.move(objectslist, currentxvector, True) for ycount in range(ynum): - currentxvector=App.Vector(currentxvector) - currentyvector=currentxvector.add(App.Vector(yvector).multiply(ycount)) - if not ycount==0: - move.move(objectslist,currentyvector,True) + currentxvector = App.Vector(currentxvector) + currentyvector = currentxvector.add(App.Vector(yvector).multiply(ycount)) + if not ycount == 0: + move.move(objectslist, currentyvector, True) for zcount in range(znum): - currentzvector=currentyvector.add(App.Vector(zvector).multiply(zcount)) - if not zcount==0: - move.move(objectslist,currentzvector,True) + currentzvector = currentyvector.add(App.Vector(zvector).multiply(zcount)) + if not zcount == 0: + move.move(objectslist, currentzvector, True) -def polarArray(objectslist,center,angle,num): - utils.type_check([(center,App.Vector), (num,int)], "polarArray") - if not isinstance(objectslist,list): objectslist = [objectslist] - fraction = float(angle)/num +def polarArray(objectslist, center, angle, num): + utils.type_check([(center, App.Vector), (num, int)], "polarArray") + if not isinstance(objectslist, list): + objectslist = [objectslist] + fraction = float(angle) / num for i in range(num): - currangle = fraction + (i*fraction) - rotate.rotate(objectslist,currangle,center,copy=True) + currangle = fraction + (i * fraction) + rotate.rotate(objectslist, currangle, center, copy=True) + ## @} diff --git a/src/Mod/Draft/draftfunctions/cut.py b/src/Mod/Draft/draftfunctions/cut.py index 2408c2a6bf..26c09c94a5 100644 --- a/src/Mod/Draft/draftfunctions/cut.py +++ b/src/Mod/Draft/draftfunctions/cut.py @@ -54,7 +54,7 @@ def cut(object1, object2): If there is a problem and the new object can't be created. """ if not App.activeDocument(): - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return obj = App.activeDocument().addObject("Part::Cut", "Cut") @@ -69,4 +69,5 @@ def cut(object1, object2): return obj + ## @} diff --git a/src/Mod/Draft/draftfunctions/downgrade.py b/src/Mod/Draft/draftfunctions/downgrade.py index 463cb7145c..605d82a60e 100644 --- a/src/Mod/Draft/draftfunctions/downgrade.py +++ b/src/Mod/Draft/draftfunctions/downgrade.py @@ -247,7 +247,6 @@ def downgrade(objects, delete=False, force=None): return True return False - # helper functions (same as in upgrade.py) def get_parent(obj): @@ -311,7 +310,6 @@ def downgrade(objects, delete=False, force=None): for newobj in new_list: gui_utils.format_object(newobj, obj, ignore_construction=True) - doc = App.ActiveDocument add_list = [] delete_list = [] @@ -347,15 +345,15 @@ def downgrade(objects, delete=False, force=None): elif force: # functions that work on a single object: - single_funcs = {"explode": explode, - "getWire": getWire, - "shapify": _shapify} + single_funcs = {"explode": explode, "getWire": getWire, "shapify": _shapify} # functions that work on multiple objects: - multi_funcs = {"cut2": cut2, - "splitCompounds": splitCompounds, - "splitFaces": splitFaces, - "splitWires": splitWires, - "subtr": subtr} + multi_funcs = { + "cut2": cut2, + "splitCompounds": splitCompounds, + "splitFaces": splitFaces, + "splitWires": splitWires, + "subtr": subtr, + } if force in single_funcs: result = any([single_funcs[force](obj) for obj in objects]) elif force in multi_funcs: @@ -388,21 +386,21 @@ def downgrade(objects, delete=False, force=None): _msg(translate("draft", "Found 1 array: exploding it")) # special case, we have one parametric object: we "de-parametrize" it - elif len(objects) == 1 \ - and hasattr(objects[0], "Shape") \ - and ( - hasattr(objects[0], "Base") - or hasattr(objects[0], "Profile") - or hasattr(objects[0], "Sections") - ): + elif ( + len(objects) == 1 + and hasattr(objects[0], "Shape") + and ( + hasattr(objects[0], "Base") + or hasattr(objects[0], "Profile") + or hasattr(objects[0], "Sections") + ) + ): result = _shapify(objects[0]) if result: _msg(translate("draft", "Found 1 parametric object: breaking its dependencies")) # we have one multi-solids compound object: extract its solids - elif len(objects) == 1 \ - and hasattr(objects[0], "Shape") \ - and len(solids) > 1: + elif len(objects) == 1 and hasattr(objects[0], "Shape") and len(solids) > 1: result = splitCompounds(objects) if result: _msg(translate("draft", "Found 1 multi-solids compound: exploding it")) @@ -423,7 +421,11 @@ def downgrade(objects, delete=False, force=None): elif same_parent and same_parent_type != "PartDesign::Body": result = subtr(objects) if result: - _msg(translate("draft", "Found several faces: subtracting them from the first one")) + _msg( + translate( + "draft", "Found several faces: subtracting them from the first one" + ) + ) # only one face: we extract its wires elif len(faces) > 0: @@ -448,4 +450,5 @@ def downgrade(objects, delete=False, force=None): gui_utils.select(add_list) return add_list, delete_list + ## @} diff --git a/src/Mod/Draft/draftfunctions/draftify.py b/src/Mod/Draft/draftfunctions/draftify.py index 8d8d14e762..465e1785a8 100644 --- a/src/Mod/Draft/draftfunctions/draftify.py +++ b/src/Mod/Draft/draftfunctions/draftify.py @@ -43,6 +43,7 @@ import draftmake.make_arc_3points as make_arc_3points Part = lz.LazyLoader("Part", globals(), "Part") DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") + def draftify(objectslist, makeblock=False, delete=True): """draftify(objectslist,[makeblock],[delete]) @@ -62,11 +63,11 @@ def draftify(objectslist, makeblock=False, delete=True): If delete = False, old objects are not deleted """ - if not isinstance(objectslist,list): + if not isinstance(objectslist, list): objectslist = [objectslist] newobjlist = [] for obj in objectslist: - if hasattr(obj,'Shape'): + if hasattr(obj, "Shape"): for cluster in Part.sortEdges(obj.Shape.Edges): w = Part.Wire(cluster) nobj = draftify_shape(w) @@ -88,11 +89,12 @@ def draftify(objectslist, makeblock=False, delete=True): return newobjlist[0] return newobjlist + def draftify_shape(shape): nobj = None if DraftGeomUtils.hasCurves(shape): - if (len(shape.Edges) == 1): + if len(shape.Edges) == 1: edge = shape.Edges[0] edge_type = DraftGeomUtils.geomType(edge) if edge_type == "Circle": @@ -101,21 +103,24 @@ def draftify_shape(shape): else: first_parameter = edge.FirstParameter last_parameter = edge.LastParameter - points = [edge.Curve.value(first_parameter), - edge.Curve.value((first_parameter + last_parameter)/2), - edge.Curve.value(last_parameter)] + points = [ + edge.Curve.value(first_parameter), + edge.Curve.value((first_parameter + last_parameter) / 2), + edge.Curve.value(last_parameter), + ] nobj = make_arc_3points.make_arc_3points(points) - # TODO: take into consideration trimmed curves and capture the specific - # type of BSpline and Bezier that can be converted to a draft object. - # elif edge_type == "BSplineCurve": - # knots = [edge.Curve.value(p) for p in edge.Curve.getKnots()] - # nobj = make_bspline.make_bspline(knots, closed=edge.isClosed()) - # elif edge_type == "BezierCurve": - # nobj = make_bezcurve.make_bezcurve(edge.Curve.getPoles(), - # closed=edge.isClosed()) + # TODO: take into consideration trimmed curves and capture the specific + # type of BSpline and Bezier that can be converted to a draft object. + # elif edge_type == "BSplineCurve": + # knots = [edge.Curve.value(p) for p in edge.Curve.getKnots()] + # nobj = make_bspline.make_bspline(knots, closed=edge.isClosed()) + # elif edge_type == "BezierCurve": + # nobj = make_bezcurve.make_bezcurve(edge.Curve.getPoles(), + # closed=edge.isClosed()) else: nobj = make_wire.make_wire(shape) return nobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/dxf.py b/src/Mod/Draft/draftfunctions/dxf.py index 1236c4fdef..dfca4bc1d1 100644 --- a/src/Mod/Draft/draftfunctions/dxf.py +++ b/src/Mod/Draft/draftfunctions/dxf.py @@ -20,8 +20,7 @@ # * USA * # * * # *************************************************************************** -"""Provides functions to return the DXF representation of various shapes. -""" +"""Provides functions to return the DXF representation of various shapes.""" ## @package dxf # \ingroup draftfunctions # \brief Provides functions to return the DXF representation of shapes. @@ -44,6 +43,7 @@ TechDraw = lz.LazyLoader("TechDraw", globals(), "TechDraw") ## \addtogroup draftfunctions # @{ + def _get_proj(vec, plane=None): """Get a projection of the vector in the plane's u and v directions. @@ -85,9 +85,9 @@ def get_dxf(obj, direction=None): p2 = _get_proj(obj.End, plane=plane) p3 = _get_proj(obj.Dimline, plane=plane) result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n" - result += "10\n"+str(p3.x)+"\n20\n"+str(p3.y)+"\n30\n"+str(p3.z)+"\n" - result += "13\n"+str(p1.x)+"\n23\n"+str(p1.y)+"\n33\n"+str(p1.z)+"\n" - result += "14\n"+str(p2.x)+"\n24\n"+str(p2.y)+"\n34\n"+str(p2.z)+"\n" + result += "10\n" + str(p3.x) + "\n20\n" + str(p3.y) + "\n30\n" + str(p3.z) + "\n" + result += "13\n" + str(p1.x) + "\n23\n" + str(p1.y) + "\n33\n" + str(p1.z) + "\n" + result += "14\n" + str(p2.x) + "\n24\n" + str(p2.y) + "\n34\n" + str(p2.z) + "\n" elif utils.get_type(obj) == "Annotation": # Only for App::Annotation @@ -104,7 +104,7 @@ def get_dxf(obj, direction=None): result += "7\nSTANDARD\n" count += 1 - elif hasattr(obj, 'Shape'): + elif hasattr(obj, "Shape"): # TODO do this the Draft way, for ex. using polylines and rectangles if not direction: direction = App.Vector(0, 0, -1) @@ -117,8 +117,7 @@ def get_dxf(obj, direction=None): except Exception: # TODO: trap only specific exception. # Impossible to generate DXF from Shape? Which exception is throw? - _wrn("get_dxf: " - "unable to project '{}' to {}".format(obj.Label, direction)) + _wrn("get_dxf: " "unable to project '{}' to {}".format(obj.Label, direction)) else: result += d else: @@ -127,11 +126,10 @@ def get_dxf(obj, direction=None): return result -def getDXF(obj, - direction=None): +def getDXF(obj, direction=None): """Return DXF string of the object. DEPRECATED. Use 'get_dxf'.""" utils.use_instead("get_dxf") - return get_dxf(obj, - direction=direction) + return get_dxf(obj, direction=direction) + ## @} diff --git a/src/Mod/Draft/draftfunctions/extrude.py b/src/Mod/Draft/draftfunctions/extrude.py index 970bdaa0df..421060a0c5 100644 --- a/src/Mod/Draft/draftfunctions/extrude.py +++ b/src/Mod/Draft/draftfunctions/extrude.py @@ -55,9 +55,10 @@ def extrude(obj, vector, solid=False): newobj.Solid = solid if App.GuiUp: obj.ViewObject.Visibility = False - gui_utils.format_object(newobj,obj) + gui_utils.format_object(newobj, obj) gui_utils.select(newobj) return newobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/fuse.py b/src/Mod/Draft/draftfunctions/fuse.py index 152baaf6b8..9a84e6b59c 100644 --- a/src/Mod/Draft/draftfunctions/fuse.py +++ b/src/Mod/Draft/draftfunctions/fuse.py @@ -49,6 +49,7 @@ def fuse(object1, object2): return import Part import DraftGeomUtils + # testing if we have holes: holes = False fshape = object1.Shape.fuse(object2.Shape) @@ -74,9 +75,10 @@ def fuse(object1, object2): if App.GuiUp: object1.ViewObject.Visibility = False object2.ViewObject.Visibility = False - gui_utils.format_object(obj,object1) + gui_utils.format_object(obj, object1) gui_utils.select(obj) return obj + ## @} diff --git a/src/Mod/Draft/draftfunctions/heal.py b/src/Mod/Draft/draftfunctions/heal.py index fe7cdd1f24..47766e53b4 100644 --- a/src/Mod/Draft/draftfunctions/heal.py +++ b/src/Mod/Draft/draftfunctions/heal.py @@ -61,7 +61,7 @@ def heal(objlist=None, delete=True, reparent=True): else: print("Manual mode: Force-healing selected objects…") - if not isinstance(objlist,list): + if not isinstance(objlist, list): objlist = [objlist] dellist = [] @@ -70,34 +70,34 @@ def heal(objlist=None, delete=True, reparent=True): for obj in objlist: dtype = utils.get_type(obj) ftype = obj.TypeId - if ftype in ["Part::FeaturePython","App::FeaturePython","Part::Part2DObjectPython"]: + if ftype in ["Part::FeaturePython", "App::FeaturePython", "Part::Part2DObjectPython"]: proxy = obj.Proxy - if hasattr(obj,"ViewObject"): - if hasattr(obj.ViewObject,"Proxy"): + if hasattr(obj, "ViewObject"): + if hasattr(obj.ViewObject, "Proxy"): proxy = obj.ViewObject.Proxy - if (proxy == 1) or (dtype in ["Unknown","Part"]) or (not auto): + if (proxy == 1) or (dtype in ["Unknown", "Part"]) or (not auto): got = True dellist.append(obj.Name) props = obj.PropertiesList if ("Dimline" in props) and ("Start" in props): print("Healing " + obj.Name + " of type Dimension") - nobj = make_copy(obj,force="Dimension",reparent=reparent) + nobj = make_copy(obj, force="Dimension", reparent=reparent) elif ("Height" in props) and ("Length" in props): print("Healing " + obj.Name + " of type Rectangle") - nobj = make_copy(obj,force="Rectangle",reparent=reparent) + nobj = make_copy(obj, force="Rectangle", reparent=reparent) elif ("Points" in props) and ("Closed" in props): if "BSpline" in obj.Name: print("Healing " + obj.Name + " of type BSpline") - nobj = make_copy(obj,force="BSpline",reparent=reparent) + nobj = make_copy(obj, force="BSpline", reparent=reparent) else: print("Healing " + obj.Name + " of type Wire") - nobj = make_copy(obj,force="Wire",reparent=reparent) + nobj = make_copy(obj, force="Wire", reparent=reparent) elif ("Radius" in props) and ("FirstAngle" in props): print("Healing " + obj.Name + " of type Circle") - nobj = make_copy(obj,force="Circle",reparent=reparent) + nobj = make_copy(obj, force="Circle", reparent=reparent) elif ("DrawMode" in props) and ("FacesNumber" in props): print("Healing " + obj.Name + " of type Polygon") - nobj = make_copy(obj,force="Polygon",reparent=reparent) + nobj = make_copy(obj, force="Polygon", reparent=reparent) else: dellist.pop() print("Object " + obj.Name + " is not healable") @@ -105,10 +105,11 @@ def heal(objlist=None, delete=True, reparent=True): if not got: print("No object seems to need healing") else: - print("Healed ",len(dellist)," objects") + print("Healed ", len(dellist), " objects") if dellist and delete: for n in dellist: App.ActiveDocument.removeObject(n) + ## @} diff --git a/src/Mod/Draft/draftfunctions/join.py b/src/Mod/Draft/draftfunctions/join.py index 85a9ca81e6..6b55fa7769 100644 --- a/src/Mod/Draft/draftfunctions/join.py +++ b/src/Mod/Draft/draftfunctions/join.py @@ -31,7 +31,7 @@ import FreeCAD as App import DraftVecUtils -def join_wires(wires, joinAttempts = 0): +def join_wires(wires, joinAttempts=0): """join_wires(objects): merges a set of wires where possible, if any of those wires have a coincident start and end point""" wires = list(wires) @@ -58,10 +58,13 @@ def join_two_wires(wire1, wire2): """ wire1AbsPoints = [wire1.Placement.multVec(point) for point in wire1.Points] wire2AbsPoints = [wire2.Placement.multVec(point) for point in wire2.Points] - if ((DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[-1]) - and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[0])) - or (DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0]) - and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[-1]))): + if ( + DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[-1]) + and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[0]) + ) or ( + DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0]) + and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[-1]) + ): wire2AbsPoints.pop() wire1.Closed = True elif DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0]): @@ -76,10 +79,9 @@ def join_two_wires(wire1, wire2): else: return False wire2AbsPoints.pop(0) - wire1.Points = ([wire1.Placement.inverse().multVec(point) - for point in wire1AbsPoints] + - [wire1.Placement.inverse().multVec(point) - for point in wire2AbsPoints]) + wire1.Points = [wire1.Placement.inverse().multVec(point) for point in wire1AbsPoints] + [ + wire1.Placement.inverse().multVec(point) for point in wire2AbsPoints + ] App.ActiveDocument.removeObject(wire2.Name) return True diff --git a/src/Mod/Draft/draftfunctions/mirror.py b/src/Mod/Draft/draftfunctions/mirror.py index 21ce9aa825..add29d290b 100644 --- a/src/Mod/Draft/draftfunctions/mirror.py +++ b/src/Mod/Draft/draftfunctions/mirror.py @@ -80,11 +80,11 @@ def mirror(objlist, p1, p2): """ if not objlist: - _err(translate("draft","No object given")) + _err(translate("draft", "No object given")) return if p1 == p2: - _err(translate("draft","The two points are coincident")) + _err(translate("draft", "The two points are coincident")) return if not isinstance(objlist, list): @@ -110,4 +110,5 @@ def mirror(objlist, p1, p2): return result + ## @} diff --git a/src/Mod/Draft/draftfunctions/move.py b/src/Mod/Draft/draftfunctions/move.py index fcb0ae4588..d2d169bcc0 100644 --- a/src/Mod/Draft/draftfunctions/move.py +++ b/src/Mod/Draft/draftfunctions/move.py @@ -92,7 +92,9 @@ def move(selection, vector, copy=False, subelements=False): if copy: for obj in objs: if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups: - newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name)) + newgroups[obj.Name] = obj.Document.addObject( + obj.TypeId, utils.get_real_name(obj.Name) + ) for idx, obj in enumerate(objs): newobj = None @@ -217,7 +219,7 @@ def move_edge(obj, edge_idx, vector, global_place=None): if utils.is_closed_edge(edge_idx, obj): move_vertex(obj, 0, vector, global_place) else: - move_vertex(obj, edge_idx+1, vector, global_place) + move_vertex(obj, edge_idx + 1, vector, global_place) def copy_moved_edge(obj, edge_idx, vector, global_place=None): @@ -233,9 +235,10 @@ def copy_moved_edge(obj, edge_idx, vector, global_place=None): if utils.is_closed_edge(edge_idx, obj): vertex2 = glp.multVec(obj.Points[0]).add(vector) else: - vertex2 = glp.multVec(obj.Points[edge_idx+1]).add(vector) + vertex2 = glp.multVec(obj.Points[edge_idx + 1]).add(vector) newobj = make_line.make_line(vertex1, vertex2) gui_utils.format_object(newobj, obj) return newobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/offset.py b/src/Mod/Draft/draftfunctions/offset.py index 3a9e8f227f..18271d239e 100644 --- a/src/Mod/Draft/draftfunctions/offset.py +++ b/src/Mod/Draft/draftfunctions/offset.py @@ -70,43 +70,51 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): """ import Part import DraftGeomUtils + newwire = None delete = None - if (copy is False - and (utils.get_type(obj).startswith("Sketcher::") - or utils.get_type(obj).startswith("Part::") - or utils.get_type(obj).startswith("PartDesign::"))): # For PartDesign_SubShapeBinders which can reference sketches. - print("the offset tool is currently unable to offset a non-Draft object directly - Creating a copy") + if copy is False and ( + utils.get_type(obj).startswith("Sketcher::") + or utils.get_type(obj).startswith("Part::") + or utils.get_type(obj).startswith("PartDesign::") + ): # For PartDesign_SubShapeBinders which can reference sketches. + print( + "the offset tool is currently unable to offset a non-Draft object directly - Creating a copy" + ) copy = True - def getRect(p,obj): + def getRect(p, obj): """returns length,height,placement""" pl = obj.Placement.copy() pl.Base = p[0] diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) - nb = DraftVecUtils.project(diag,bb) - nh = DraftVecUtils.project(diag,bh) - if obj.Length.Value < 0: l = -nb.Length - else: l = nb.Length - if obj.Height.Value < 0: h = -nh.Length - else: h = nh.Length - return l,h,pl + nb = DraftVecUtils.project(diag, bb) + nh = DraftVecUtils.project(diag, bh) + if obj.Length.Value < 0: + l = -nb.Length + else: + l = nb.Length + if obj.Height.Value < 0: + h = -nh.Length + else: + h = nh.Length + return l, h, pl - def getRadius(obj,delta): + def getRadius(obj, delta): """returns a new radius for a regular polygon""" - an = math.pi/obj.FacesNumber - nr = DraftVecUtils.rotate(delta,-an) - nr.multiply(1/math.cos(an)) + an = math.pi / obj.FacesNumber + nr = DraftVecUtils.rotate(delta, -an) + nr.multiply(1 / math.cos(an)) nr = obj.Shape.Vertexes[0].Point.add(nr) nr = nr.sub(obj.Placement.Base) nr = nr.Length if obj.DrawMode == "inscribed": return nr else: - return nr * math.cos(math.pi/obj.FacesNumber) + return nr * math.cos(math.pi / obj.FacesNumber) newwire = None if utils.get_type(obj) == "Circle": @@ -117,27 +125,29 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): if sym: d1 = App.Vector(delta).multiply(0.5) d2 = d1.negative() - n1 = DraftGeomUtils.offsetWire(obj.Shape,d1) - n2 = DraftGeomUtils.offsetWire(obj.Shape,d2) + n1 = DraftGeomUtils.offsetWire(obj.Shape, d1) + n2 = DraftGeomUtils.offsetWire(obj.Shape, d2) else: - if isinstance(delta,float) and (len(obj.Shape.Edges) == 1): + if isinstance(delta, float) and (len(obj.Shape.Edges) == 1): # circle c = obj.Shape.Edges[0].Curve - nc = Part.Circle(c.Center,c.Axis,delta) + nc = Part.Circle(c.Center, c.Axis, delta) if len(obj.Shape.Vertexes) > 1: - nc = Part.ArcOfCircle(nc,obj.Shape.Edges[0].FirstParameter,obj.Shape.Edges[0].LastParameter) + nc = Part.ArcOfCircle( + nc, obj.Shape.Edges[0].FirstParameter, obj.Shape.Edges[0].LastParameter + ) newwire = Part.Wire(nc.toShape()) p = [] else: - newwire = DraftGeomUtils.offsetWire(obj.Shape,delta) + newwire = DraftGeomUtils.offsetWire(obj.Shape, delta) if DraftGeomUtils.hasCurves(newwire) and copy: p = [] else: p = DraftGeomUtils.getVerts(newwire) if occ: - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") - newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape,delta,occ=True) - gui_utils.formatObject(newobj,obj) + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") + newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape, delta, occ=True) + gui_utils.formatObject(newobj, obj) if not copy: delete = obj.Name elif bind: @@ -151,35 +161,36 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): if s1 and s2: w1 = s1.Edges w2 = s2.Edges - w3 = Part.LineSegment(s1.Vertexes[0].Point,s2.Vertexes[0].Point).toShape() - w4 = Part.LineSegment(s1.Vertexes[-1].Point,s2.Vertexes[-1].Point).toShape() - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") - newobj.Shape = Part.Face(Part.Wire(w1+[w3]+w2+[w4])) + w3 = Part.LineSegment(s1.Vertexes[0].Point, s2.Vertexes[0].Point).toShape() + w4 = Part.LineSegment(s1.Vertexes[-1].Point, s2.Vertexes[-1].Point).toShape() + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") + newobj.Shape = Part.Face(Part.Wire(w1 + [w3] + w2 + [w4])) else: print("Draft.offset: Unable to bind wires") else: - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = Part.Face(obj.Shape.Wires[0]) if not copy: delete = obj.Name elif copy: newobj = None - if sym: return None + if sym: + return None if utils.get_type(obj) == "Wire": if p: newobj = make_wire(p) newobj.Closed = obj.Closed elif newwire: - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire else: print("Draft.offset: Unable to duplicate this object") elif utils.get_type(obj) == "Rectangle": if p: - length,height,plac = getRect(p,obj) - newobj = make_rectangle(length,height,plac) + length, height, plac = getRect(p, obj) + newobj = make_rectangle(length, height, plac) elif newwire: - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire else: print("Draft.offset: Unable to duplicate this object") @@ -192,7 +203,7 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): elif utils.get_type(obj) == "Polygon": pl = obj.Placement newobj = make_polygon(obj.FacesNumber) - newobj.Radius = getRadius(obj,delta) + newobj.Radius = getRadius(obj, delta) newobj.DrawMode = obj.DrawMode newobj.Placement = pl elif utils.get_type(obj) == "BSpline": @@ -207,37 +218,38 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): except Part.OCCError: pass if (not newobj) and newwire: - newobj = App.ActiveDocument.addObject("Part::Feature","Offset") + newobj = App.ActiveDocument.addObject("Part::Feature", "Offset") newobj.Shape = newwire if not newobj: print("Draft.offset: Unable to create an offset") if newobj: - gui_utils.formatObject(newobj,obj) + gui_utils.formatObject(newobj, obj) else: newobj = None - if sym: return None + if sym: + return None if utils.get_type(obj) == "Wire": if obj.Base or obj.Tool: App.Console.PrintWarning("Warning: object history removed\n") obj.Base = None obj.Tool = None - obj.Placement = App.Placement() # p points are in the global coordinate system + obj.Placement = App.Placement() # p points are in the global coordinate system obj.Points = p elif utils.get_type(obj) == "BSpline": - #print(delta) + # print(delta) obj.Points = delta - #print("done") + # print("done") elif utils.get_type(obj) == "Rectangle": - length,height,plac = getRect(p,obj) + length, height, plac = getRect(p, obj) obj.Placement = plac obj.Length = length obj.Height = height elif utils.get_type(obj) == "Circle": obj.Radius = delta elif utils.get_type(obj) == "Polygon": - obj.Radius = getRadius(obj,delta) - elif utils.get_type(obj) == 'Part': - print("unsupported object") # TODO + obj.Radius = getRadius(obj, delta) + elif utils.get_type(obj) == "Part": + print("unsupported object") # TODO newobj = obj if copy and params.get_param("selectBaseObjects"): gui_utils.select(obj) @@ -247,4 +259,5 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False): App.ActiveDocument.removeObject(delete) return newobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/rotate.py b/src/Mod/Draft/draftfunctions/rotate.py index 028c50c832..acf1931b9e 100644 --- a/src/Mod/Draft/draftfunctions/rotate.py +++ b/src/Mod/Draft/draftfunctions/rotate.py @@ -42,8 +42,14 @@ from draftutils import params from draftutils import utils -def rotate(selection, angle, center=App.Vector(0, 0, 0), - axis=App.Vector(0, 0, 1), copy=False, subelements=False): +def rotate( + selection, + angle, + center=App.Vector(0, 0, 0), + axis=App.Vector(0, 0, 1), + copy=False, + subelements=False, +): """rotate(selection, angle, [center], [axis], [copy], [subelements]) Rotates or copies selected objects. @@ -80,8 +86,16 @@ def rotate(selection, angle, center=App.Vector(0, 0, 0), single object / list with 2 or more objects / empty list The objects (or their copies). """ - utils.type_check([(angle, (float, int)), (center, App.Vector), - (axis, App.Vector), (copy, bool), (subelements, bool)], "rotate") + utils.type_check( + [ + (angle, (float, int)), + (center, App.Vector), + (axis, App.Vector), + (copy, bool), + (subelements, bool), + ], + "rotate", + ) if not isinstance(selection, list): selection = [selection] if not selection: @@ -106,7 +120,9 @@ def rotate(selection, angle, center=App.Vector(0, 0, 0), if copy: for obj in objs: if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups: - newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name)) + newgroups[obj.Name] = obj.Document.addObject( + obj.TypeId, utils.get_real_name(obj.Name) + ) for idx, obj in enumerate(objs): newobj = None @@ -230,9 +246,8 @@ def rotate_vertex(obj, vert_idx, angle, center, axis, global_place=None): glp = global_place points = obj.Points points[vert_idx] = glp.inverse().multVec( - rotate_vector_from_center( - glp.multVec(points[vert_idx]), - angle, axis, center)) + rotate_vector_from_center(glp.multVec(points[vert_idx]), angle, axis, center) + ) obj.Points = points @@ -245,7 +260,7 @@ def rotate_edge(obj, edge_idx, angle, center, axis, global_place=None): if utils.is_closed_edge(edge_idx, obj): rotate_vertex(obj, 0, angle, center, axis, global_place) else: - rotate_vertex(obj, edge_idx+1, angle, center, axis, global_place) + rotate_vertex(obj, edge_idx + 1, angle, center, axis, global_place) def copy_rotated_edge(obj, edge_idx, angle, center, axis, global_place=None): @@ -257,19 +272,16 @@ def copy_rotated_edge(obj, edge_idx, angle, center, axis, global_place=None): glp = obj.getGlobalPlacement() else: glp = global_place - vertex1 = rotate_vector_from_center( - glp.multVec(obj.Points[edge_idx]), - angle, axis, center) + vertex1 = rotate_vector_from_center(glp.multVec(obj.Points[edge_idx]), angle, axis, center) if utils.is_closed_edge(edge_idx, obj): - vertex2 = rotate_vector_from_center( - glp.multVec(obj.Points[0]), - angle, axis, center) + vertex2 = rotate_vector_from_center(glp.multVec(obj.Points[0]), angle, axis, center) else: vertex2 = rotate_vector_from_center( - glp.multVec(obj.Points[edge_idx+1]), - angle, axis, center) + glp.multVec(obj.Points[edge_idx + 1]), angle, axis, center + ) newobj = make_line.make_line(vertex1, vertex2) gui_utils.format_object(newobj, obj) return newobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/scale.py b/src/Mod/Draft/draftfunctions/scale.py index eae3c27e09..bd2553ab71 100644 --- a/src/Mod/Draft/draftfunctions/scale.py +++ b/src/Mod/Draft/draftfunctions/scale.py @@ -43,8 +43,7 @@ from draftutils import params from draftutils import utils -def scale(selection, scale, center=App.Vector(0, 0, 0), - copy=False, clone=False, subelements=False): +def scale(selection, scale, center=App.Vector(0, 0, 0), copy=False, clone=False, subelements=False): """scale(selection, scale, [center], [copy], [clone], [subelements]) Scales or copies selected objects. @@ -82,8 +81,16 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), single object / list with 2 or more objects / empty list The objects (or their copies). """ - utils.type_check([(scale, App.Vector), (center, App.Vector), - (copy, bool), (clone, bool), (subelements, bool)], "scale") + utils.type_check( + [ + (scale, App.Vector), + (center, App.Vector), + (copy, bool), + (clone, bool), + (subelements, bool), + ], + "scale", + ) sx, sy, sz = scale if sx * sy * sz == 0: raise ValueError("Zero component in scale vector") @@ -98,9 +105,13 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), if subelements: return _scale_subelements(selection, scale, center, copy) else: - objs, parent_places, sel_info = utils._modifiers_process_selection(selection, (copy or clone), scale=True) + objs, parent_places, sel_info = utils._modifiers_process_selection( + selection, (copy or clone), scale=True + ) else: - objs = utils._modifiers_filter_objects(utils._modifiers_get_group_contents(selection), (copy or clone), scale=True) + objs = utils._modifiers_filter_objects( + utils._modifiers_get_group_contents(selection), (copy or clone), scale=True + ) parent_places = None sel_info = None @@ -113,7 +124,9 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), if copy or clone: for obj in objs: if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups: - newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name)) + newgroups[obj.Name] = obj.Document.addObject( + obj.TypeId, utils.get_real_name(obj.Name) + ) for idx, obj in enumerate(objs): newobj = None @@ -174,7 +187,9 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), continue if sx == sy == sz: newobj = make_clone.make_clone(obj, forcedraft=True) - newobj.Placement.Base = scale_vector_from_center(newobj.Placement.Base, scale, center) + newobj.Placement.Base = scale_vector_from_center( + newobj.Placement.Base, scale, center + ) newobj.Scale = scale else: if parent_place.isIdentity(): @@ -221,10 +236,10 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), else: pla = parent_place * obj.Placement pts = [ - App.Vector (0.0, 0.0, 0.0), - App.Vector (obj.Length.Value, 0.0, 0.0), - App.Vector (obj.Length.Value, obj.Height.Value, 0.0), - App.Vector (0.0, obj.Height.Value, 0.0) + App.Vector(0.0, 0.0, 0.0), + App.Vector(obj.Length.Value, 0.0, 0.0), + App.Vector(obj.Length.Value, obj.Height.Value, 0.0), + App.Vector(0.0, obj.Height.Value, 0.0), ] pts = [pla.multVec(p) for p in pts] pts = [scale_vector_from_center(p, scale, center) for p in pts] @@ -232,7 +247,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), x_vec = pts[1] - pts[0] y_vec = pts[3] - pts[0] ang = x_vec.getAngle(y_vec) - if math.isclose(ang % math.pi/2, math.pi/4, abs_tol=1e-6): + if math.isclose(ang % math.pi / 2, math.pi / 4, abs_tol=1e-6): if copy: newobj = make_copy.make_copy(obj) newobj.Placement = pla @@ -275,6 +290,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), if create_non_parametric: import Part + if parent_place.isIdentity(): pla = obj.Placement else: @@ -288,6 +304,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0), if App.GuiUp: if utils.get_type(obj) in ("Circle", "Ellipse"): from draftviewproviders.view_base import ViewProviderDraft + ViewProviderDraft(newobj.ViewObject) else: newobj.ViewObject.Proxy = 0 @@ -384,7 +401,7 @@ def scale_edge(obj, edge_idx, scale, center, global_place=None): if utils.is_closed_edge(edge_idx, obj): scale_vertex(obj, 0, scale, center, global_place) else: - scale_vertex(obj, edge_idx+1, scale, center, global_place) + scale_vertex(obj, edge_idx + 1, scale, center, global_place) def copy_scaled_edge(obj, edge_idx, scale, center, global_place=None): @@ -400,9 +417,10 @@ def copy_scaled_edge(obj, edge_idx, scale, center, global_place=None): if utils.is_closed_edge(edge_idx, obj): vertex2 = scale_vector_from_center(glp.multVec(obj.Points[0]), scale, center) else: - vertex2 = scale_vector_from_center(glp.multVec(obj.Points[edge_idx+1]), scale, center) + vertex2 = scale_vector_from_center(glp.multVec(obj.Points[edge_idx + 1]), scale, center) newobj = make_line.make_line(vertex1, vertex2) gui_utils.format_object(newobj, obj) return newobj + ## @} diff --git a/src/Mod/Draft/draftfunctions/split.py b/src/Mod/Draft/draftfunctions/split.py index db8231e626..b14179e579 100644 --- a/src/Mod/Draft/draftfunctions/split.py +++ b/src/Mod/Draft/draftfunctions/split.py @@ -30,6 +30,7 @@ from draftmake import make_copy from draftutils import utils + def split(wire, newPoint, edgeIndex): if utils.get_type(wire) != "Wire": return None @@ -44,8 +45,10 @@ def split_closed_wire(wire, edgeIndex): if edgeIndex == len(wire.Points): new.Points = [wire.Points[0], wire.Points[-1]] else: - new.Points = [wire.Points[edgeIndex-1], wire.Points[edgeIndex]] - wire.Points = list(reversed(wire.Points[0:edgeIndex])) + list(reversed(wire.Points[edgeIndex:])) + new.Points = [wire.Points[edgeIndex - 1], wire.Points[edgeIndex]] + wire.Points = list(reversed(wire.Points[0:edgeIndex])) + list( + reversed(wire.Points[edgeIndex:]) + ) return new diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index fd40e32d71..3f5fff1cf0 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -21,8 +21,7 @@ # * USA * # * * # *************************************************************************** -"""Provides functions to return the SVG representation of various shapes. -""" +"""Provides functions to return the SVG representation of various shapes.""" ## @package svg # \ingroup draftfunctions # \brief Provides functions to return the SVG representation of shapes. @@ -67,7 +66,7 @@ def get_line_style(line_style, scale): style = style.split(",") try: # scale dashes - style = ",".join([str(float(d)/scale) for d in style]) + style = ",".join([str(float(d) / scale) for d in style]) # print("lstyle ", style) except Exception: # TODO: trap only specific exception; what is the problem? @@ -91,7 +90,7 @@ def get_pattern(pat): if pat in patterns: return patterns[pat][0] - return '' + return "" def getPattern(pat): @@ -100,8 +99,7 @@ def getPattern(pat): return get_pattern(pat) -def get_arrow(obj, - arrowtype, point, arrowsize, color, linewidth, angle=0): +def get_arrow(obj, arrowtype, point, arrowsize, color, linewidth, angle=0): """Get the SVG representation from an arrow.""" svg = "" vobj = _get_view_object(obj) @@ -110,54 +108,52 @@ def get_arrow(obj, return svg _cx_cy_r = 'cx="{}" cy="{}" r="{}"'.format(point.x, point.y, arrowsize) - _rotate = 'rotate({},{},{})'.format(math.degrees(angle), - point.x, point.y) - _transl = 'translate({},{})'.format(point.x, point.y) - _scale = 'scale({size},{size})'.format(size=arrowsize) + _rotate = "rotate({},{},{})".format(math.degrees(angle), point.x, point.y) + _transl = "translate({},{})".format(point.x, point.y) + _scale = "scale({size},{size})".format(size=arrowsize) _style = 'style="stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:square"' if arrowtype == "Circle": - svg += ' math.pi/2: - tangle = tangle-math.pi + if tangle > math.pi / 2: + tangle = tangle - math.pi # elif (tangle <= -math.pi/2) or (tangle > math.pi/2): # tangle = tangle + math.pi @@ -297,28 +295,28 @@ def _svg_dimension(obj, plane, scale, linewidth, fontsize, # " text: ", prx.string) if abs(tangle + math.radians(rotation)) < 0.0001: tangle += math.pi - _v = App.Vector(0, 2.0/scale, 0) + _v = App.Vector(0, 2.0 / scale, 0) _rot = DraftVecUtils.rotate(_v, tangle) tbase = tbase + _rot if not nolines: - svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' ' - svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' ' - svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' ' - svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" ' + svg += 'd="M ' + str(p1.x) + " " + str(p1.y) + " " + svg += "L " + str(p2.x) + " " + str(p2.y) + " " + svg += "L " + str(p3.x) + " " + str(p3.y) + " " + svg += "L " + str(p4.x) + " " + str(p4.y) + '" ' else: tangle = 0 if rotation != 0: tangle = -math.radians(rotation) - tbase = tbase + App.Vector(0, -2.0/scale, 0) + tbase = tbase + App.Vector(0, -2.0 / scale, 0) if not nolines: - svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' ' - svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' ' - svg += 'L ' + str(p2a.x) + ' ' + str(p2a.y) + ' ' - svg += 'M ' + str(p2b.x) + ' ' + str(p2b.y) + ' ' - svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' ' - svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" ' + svg += 'd="M ' + str(p1.x) + " " + str(p1.y) + " " + svg += "L " + str(p2.x) + " " + str(p2.y) + " " + svg += "L " + str(p2a.x) + " " + str(p2a.y) + " " + svg += "M " + str(p2b.x) + " " + str(p2b.y) + " " + svg += "L " + str(p3.x) + " " + str(p3.y) + " " + svg += "L " + str(p4.x) + " " + str(p4.y) + '" ' if not nolines: svg += 'fill="none" stroke="' @@ -326,66 +324,78 @@ def _svg_dimension(obj, plane, scale, linewidth, fontsize, svg += 'stroke-width="' + str(linewidth) + ' px" ' svg += 'style="stroke-width:' + str(linewidth) svg += ';stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:square" ' - svg += 'freecad:basepoint1="'+str(p1.x)+' '+str(p1.y)+'" ' - svg += 'freecad:basepoint2="'+str(p4.x)+' '+str(p4.y)+'" ' - svg += 'freecad:dimpoint="'+str(p2.x)+' '+str(p2.y)+'"' - svg += '/>\n' + svg += 'freecad:basepoint1="' + str(p1.x) + " " + str(p1.y) + '" ' + svg += 'freecad:basepoint2="' + str(p4.x) + " " + str(p4.y) + '" ' + svg += 'freecad:dimpoint="' + str(p2.x) + " " + str(p2.y) + '"' + svg += "/>\n" # drawing dimension and extension lines overshoots if hasattr(vobj, "DimOvershoot") and vobj.DimOvershoot.Value: - shootsize = vobj.DimOvershoot.Value/pointratio - svg += get_overshoot(p2, shootsize, stroke, - linewidth, angle) - svg += get_overshoot(p3, shootsize, stroke, - linewidth, angle + math.pi) + shootsize = vobj.DimOvershoot.Value / pointratio + svg += get_overshoot(p2, shootsize, stroke, linewidth, angle) + svg += get_overshoot(p3, shootsize, stroke, linewidth, angle + math.pi) if hasattr(vobj, "ExtOvershoot") and vobj.ExtOvershoot.Value: - shootsize = vobj.ExtOvershoot.Value/pointratio + shootsize = vobj.ExtOvershoot.Value / pointratio shootangle = -DraftVecUtils.angle(p1 - p2) - svg += get_overshoot(p2, shootsize, stroke, - linewidth, shootangle) - svg += get_overshoot(p3, shootsize, stroke, - linewidth, shootangle) + svg += get_overshoot(p2, shootsize, stroke, linewidth, shootangle) + svg += get_overshoot(p3, shootsize, stroke, linewidth, shootangle) # drawing arrows - if hasattr(vobj, "ArrowTypeStart") \ - and hasattr(vobj, "ArrowTypeEnd") \ - and hasattr(vobj, "ArrowSizeStart") \ - and hasattr(vobj, "ArrowSizeEnd"): + if ( + hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + ): if getattr(vobj, "FlipArrows", False): angle = angle + math.pi if getattr(vobj, "FlipText", False): angle = angle + math.pi - svg += get_arrow(obj, - vobj.ArrowTypeStart, - p2, - vobj.ArrowSizeStart.Value/pointratio, - stroke, - linewidth, - angle) + svg += get_arrow( + obj, + vobj.ArrowTypeStart, + p2, + vobj.ArrowSizeStart.Value / pointratio, + stroke, + linewidth, + angle, + ) - svg += get_arrow(obj, - vobj.ArrowTypeEnd, - p3, - vobj.ArrowSizeEnd.Value/pointratio, - stroke, - linewidth, - angle + math.pi) + svg += get_arrow( + obj, + vobj.ArrowTypeEnd, + p3, + vobj.ArrowSizeEnd.Value / pointratio, + stroke, + linewidth, + angle + math.pi, + ) # drawing text - svg += svgtext.get_text(plane, techdraw, - tstroke, fontsize, vobj.FontName, - tangle, tbase, prx.string) + svg += svgtext.get_text( + plane, techdraw, tstroke, fontsize, vobj.FontName, tangle, tbase, prx.string + ) return svg -def get_svg(obj, - scale=1, linewidth=0.35, fontsize=12, - fillstyle="shape color", direction=None, linestyle=None, - color=None, linespacing=None, techdraw=False, rotation=0, - fillspaces=False, override=True): +def get_svg( + obj, + scale=1, + linewidth=0.35, + fontsize=12, + fillstyle="shape color", + direction=None, + linestyle=None, + color=None, + linespacing=None, + techdraw=False, + rotation=0, + fillspaces=False, + override=True, +): """Return a string containing an SVG representation of the object. Paramaeters @@ -434,17 +444,22 @@ def get_svg(obj, """ # If this is a group, recursively call this function to gather # all the SVG strings from the contents of the group. - if (obj.isDerivedFrom("App::DocumentObjectGroup") - or utils.get_type(obj) in ["Layer", "BuildingPart", "IfcGroup"] - or obj.isDerivedFrom("App::LinkGroup") - or (obj.isDerivedFrom("App::Link") - and obj.LinkedObject.isDerivedFrom("App::DocumentObjectGroup"))): + if ( + obj.isDerivedFrom("App::DocumentObjectGroup") + or utils.get_type(obj) in ["Layer", "BuildingPart", "IfcGroup"] + or obj.isDerivedFrom("App::LinkGroup") + or ( + obj.isDerivedFrom("App::Link") + and obj.LinkedObject.isDerivedFrom("App::DocumentObjectGroup") + ) + ): hidden_doc = None - if (obj.isDerivedFrom("App::LinkGroup") - or (obj.isDerivedFrom("App::Link") - and obj.LinkedObject.isDerivedFrom("App::DocumentObjectGroup"))): + if obj.isDerivedFrom("App::LinkGroup") or ( + obj.isDerivedFrom("App::Link") + and obj.LinkedObject.isDerivedFrom("App::DocumentObjectGroup") + ): if obj.Placement.isIdentity(): if obj.isDerivedFrom("App::LinkGroup"): group = obj.ElementList @@ -467,11 +482,21 @@ def get_svg(obj, svg = "" for child in group: - svg += get_svg(child, - scale, linewidth, fontsize, - fillstyle, direction, linestyle, - color, linespacing, techdraw, - rotation, fillspaces, override) + svg += get_svg( + child, + scale, + linewidth, + fontsize, + fillstyle, + direction, + linestyle, + color, + linespacing, + techdraw, + rotation, + fillspaces, + override, + ) if hidden_doc is not None: try: @@ -492,11 +517,21 @@ def get_svg(obj, new.Placement = obj.Placement * new.Placement else: new.Placement = obj.Placement - svg = get_svg(new, - scale, linewidth, fontsize, - fillstyle, direction, linestyle, - color, linespacing, techdraw, - rotation, fillspaces, override) + svg = get_svg( + new, + scale, + linewidth, + fontsize, + fillstyle, + direction, + linestyle, + color, + linespacing, + techdraw, + rotation, + fillspaces, + override, + ) try: App.closeDocument(hidden_doc.Name) except: @@ -507,7 +542,7 @@ def get_svg(obj, pathdata = [] svg = "" - linewidth = float(linewidth)/scale + linewidth = float(linewidth) / scale if not override: if vobj is not None and hasattr(vobj, "LineWidth"): if hasattr(vobj.LineWidth, "Value"): @@ -516,9 +551,9 @@ def get_svg(obj, lw = vobj.LineWidth linewidth = lw * linewidth - fontsize = (float(fontsize)/scale)/2 + fontsize = (float(fontsize) / scale) / 2 if linespacing: - linespacing = float(linespacing)/scale + linespacing = float(linespacing) / scale else: linespacing = 0.5 @@ -532,9 +567,9 @@ def get_svg(obj, if isinstance(direction, App.Vector): if direction != App.Vector(0, 0, 0): plane = WorkingPlane.PlaneBase() - plane.align_to_point_and_axis_svg(App.Vector(0, 0, 0), - direction.negative().negative(), - 0) + plane.align_to_point_and_axis_svg( + App.Vector(0, 0, 0), direction.negative().negative(), 0 + ) else: raise ValueError("'direction' cannot be: Vector(0, 0, 0)") elif isinstance(direction, WorkingPlane.PlaneBase): @@ -573,13 +608,14 @@ def get_svg(obj, pass elif isinstance(obj, Part.Shape): - svg = _svg_shape(svg, obj, plane, - fillstyle, pathdata, stroke, linewidth, lstyle) + svg = _svg_shape(svg, obj, plane, fillstyle, pathdata, stroke, linewidth, lstyle) - elif (utils.get_type(obj) in ["Dimension", "LinearDimension"] - or (utils.get_type(obj) == "IfcAnnotation" and obj.ObjectType == "DIMENSION")): - svg = _svg_dimension(obj, plane, scale, linewidth, fontsize, - stroke, tstroke, pointratio, techdraw, rotation) + elif utils.get_type(obj) in ["Dimension", "LinearDimension"] or ( + utils.get_type(obj) == "IfcAnnotation" and obj.ObjectType == "DIMENSION" + ): + svg = _svg_dimension( + obj, plane, scale, linewidth, fontsize, stroke, tstroke, pointratio, techdraw, rotation + ) elif utils.get_type(obj) == "AngularDimension": if not App.GuiUp: @@ -593,50 +629,79 @@ def get_svg(obj, # drawing arc fill = "none" if vobj.DisplayMode == "World": - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=None, - edges=[prx.circle]) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=[prx.circle], + ) else: if hasattr(prx, "circle1"): - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=None, - edges=[prx.circle1]) - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=None, - edges=[prx.circle2]) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=[prx.circle1], + ) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=[prx.circle2], + ) else: - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=None, - edges=[prx.circle]) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=[prx.circle], + ) # drawing arrows - if hasattr(vobj, "ArrowTypeStart") \ - and hasattr(vobj, "ArrowTypeEnd") \ - and hasattr(vobj, "ArrowSizeStart") \ - and hasattr(vobj, "ArrowSizeEnd"): + if ( + hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + ): p2 = get_proj(prx.p2, plane) p3 = get_proj(prx.p3, plane) - arrowsizestart = vobj.ArrowSizeStart.Value/pointratio + arrowsizestart = vobj.ArrowSizeStart.Value / pointratio halfstartarrowlength = 2 * arrowsizestart - startarrowangle = 2 * math.asin(halfstartarrowlength / prx.circle.Curve.Radius) - arrowsizeend = vobj.ArrowSizeEnd.Value/pointratio + startarrowangle = 2 * math.asin( + halfstartarrowlength / prx.circle.Curve.Radius + ) + arrowsizeend = vobj.ArrowSizeEnd.Value / pointratio halfendarrowlength = 2 * arrowsizeend endarrowangle = 2 * math.asin(halfendarrowlength / prx.circle.Curve.Radius) - if hasattr(vobj, "FlipArrows") \ - and vobj.FlipArrows: + if hasattr(vobj, "FlipArrows") and vobj.FlipArrows: startarrowangle = -startarrowangle endarrowangle = -endarrowangle - _v1a = prx.circle.valueAt(prx.circle.FirstParameter - + startarrowangle) + _v1a = prx.circle.valueAt(prx.circle.FirstParameter + startarrowangle) _v1b = prx.circle.valueAt(prx.circle.FirstParameter) - _v2a = prx.circle.valueAt(prx.circle.LastParameter - - endarrowangle) + _v2a = prx.circle.valueAt(prx.circle.LastParameter - endarrowangle) _v2b = prx.circle.valueAt(prx.circle.LastParameter) u1 = get_proj(_v1a - _v1b, plane) @@ -644,49 +709,36 @@ def get_svg(obj, angle1 = -DraftVecUtils.angle(u1) angle2 = -DraftVecUtils.angle(u2) - svg += get_arrow(obj, - vobj.ArrowTypeStart, - p2, - arrowsizestart, - stroke, - linewidth, - angle1) - svg += get_arrow(obj, - vobj.ArrowTypeEnd, - p3, - arrowsizeend, - stroke, - linewidth, - angle2) + svg += get_arrow( + obj, vobj.ArrowTypeStart, p2, arrowsizestart, stroke, linewidth, angle1 + ) + svg += get_arrow( + obj, vobj.ArrowTypeEnd, p3, arrowsizeend, stroke, linewidth, angle2 + ) # drawing text if vobj.DisplayMode == "World": - _diff = (prx.circle.LastParameter - - prx.circle.FirstParameter) - t = prx.circle.tangentAt(prx.circle.FirstParameter - + _diff/2.0) + _diff = prx.circle.LastParameter - prx.circle.FirstParameter + t = prx.circle.tangentAt(prx.circle.FirstParameter + _diff / 2.0) t = get_proj(t, plane) tangle = -DraftVecUtils.angle(t) - if (tangle <= -math.pi/2) or (tangle > math.pi/2): + if (tangle <= -math.pi / 2) or (tangle > math.pi / 2): tangle = tangle + math.pi - _diff = (prx.circle.LastParameter - - prx.circle.FirstParameter) - _va = prx.circle.valueAt(prx.circle.FirstParameter - + _diff/2.0) + _diff = prx.circle.LastParameter - prx.circle.FirstParameter + _va = prx.circle.valueAt(prx.circle.FirstParameter + _diff / 2.0) tbase = get_proj(_va, plane) - _v = App.Vector(0, 2.0/scale, 0) + _v = App.Vector(0, 2.0 / scale, 0) tbase = tbase + DraftVecUtils.rotate(_v, tangle) # print(tbase) else: tangle = 0 tbase = get_proj(prx.tbase, plane) - svg += svgtext.get_text(plane, techdraw, - tstroke, fontsize, - vobj.FontName, - tangle, tbase, prx.string) + svg += svgtext.get_text( + plane, techdraw, tstroke, fontsize, vobj.FontName, tangle, tbase, prx.string + ) elif utils.get_type(obj) == "Label": @@ -699,48 +751,59 @@ def get_svg(obj, # Some Labels may have no Line property # Draw multisegment line proj_points = list(map(lambda x: get_proj(x, plane), obj.Points)) - path_dir_list = [format_point(proj_points[0], action='M')] + path_dir_list = [format_point(proj_points[0], action="M")] path_dir_list += map(format_point, proj_points[1:]) path_dir_str = " ".join(path_dir_list) - svg_path = ' 1): + if hasattr(vobj, "ArrowTypeStart") and ( + hasattr(vobj, "ArrowSizeStart") and len(obj.Points) > 1 + ): last_segment = App.Vector(obj.Points[-1] - obj.Points[-2]) _v = get_proj(last_segment, plane) angle = -DraftVecUtils.angle(_v) + math.pi - svg += get_arrow(obj, - vobj.ArrowTypeStart, - proj_points[-1], - vobj.ArrowSizeStart.Value/pointratio, - stroke, - linewidth, - angle) + svg += get_arrow( + obj, + vobj.ArrowTypeStart, + proj_points[-1], + vobj.ArrowSizeStart.Value / pointratio, + stroke, + linewidth, + angle, + ) fontname = vobj.FontName position = get_proj(obj.Placement.Base, plane) rotation = obj.Placement.Rotation justification = vobj.Justification text = obj.Text - svg += svgtext.get_text(plane, techdraw, - tstroke, fontsize, fontname, - rotation, position, text, - linespacing, justification) + svg += svgtext.get_text( + plane, + techdraw, + tstroke, + fontsize, + fontname, + rotation, + position, + text, + linespacing, + justification, + ) - elif (utils.get_type(obj) in ["Annotation", "DraftText", "Text"] - or (utils.get_type(obj) == "IfcAnnotation" and obj.ObjectType == "TEXT")): + elif utils.get_type(obj) in ["Annotation", "DraftText", "Text"] or ( + utils.get_type(obj) == "IfcAnnotation" and obj.ObjectType == "TEXT" + ): # returns an svg representation of a document annotation if not App.GuiUp: _wrn("Export of texts to SVG is only available in GUI mode") @@ -757,10 +820,7 @@ def get_svg(obj, t = obj.Text j = vobj.Justification - svg += svgtext.get_text(plane, techdraw, - tstroke, fontsize, n, - r, p, t, - linespacing, j) + svg += svgtext.get_text(plane, techdraw, tstroke, fontsize, n, r, p, t, linespacing, j) elif utils.get_type(obj) == "Axis": # returns the SVG representation of an Arch Axis system @@ -769,45 +829,61 @@ def get_svg(obj, if App.GuiUp: fn = vobj.FontName - fill = 'none' - rad = vobj.BubbleSize.Value/2 + fill = "none" + rad = vobj.BubbleSize.Value / 2 n = 0 for e in obj.Shape.Edges: - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=None, - edges=[e]) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=[e], + ) for t in vobj.Proxy.getTextData(): - pos = t[1].add(App.Vector(0,-fontsize/2,0)) - svg += svgtext.get_text(plane, techdraw, - tstroke, fontsize, fn, - 0.0, pos, t[0], - 1.0, "center") + pos = t[1].add(App.Vector(0, -fontsize / 2, 0)) + svg += svgtext.get_text( + plane, techdraw, tstroke, fontsize, fn, 0.0, pos, t[0], 1.0, "center" + ) for b in vobj.Proxy.getShapeData(): - if hasattr(b,"Curve") and isinstance(b.Curve,Part.Circle): - svg += get_circle(plane, - fill, stroke, linewidth, "none", - b) + if hasattr(b, "Curve") and isinstance(b.Curve, Part.Circle): + svg += get_circle(plane, fill, stroke, linewidth, "none", b) else: sfill = stroke - svg += get_path(obj, plane, - sfill, pathdata, stroke, linewidth, "none", - fill_opacity=None, - edges=b.Edges) + svg += get_path( + obj, + plane, + sfill, + pathdata, + stroke, + linewidth, + "none", + fill_opacity=None, + edges=b.Edges, + ) elif utils.get_type(obj) == "Pipe": fill = stroke if obj.Base and obj.Diameter: - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=None, - edges=obj.Base.Shape.Edges) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=None, + edges=obj.Base.Shape.Edges, + ) for f in obj.Shape.Faces: if len(f.Edges) == 1: if isinstance(f.Edges[0].Curve, Part.Circle): - svg += get_circle(plane, - fill, stroke, linewidth, lstyle, - f.Edges[0]) + svg += get_circle(plane, fill, stroke, linewidth, lstyle, f.Edges[0]) elif utils.get_type(obj) == "Rebar": fill = "none" @@ -822,10 +898,9 @@ def get_svg(obj, wire = basewire.copy() wire.Placement = placement.multiply(basewire.Placement) wires.append(wire) - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=None, - wires=wires) + svg += get_path( + obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, wires=wires + ) elif utils.get_type(obj) == "PipeConnector": pass @@ -843,16 +918,22 @@ def get_svg(obj, obj.Proxy.getArea(obj, notouch=True) if hasattr(obj.Proxy, "face"): # setting fill - if App.GuiUp and hasattr(vobj,"ShapeColor"): - fill = utils.get_rgb(vobj.ShapeColor, - testbw=False) + if App.GuiUp and hasattr(vobj, "ShapeColor"): + fill = utils.get_rgb(vobj.ShapeColor, testbw=False) fill_opacity = 1 - vobj.Transparency / 100.0 else: fill = "#888888" - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=fill_opacity, - wires=[obj.Proxy.face.OuterWire]) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=fill_opacity, + wires=[obj.Proxy.face.OuterWire], + ) c = utils.get_rgb(vobj.TextColor) n = vobj.FontName a = 0 @@ -861,10 +942,10 @@ def get_svg(obj, t1 = vobj.Proxy.text1.string.getValues() t2 = vobj.Proxy.text2.string.getValues() - scale = vobj.FirstLine.Value/vobj.FontSize.Value + scale = vobj.FirstLine.Value / vobj.FontSize.Value f1 = fontsize * scale - if round(plane.axis.getAngle(App.Vector(0,0,1)),2) not in [0,3.14]: + if round(plane.axis.getAngle(App.Vector(0, 0, 1)), 2) not in [0, 3.14]: # if not in XY view, place the label at center p2 = obj.Shape.CenterOfMass else: @@ -875,23 +956,31 @@ def get_svg(obj, lspc = App.Vector(_h) p1 = p2 + lspc j = vobj.TextAlign - t3 = svgtext.get_text(plane, techdraw, - c, f1, n, - a, get_proj(p1, plane), t1, - linespacing, j, flip=True) + t3 = svgtext.get_text( + plane, techdraw, c, f1, n, a, get_proj(p1, plane), t1, linespacing, j, flip=True + ) svg += t3 if t2: ofs = App.Vector(0, -lspc.Length, 0) if a: Z = App.Vector(0, 0, 1) ofs = App.Rotation(Z, -rotation).multVec(ofs) - t4 = svgtext.get_text(plane, techdraw, - c, fontsize, n, - a, get_proj(p1, plane).add(ofs), t2, - linespacing, j, flip=True) + t4 = svgtext.get_text( + plane, + techdraw, + c, + fontsize, + n, + a, + get_proj(p1, plane).add(ofs), + t2, + linespacing, + j, + flip=True, + ) svg += t4 - elif hasattr(obj, 'Shape'): + elif hasattr(obj, "Shape"): # In the past we tested for a Part Feature # elif obj.isDerivedFrom('Part::Feature'): # @@ -899,7 +988,7 @@ def get_svg(obj, # test for a 'Shape'. All Part::Features should have a Shape, # and App::Links can have one as well. if obj.Shape.isNull(): - return '' + return "" fill_opacity = 1 # setting fill @@ -911,21 +1000,20 @@ def get_svg(obj, m = None if m != "Wireframe": - if (fillstyle == "shape color") and hasattr(vobj,"ShapeColor"): - fill = utils.get_rgb(vobj.ShapeColor, - testbw=False) + if (fillstyle == "shape color") and hasattr(vobj, "ShapeColor"): + fill = utils.get_rgb(vobj.ShapeColor, testbw=False) fill_opacity = 1 - vobj.Transparency / 100.0 - elif fillstyle in ("none",None): + elif fillstyle in ("none", None): fill = "none" else: - fill = 'url(#'+fillstyle+')' + fill = "url(#" + fillstyle + ")" svg += get_pattern(fillstyle) else: fill = "none" else: fill = "#888888" else: - fill = 'none' + fill = "none" if len(obj.Shape.Vertexes) > 1: wiredEdges = [] @@ -934,81 +1022,115 @@ def get_svg(obj, # place outer wire first wires = [f.OuterWire] wires.extend([w for w in f.Wires if w.hashCode() != f.OuterWire.hashCode()]) - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=fill_opacity, - wires=f.Wires, - pathname='%s_f%04d' % (obj.Name, i)) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=fill_opacity, + wires=f.Wires, + pathname="%s_f%04d" % (obj.Name, i), + ) wiredEdges.extend(f.Edges) else: for i, w in enumerate(obj.Shape.Wires): - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=fill_opacity, - edges=w.Edges, - pathname='%s_w%04d' % (obj.Name, i)) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=fill_opacity, + edges=w.Edges, + pathname="%s_w%04d" % (obj.Name, i), + ) wiredEdges.extend(w.Edges) if len(wiredEdges) != len(obj.Shape.Edges): - fill = 'none' # Required if obj has a face. Edges processed here have no face. + fill = "none" # Required if obj has a face. Edges processed here have no face. for i, e in enumerate(obj.Shape.Edges): if DraftGeomUtils.findEdge(e, wiredEdges) is None: - svg += get_path(obj, plane, - fill, pathdata, stroke, linewidth, - lstyle, fill_opacity=fill_opacity, - edges=[e], - pathname='%s_nwe%04d' % (obj.Name, i)) + svg += get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=fill_opacity, + edges=[e], + pathname="%s_nwe%04d" % (obj.Name, i), + ) else: # closed circle or spline if obj.Shape.Edges: if isinstance(obj.Shape.Edges[0].Curve, Part.Circle): - svg = get_circle(plane, - fill, stroke, linewidth, lstyle, - obj.Shape.Edges[0]) + svg = get_circle(plane, fill, stroke, linewidth, lstyle, obj.Shape.Edges[0]) else: - svg = get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity=fill_opacity, - edges=obj.Shape.Edges) + svg = get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity=fill_opacity, + edges=obj.Shape.Edges, + ) - if App.GuiUp \ - and hasattr(vobj, "ArrowTypeStart") \ - and hasattr(vobj, "ArrowTypeEnd") \ - and hasattr(vobj, "ArrowSizeStart") \ - and hasattr(vobj, "ArrowSizeEnd") \ - and len(obj.Shape.Vertexes) > 1: + if ( + App.GuiUp + and hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + and len(obj.Shape.Vertexes) > 1 + ): # Draft_Wire p1 = get_proj(obj.Shape.Vertexes[0].Point, plane) p2 = get_proj(obj.Shape.Vertexes[1].Point, plane) - svg += get_arrow(obj, - vobj.ArrowTypeStart, - p1, - vobj.ArrowSizeStart.Value/pointratio, - stroke, - linewidth, - -DraftVecUtils.angle(p2 - p1)) + svg += get_arrow( + obj, + vobj.ArrowTypeStart, + p1, + vobj.ArrowSizeStart.Value / pointratio, + stroke, + linewidth, + -DraftVecUtils.angle(p2 - p1), + ) p1 = get_proj(obj.Shape.Vertexes[-1].Point, plane) p2 = get_proj(obj.Shape.Vertexes[-2].Point, plane) - svg += get_arrow(obj, - vobj.ArrowTypeEnd, - p1, - vobj.ArrowSizeEnd.Value/pointratio, - stroke, - linewidth, - -DraftVecUtils.angle(p2 - p1)) + svg += get_arrow( + obj, + vobj.ArrowTypeEnd, + p1, + vobj.ArrowSizeEnd.Value / pointratio, + stroke, + linewidth, + -DraftVecUtils.angle(p2 - p1), + ) # techdraw expects bottom-to-top coordinates if techdraw: - svg = '\n ' + svg + '\n' + svg = '\n ' + svg + "\n" return svg def _get_view_object(obj): - if obj.isDerivedFrom("App::Link") \ - and hasattr(obj, "ViewObject") \ - and hasattr(obj.ViewObject, "OverrideMaterial") \ - and not obj.ViewObject.OverrideMaterial \ - and hasattr(obj.LinkedObject, "ViewObject"): + if ( + obj.isDerivedFrom("App::Link") + and hasattr(obj, "ViewObject") + and hasattr(obj.ViewObject, "OverrideMaterial") + and not obj.ViewObject.OverrideMaterial + and hasattr(obj.LinkedObject, "ViewObject") + ): return obj.LinkedObject.ViewObject if hasattr(obj, "ViewObject"): return obj.ViewObject @@ -1026,21 +1148,38 @@ def get_print_color(obj): return None -def getSVG(obj, - scale=1, linewidth=0.35, fontsize=12, - fillstyle="shape color", direction=None, - linestyle=None, - color=None, linespacing=None, - techdraw=False, rotation=0, - fillSpaces=False, override=True): +def getSVG( + obj, + scale=1, + linewidth=0.35, + fontsize=12, + fillstyle="shape color", + direction=None, + linestyle=None, + color=None, + linespacing=None, + techdraw=False, + rotation=0, + fillSpaces=False, + override=True, +): """Return SVG string of the object. DEPRECATED. Use 'get_svg'.""" utils.use_instead("get_svg") - return get_svg(obj, - scale=scale, linewidth=linewidth, fontsize=fontsize, - fillstyle=fillstyle, direction=direction, - linestyle=linestyle, - color=color, linespacing=linespacing, - techdraw=techdraw, rotation=rotation, - fillspaces=fillSpaces, override=override) + return get_svg( + obj, + scale=scale, + linewidth=linewidth, + fontsize=fontsize, + fillstyle=fillstyle, + direction=direction, + linestyle=linestyle, + color=color, + linespacing=linespacing, + techdraw=techdraw, + rotation=rotation, + fillspaces=fillSpaces, + override=override, + ) + ## @} diff --git a/src/Mod/Draft/draftfunctions/svgshapes.py b/src/Mod/Draft/draftfunctions/svgshapes.py index efe62186ef..d588f23c0c 100644 --- a/src/Mod/Draft/draftfunctions/svgshapes.py +++ b/src/Mod/Draft/draftfunctions/svgshapes.py @@ -21,8 +21,7 @@ # * USA * # * * # *************************************************************************** -"""Provides functions to return the SVG representation of some shapes. -""" +"""Provides functions to return the SVG representation of some shapes.""" ## @package svgshapes # \ingroup draftfunctions # \brief Provides functions to return the SVG representation of some shapes. @@ -95,21 +94,21 @@ def get_discretized(edge, plane): if pieces == 0: pieces = 10 - d = int(edge.Length/pieces) + d = int(edge.Length / pieces) if d == 0: d = 1 edata = "" for i in range(d + 1): _length = edge.LastParameter - edge.FirstParameter - _point = edge.FirstParameter + float(i)/d * _length + _point = edge.FirstParameter + float(i) / d * _length _vec = edge.valueAt(_point) v = get_proj(_vec, plane) if not edata: - edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' ' + edata += "M " + str(v.x) + " " + str(v.y) + " " else: - edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' ' + edata += "L " + str(v.x) + " " + str(v.y) + " " return edata @@ -120,9 +119,9 @@ def getDiscretized(edge, plane): return get_discretized(edge, plane) -def _get_path_circ_ellipse(plane, edge, verts, edata, - iscircle, isellipse, - fill, stroke, linewidth, lstyle): +def _get_path_circ_ellipse( + plane, edge, verts, edata, iscircle, isellipse, fill, stroke, linewidth, lstyle +): """Get the edge data from a path that is a circle or ellipse.""" if plane: drawing_plane_normal = plane.axis @@ -166,9 +165,7 @@ def _get_path_circ_ellipse(plane, edge, verts, edata, if not done: if len(edge.Vertexes) == 1 and iscircle: # Complete circle not only arc - svg = get_circle(plane, - fill, stroke, linewidth, lstyle, - edge) + svg = get_circle(plane, fill, stroke, linewidth, lstyle, edge) # If it's a circle we will return the final SVG string, # otherwise it will process the `edata` further return "svg", svg @@ -180,9 +177,8 @@ def _get_path_circ_ellipse(plane, edge, verts, edata, # return svg # Difference in angles - _diff = (center.LastParameter - center.FirstParameter)/2.0 - endpoints = [get_proj(center.value(_diff), plane), - get_proj(verts[-1].Point, plane)] + _diff = (center.LastParameter - center.FirstParameter) / 2.0 + endpoints = [get_proj(center.value(_diff), plane), get_proj(verts[-1].Point, plane)] else: endpoints = [get_proj(verts[-1].Point, plane)] @@ -213,16 +209,15 @@ def _get_path_circ_ellipse(plane, edge, verts, edata, # between tangents _diff = edge.LastParameter - edge.FirstParameter t1 = edge.tangentAt(edge.FirstParameter) - t2 = edge.tangentAt(edge.FirstParameter + _diff/10) + t2 = edge.tangentAt(edge.FirstParameter + _diff / 10) flag_sweep = DraftVecUtils.angle(t1, t2, drawing_plane_normal) < 0 for v in endpoints: - edata += ('A {} {} {} ' - '{} {} ' - '{} {} '.format(rx, ry, rot, - int(flag_large_arc), - int(flag_sweep), - v.x, v.y)) + edata += ( + "A {} {} {} " + "{} {} " + "{} {} ".format(rx, ry, rot, int(flag_large_arc), int(flag_sweep), v.x, v.y) + ) return "edata", edata @@ -232,7 +227,7 @@ def _get_path_bspline(plane, edge, edata): bspline = edge.Curve.toBSpline(edge.FirstParameter, edge.LastParameter) if bspline.Degree > 3 or bspline.isRational(): try: - bspline = bspline.approximateBSpline(0.05, 50, 3, 'C0') + bspline = bspline.approximateBSpline(0.05, 50, 3, "C0") except RuntimeError: _wrn("Debug: unable to approximate bspline from edge") @@ -242,30 +237,30 @@ def _get_path_bspline(plane, edge, edata): _wrn("Bezier segment of degree > 3") raise AssertionError elif bezierseg.Degree == 1: - edata += 'L ' + edata += "L " elif bezierseg.Degree == 2: - edata += 'Q ' + edata += "Q " elif bezierseg.Degree == 3: - edata += 'C ' + edata += "C " for pole in bezierseg.getPoles()[1:]: v = get_proj(pole, plane) - edata += '{} {} '.format(v.x, v.y) + edata += "{} {} ".format(v.x, v.y) else: - _msg("Debug: one edge (hash {}) " - "has been discretized " - "with parameter 0.1".format(edge.hashCode())) + _msg( + "Debug: one edge (hash {}) " + "has been discretized " + "with parameter 0.1".format(edge.hashCode()) + ) for linepoint in bspline.discretize(0.1)[1:]: v = get_proj(linepoint, plane) - edata += 'L {} {} '.format(v.x, v.y) + edata += "L {} {} ".format(v.x, v.y) return edata -def get_circle(plane, - fill, stroke, linewidth, lstyle, - edge): +def get_circle(plane, fill, stroke, linewidth, lstyle, edge): """Get the SVG representation from a circular edge.""" cen = get_proj(edge.Curve.Center, plane) rad = edge.Curve.Radius @@ -277,7 +272,7 @@ def get_circle(plane, if round(edge.Curve.Axis.getAngle(drawing_plane_normal), 2) in [0, 3.14]: # Perpendicular projection: circle - svg = ' 1: last_pt = verts[-1].Point nextverts = _edges[1].Vertexes - if (last_pt - nextverts[0].Point).Length > 1e-6 \ - and (last_pt - nextverts[-1].Point).Length > 1e-6: + if (last_pt - nextverts[0].Point).Length > 1e-6 and ( + last_pt - nextverts[-1].Point + ).Length > 1e-6: verts.reverse() v = get_proj(verts[0].Point, plane) - edata += 'M {} {} '.format(v.x, v.y) + edata += "M {} {} ".format(v.x, v.y) else: previousverts = verts verts = edge.Vertexes if (verts[0].Point - previousverts[-1].Point).Length > 1e-6: verts.reverse() if (verts[0].Point - previousverts[-1].Point).Length > 1e-6: - raise ValueError('edges not ordered') + raise ValueError("edges not ordered") iscircle = DraftGeomUtils.geomType(edge) == "Circle" isellipse = DraftGeomUtils.geomType(edge) == "Ellipse" if iscircle or isellipse: - _type, data = _get_path_circ_ellipse(plane, edge, verts, - edata, - iscircle, isellipse, - fill, stroke, - linewidth, lstyle) + _type, data = _get_path_circ_ellipse( + plane, edge, verts, edata, iscircle, isellipse, fill, stroke, linewidth, lstyle + ) if _type == "svg": # final svg string already calculated, so just return it return data @@ -412,14 +409,14 @@ def get_path(obj, plane, edata = data elif DraftGeomUtils.geomType(edge) == "Line": v = get_proj(verts[-1].Point, plane) - edata += 'L {} {} '.format(v.x, v.y) + edata += "L {} {} ".format(v.x, v.y) else: # If it's not a circle nor ellipse nor straight line # convert the curve to BSpline edata = _get_path_bspline(plane, edge, edata) - if fill != 'none': - edata += 'Z ' + if fill != "none": + edata += "Z " if edata in pathdata: # do not draw a path on another identical path @@ -432,29 +429,48 @@ def get_path(obj, plane, svg += 'stroke="{}" '.format(stroke) svg += 'stroke-width="{} px" '.format(linewidth) svg += 'style="' - svg += 'stroke-width:{};'.format(linewidth) - svg += 'stroke-miterlimit:4;' - svg += 'stroke-dasharray:{};'.format(lstyle) - svg += 'stroke-linecap:square;' - svg += 'fill:{};'.format(fill) + svg += "stroke-width:{};".format(linewidth) + svg += "stroke-miterlimit:4;" + svg += "stroke-dasharray:{};".format(lstyle) + svg += "stroke-linecap:square;" + svg += "fill:{};".format(fill) # fill_opacity must be a number, but if it's `None` it is omitted if fill_opacity is not None: - svg += 'fill-opacity:{};'.format(fill_opacity) + svg += "fill-opacity:{};".format(fill_opacity) svg += 'fill-rule: evenodd"' - svg += '/>\n' + svg += "/>\n" return svg -def getPath(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity, - edges=[], wires=[], pathname=None): +def getPath( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity, + edges=[], + wires=[], + pathname=None, +): """Get the SVG representation from a path. DEPRECATED.""" utils.use_instead("get_path") - return get_path(obj, plane, - fill, pathdata, stroke, linewidth, lstyle, - fill_opacity, - edges=edges, wires=wires, pathname=pathname) + return get_path( + obj, + plane, + fill, + pathdata, + stroke, + linewidth, + lstyle, + fill_opacity, + edges=edges, + wires=wires, + pathname=pathname, + ) + ## @} diff --git a/src/Mod/Draft/draftfunctions/svgtext.py b/src/Mod/Draft/draftfunctions/svgtext.py index dfb8b537dc..e2e3ae0c9e 100644 --- a/src/Mod/Draft/draftfunctions/svgtext.py +++ b/src/Mod/Draft/draftfunctions/svgtext.py @@ -36,9 +36,7 @@ import draftutils.utils as utils # @{ -def _get_text_techdraw(text, tcolor, fontsize, anchor, - align, fontname, angle, base, - linespacing): +def _get_text_techdraw(text, tcolor, fontsize, anchor, align, fontname, angle, base, linespacing): """Return the SVG representation of text for TechDraw display. `text` is a list of textual elements; they are iterated, styled, @@ -56,28 +54,23 @@ def _get_text_techdraw(text, tcolor, fontsize, anchor, _t = _t.replace("<", "<") t = _t.replace(">", ">") - svg += ' tag with style options. The text must be added after this tag, and then must be closed. @@ -86,37 +79,43 @@ def _get_text_header(tcolor, fontsize, anchor, align, ... """ - svg = ' text[0] # text[1] - svg = _get_text_techdraw(text, tcolor, fontsize, anchor, - align, fontname, angle, base, - linespacing) + svg = _get_text_techdraw( + text, tcolor, fontsize, anchor, align, fontname, angle, base, linespacing + ) else: # If the SVG is not for TechDraw, and there is a single item # in the text list, place it in a single tag. @@ -167,8 +166,7 @@ def get_text(plane, techdraw, # text[0] # text[1] # - svg = _get_text_header(tcolor, fontsize, anchor, align, - fontname, angle, base, flip) + svg = _get_text_header(tcolor, fontsize, anchor, align, fontname, angle, base, flip) if len(text) == 1: _t = text[0].replace("&", "&").replace("<", "<") @@ -176,25 +174,34 @@ def get_text(plane, techdraw, else: for i in range(len(text)): if i == 0: - svg += '' + svg += "" else: svg += ''.format(linespacing) _t = text[i].replace("&", "&").replace("<", "<") svg += _t.replace(">", ">") - svg += '\n' - svg += '\n' + svg += "\n" + svg += "\n" return svg -def getText(plane, techdraw, - tcolor, fontsize, fontname, - angle, base, text, - linespacing=0.5, align="center", flip=True): +def getText( + plane, + techdraw, + tcolor, + fontsize, + fontname, + angle, + base, + text, + linespacing=0.5, + align="center", + flip=True, +): """Get the SVG representation of a textual element. DEPRECATED.""" utils.use_instead("get_text") - return get_text(plane, techdraw, - tcolor, fontsize, fontname, - angle, base, text, - linespacing, align, flip) + return get_text( + plane, techdraw, tcolor, fontsize, fontname, angle, base, text, linespacing, align, flip + ) + ## @} diff --git a/src/Mod/Draft/draftfunctions/upgrade.py b/src/Mod/Draft/draftfunctions/upgrade.py index 79cc7449ff..06196eaa02 100644 --- a/src/Mod/Draft/draftfunctions/upgrade.py +++ b/src/Mod/Draft/draftfunctions/upgrade.py @@ -220,8 +220,9 @@ def upgrade(objects, delete=False, force=None): new_area = new_face.Area new_cen = new_face.CenterOfMass for old_area, old_cen, old_color in old_data: - if math.isclose(new_area, old_area, abs_tol=1e-7) \ - and new_cen.isEqual(old_cen, 1e-7): + if math.isclose(new_area, old_area, abs_tol=1e-7) and new_cen.isEqual( + old_cen, 1e-7 + ): new_colors.append(old_color) break newobj.ViewObject.DiffuseColor = new_colors @@ -316,8 +317,11 @@ def upgrade(objects, delete=False, force=None): for cluster in sorted_edges: for edge in cluster: print("Curve: {}".format(edge.Curve)) - print("first: {}, last: {}".format(edge.Vertexes[0].Point, - edge.Vertexes[-1].Point)) + print( + "first: {}, last: {}".format( + edge.Vertexes[0].Point, edge.Vertexes[-1].Point + ) + ) wires = [Part.Wire(cluster) for cluster in sorted_edges] except Part.OCCError: return False @@ -349,7 +353,6 @@ def upgrade(objects, delete=False, force=None): delete_list.append(obj) return True - # helper functions (same as in downgrade.py) def get_parent(obj): @@ -413,7 +416,6 @@ def upgrade(objects, delete=False, force=None): for newobj in new_list: gui_utils.format_object(newobj, obj, ignore_construction=True) - doc = App.ActiveDocument add_list = [] delete_list = [] @@ -476,17 +478,21 @@ def upgrade(objects, delete=False, force=None): result = turnToParts(meshes) else: # functions that work on a single object: - single_funcs = {"closeWire": closeWire, - "draftify": _draftify, - "makeSketchFace": makeSketchFace, - "makeSolid": makeSolid} + single_funcs = { + "closeWire": closeWire, + "draftify": _draftify, + "makeSketchFace": makeSketchFace, + "makeSolid": makeSolid, + } # functions that work on multiple objects: - multi_funcs = {"joinFaces": joinFaces, - "makeCompound": makeCompound, - "makeFaces": makeFaces, - "makeFusion": makeFusion, - "makeShell": makeShell, - "makeWires": makeWires} + multi_funcs = { + "joinFaces": joinFaces, + "makeCompound": makeCompound, + "makeFaces": makeFaces, + "makeFusion": makeFusion, + "makeShell": makeShell, + "makeWires": makeWires, + } if force in single_funcs: result = any([single_funcs[force](obj) for obj in objects]) elif force in multi_funcs: @@ -536,39 +542,55 @@ def upgrade(objects, delete=False, force=None): _msg(translate("draft", "Found 1 solidifiable object: solidifying it")) # we have exactly 2 objects: we fuse them - elif len(objects) == 2 \ - and not faces_coplanarity \ - and same_parent \ - and same_parent_type != "PartDesign::Body": + elif ( + len(objects) == 2 + and not faces_coplanarity + and same_parent + and same_parent_type != "PartDesign::Body" + ): result = makeFusion(objects) if result: _msg(translate("draft", "Found 2 objects: fusing them")) # we have many separate faces: we try to make a shell or compound - elif len(objects) > 1 \ - and len(faces) > 1 \ - and same_parent \ - and same_parent_type != "PartDesign::Body": + elif ( + len(objects) > 1 + and len(faces) > 1 + and same_parent + and same_parent_type != "PartDesign::Body" + ): result = makeShell(objects) if result: - _msg(translate( - "draft", - "Found several objects: creating a " + result.Shape.ShapeType - )) + _msg( + translate( + "draft", "Found several objects: creating a " + result.Shape.ShapeType + ) + ) # we have faces: we try to join them if they are coplanar elif len(objects) == 1 and len(faces) > 1 and faces_coplanarity: result = joinFaces(objects) if result: - _msg(translate("draft", "Found object with several coplanar faces: refining them")) + _msg( + translate( + "draft", "Found object with several coplanar faces: refining them" + ) + ) # only one object: if not parametric, we "draftify" it - elif len(objects) == 1 \ - and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \ - and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]: + elif ( + len(objects) == 1 + and not objects[0].isDerivedFrom("Part::Part2DObjectPython") + and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"] + ): result = _draftify(objects[0]) if result: - _msg(translate("draft", "Found 1 non-parametric object: replacing it with a Draft object")) + _msg( + translate( + "draft", + "Found 1 non-parametric object: replacing it with a Draft object", + ) + ) # in the following cases there are no faces elif not faces: @@ -579,7 +601,11 @@ def upgrade(objects, delete=False, force=None): if len(objects) == 1 and objects[0].isDerivedFrom("Sketcher::SketchObject"): result = makeSketchFace(objects[0]) if result: - _msg(translate("draft", "Found 1 closed sketch object: creating a face from it")) + _msg( + translate( + "draft", "Found 1 closed sketch object: creating a face from it" + ) + ) # only closed wires else: result = makeFaces(objects) @@ -594,7 +620,11 @@ def upgrade(objects, delete=False, force=None): else: result = makeCompound(objects) if result: - _msg(translate("draft", "Found several non-treatable objects: creating compound")) + _msg( + translate( + "draft", "Found several non-treatable objects: creating compound" + ) + ) # special case, we have only one open wire. We close it, unless it has only 1 edge! elif len(objects) == 1 and len(openwires) == 1: @@ -603,16 +633,23 @@ def upgrade(objects, delete=False, force=None): _msg(translate("draft", "Found 1 open wire: closing it")) # only one object: if not parametric, we "draftify" it - elif len(objects) == 1 \ - and len(edges) == 1 \ - and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \ - and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]: + elif ( + len(objects) == 1 + and len(edges) == 1 + and not objects[0].isDerivedFrom("Part::Part2DObjectPython") + and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"] + ): edge_type = DraftGeomUtils.geomType(objects[0].Shape.Edges[0]) # currently only support Line and Circle if edge_type in ("Line", "Circle"): result = _draftify(objects[0]) if result: - _msg(translate("draft", "Found 1 non-parametric object: replacing it with a Draft object")) + _msg( + translate( + "draft", + "Found 1 non-parametric object: replacing it with a Draft object", + ) + ) # only points, no edges elif not edges and len(objects) > 1: @@ -637,4 +674,5 @@ def upgrade(objects, delete=False, force=None): gui_utils.select(add_list) return add_list, delete_list + ## @} diff --git a/src/Mod/Draft/draftgeoutils/arcs.py b/src/Mod/Draft/draftgeoutils/arcs.py index c27766e767..8963cbefd0 100644 --- a/src/Mod/Draft/draftgeoutils/arcs.py +++ b/src/Mod/Draft/draftgeoutils/arcs.py @@ -74,7 +74,7 @@ def isClockwise(edge, ref=None): # if that axis points "the wrong way" from the reference, we invert it if not ref: ref = App.Vector(0, 0, 1) - if n.getAngle(ref) > math.pi/2: + if n.getAngle(ref) > math.pi / 2: n = n.negative() if DraftVecUtils.angle(v1, v2, n) < 0: @@ -92,9 +92,9 @@ def isWideAngle(edge): return False r = edge.Curve.Radius - total = 2*r*math.pi + total = 2 * r * math.pi - if edge.Length > total/2: + if edge.Length > total / 2: return True return False @@ -106,7 +106,7 @@ def arcFrom2Pts(firstPt, lastPt, center, axis=None): radius2 = lastPt.sub(center).Length # (PREC = 4 = same as Part Module), Is it possible? - if round(radius1-radius2, 4) != 0: + if round(radius1 - radius2, 4) != 0: return None thirdPt = App.Vector(firstPt.sub(center).add(lastPt).sub(center)) @@ -141,7 +141,7 @@ def arcFromSpline(edge): # 2-point arc p1 = edge.Vertexes[0].Point p2 = edge.Vertexes[-1].Point - ml = edge.Length/2 + ml = edge.Length / 2 p3 = edge.valueAt(ml) try: return Part.Arc(p1, p3, p2).toShape() @@ -162,4 +162,5 @@ def arcFromSpline(edge): print("couldn't make a circle out of this edge") return None + ## @} diff --git a/src/Mod/Draft/draftgeoutils/circle_inversion.py b/src/Mod/Draft/draftgeoutils/circle_inversion.py index c48436109a..f413ba758b 100644 --- a/src/Mod/Draft/draftgeoutils/circle_inversion.py +++ b/src/Mod/Draft/draftgeoutils/circle_inversion.py @@ -84,9 +84,7 @@ def polarInversion(circle, edge): print("debug: circleInversionPole bad parameters! Must be a circle.") return None - nearest = circle.Curve.Center.add(findDistance(circle.Curve.Center, - edge, - False)) + nearest = circle.Curve.Center.add(findDistance(circle.Curve.Center, edge, False)) if nearest: inversionPole = pointInversion(circle, nearest) if inversionPole: @@ -117,8 +115,7 @@ def circleInversion(circle, circle2): pointOnCircle2 = App.Vector.add(cen2, App.Vector(rad2, 0, 0)) invPointOnCircle2 = pointInversion(circle, pointOnCircle2) - return Part.Circle(invCen2, - NORM, - DraftVecUtils.dist(invCen2, invPointOnCircle2)) + return Part.Circle(invCen2, NORM, DraftVecUtils.dist(invCen2, invPointOnCircle2)) + ## @} diff --git a/src/Mod/Draft/draftgeoutils/circles.py b/src/Mod/Draft/draftgeoutils/circles.py index d5dac2aaf4..d995ef4fad 100644 --- a/src/Mod/Draft/draftgeoutils/circles.py +++ b/src/Mod/Draft/draftgeoutils/circles.py @@ -65,18 +65,18 @@ def getCircleFromSpline(edge): # get 2 points p1 = edge.Curve.value(0) - p2 = edge.Curve.value(math.pi/2) + p2 = edge.Curve.value(math.pi / 2) # get 2 tangents t1 = edge.Curve.tangent(0)[0] - t2 = edge.Curve.tangent(math.pi/2)[0] + t2 = edge.Curve.tangent(math.pi / 2)[0] # get normal n = p1.cross(p2) if DraftVecUtils.isNull(n): return None # get rays - r1 = DraftVecUtils.rotate(t1, math.pi/2, n) - r2 = DraftVecUtils.rotate(t2, math.pi/2, n) + r1 = DraftVecUtils.rotate(t1, math.pi / 2, n) + r2 = DraftVecUtils.rotate(t2, math.pi / 2, n) # get center (intersection of rays) i = findIntersection(p1, p1.add(r1), p2, p2.add(r2), True, True) if not i: @@ -116,10 +116,8 @@ def circlefrom1Line2Points(edge, p1, p2): x = DraftVecUtils.crossproduct(vec(p1_p2)) x.normalize() perp_mid = App.Vector.add(mid, x) - cen1 = findIntersection(edg(projectedCen1, perpCen1), - edg(mid, perp_mid), True, True) - cen2 = findIntersection(edg(projectedCen2, perpCen2), - edg(mid, perp_mid), True, True) + cen1 = findIntersection(edg(projectedCen1, perpCen1), edg(mid, perp_mid), True, True) + cen2 = findIntersection(edg(projectedCen2, perpCen2), edg(mid, perp_mid), True, True) circles = [] if cen1: @@ -157,8 +155,9 @@ def circleFrom2LinesRadius(edge1, edge2, radius): intsec = intsec[0] bis12 = angleBisection(edge1, edge2) - bis21 = Part.LineSegment(bis12.Vertexes[0].Point, - DraftVecUtils.rotate(vec(bis12), math.pi/2.0)) + bis21 = Part.LineSegment( + bis12.Vertexes[0].Point, DraftVecUtils.rotate(vec(bis12), math.pi / 2.0) + ) ang12 = abs(DraftVecUtils.angle(vec(edge1), vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) @@ -185,10 +184,9 @@ def circleFrom3LineTangents(edge1, edge2, edge3): It calculates up to 6 possible centers. """ + def rot(ed): - geo = Part.LineSegment(v1(ed), - v1(ed).add(DraftVecUtils.rotate(vec(ed), - math.pi/2))) + geo = Part.LineSegment(v1(ed), v1(ed).add(DraftVecUtils.rotate(vec(ed), math.pi / 2))) return geo.toShape() bis12 = angleBisection(edge1, edge2) @@ -273,7 +271,7 @@ def circleFromPointLineRadius(point, edge, radius): else: normPoint = point.add(findDistance(point, edge, False)) normDist = DraftVecUtils.dist(normPoint, point) - dist = math.sqrt(radius**2 - (radius - normDist)**2) + dist = math.sqrt(radius**2 - (radius - normDist) ** 2) centerNormVec = DraftVecUtils.scaleTo(point.sub(normPoint), radius) edgeDir = edge.Vertexes[0].Point.sub(normPoint) edgeDir.normalize() @@ -311,7 +309,7 @@ def circleFrom2PointsRadius(p1, p2, radius): dist_p1p2 = DraftVecUtils.dist(p1, p2) mid = findMidpoint(p1_p2) - if dist_p1p2 == 2*radius: + if dist_p1p2 == 2 * radius: circle = Part.Circle(mid, NORM, radius) if circle: return [circle] @@ -322,7 +320,7 @@ def circleFrom2PointsRadius(p1, p2, radius): _dir.normalize() perpDir = _dir.cross(App.Vector(0, 0, 1)) perpDir.normalize() - dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) + dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0) ** 2) cen1 = App.Vector.add(mid, App.Vector(perpDir).multiply(dist)) cen2 = App.Vector.add(mid, App.Vector(perpDir).multiply(-dist)) @@ -346,16 +344,14 @@ def findHomotheticCenterOfCircles(circle1, circle2): http://en.wikipedia.org/wiki/Homothetic_center http://mathworld.wolfram.com/HomotheticCenter.html """ - if (geomType(circle1) == "Circle" and geomType(circle2) == "Circle"): + if geomType(circle1) == "Circle" and geomType(circle2) == "Circle": print("debug: findHomotheticCenterOfCircles bad parameters!") return None - if DraftVecUtils.equals(circle1.Curve.Center, - circle2.Curve.Center): + if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None - cen1_cen2 = Part.LineSegment(circle1.Curve.Center, - circle2.Curve.Center).toShape() + cen1_cen2 = Part.LineSegment(circle1.Curve.Center, circle2.Curve.Center).toShape() cenDir = vec(cen1_cen2) cenDir.normalize() @@ -364,18 +360,17 @@ def findHomotheticCenterOfCircles(circle1, circle2): perpCenDir.normalize() # Get point on first circle - p1 = App.Vector.add(circle1.Curve.Center, - App.Vector(perpCenDir).multiply(circle1.Curve.Radius)) + p1 = App.Vector.add(circle1.Curve.Center, App.Vector(perpCenDir).multiply(circle1.Curve.Radius)) centers = [] # Calculate inner homothetic center # Get point on second circle - p2_inner = App.Vector.add(circle1.Curve.Center, - App.Vector(perpCenDir).multiply(-circle1.Curve.Radius)) - hCenterInner = DraftVecUtils.intersect(circle1.Curve.Center, - circle2.Curve.Center, - p1, p2_inner, - True, True) + p2_inner = App.Vector.add( + circle1.Curve.Center, App.Vector(perpCenDir).multiply(-circle1.Curve.Radius) + ) + hCenterInner = DraftVecUtils.intersect( + circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True + ) if hCenterInner: centers.append(hCenterInner) @@ -383,12 +378,12 @@ def findHomotheticCenterOfCircles(circle1, circle2): # have different radii if circle1.Curve.Radius != circle2.Curve.Radius: # Get point on second circle - p2_outer = App.Vector.add(circle1.Curve.Center, - App.Vector(perpCenDir).multiply(circle1.Curve.Radius)) - hCenterOuter = DraftVecUtils.intersect(circle1.Curve.Center, - circle2.Curve.Center, - p1, p2_outer, - True, True) + p2_outer = App.Vector.add( + circle1.Curve.Center, App.Vector(perpCenDir).multiply(circle1.Curve.Radius) + ) + hCenterOuter = DraftVecUtils.intersect( + circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True + ) if hCenterOuter: centers.append(hCenterOuter) @@ -473,9 +468,11 @@ def findRadicalCenter(circle1, circle2, circle3): -------- findRadicalAxis """ - if (geomType(circle1) != "Circle" - or geomType(circle2) != "Circle" - or geomType(circle3) != "Circle"): + if ( + geomType(circle1) != "Circle" + or geomType(circle2) != "Circle" + or geomType(circle3) != "Circle" + ): print("debug: findRadicalCenter bad parameters! Must be circles.") return None @@ -494,4 +491,5 @@ def findRadicalCenter(circle1, circle2, circle3): # No radical center could be calculated. return None + ## @} diff --git a/src/Mod/Draft/draftgeoutils/circles_apollonius.py b/src/Mod/Draft/draftgeoutils/circles_apollonius.py index e1f975b4f9..c8b270d9ee 100644 --- a/src/Mod/Draft/draftgeoutils/circles_apollonius.py +++ b/src/Mod/Draft/draftgeoutils/circles_apollonius.py @@ -68,9 +68,11 @@ def outerSoddyCircle(circle1, circle2, circle3): Either Creative Commons Attribution 3.0, the MIT license, or the GNU Lesser General License LGPL. """ - if (geomType(circle1) != "Circle" - or geomType(circle2) != "Circle" - or geomType(circle3) != "Circle"): + if ( + geomType(circle1) != "Circle" + or geomType(circle2) != "Circle" + or geomType(circle3) != "Circle" + ): print("debug: outerSoddyCircle bad parameters! Must be circles.") return None @@ -93,7 +95,7 @@ def outerSoddyCircle(circle1, circle2, circle3): q2 = (k2 + 0j) * (B.x + B.y * 1j) q3 = (k3 + 0j) * (C.x + C.y * 1j) - temp = ((q1 * q2) + (q2 * q3) + (q3 * q1)) + temp = (q1 * q2) + (q2 * q3) + (q3 * q1) q4 = q1 + q2 + q3 - ((2 + 0j) * cmath.sqrt(temp)) z = q4 / (k4 + 0j) @@ -121,9 +123,11 @@ def innerSoddyCircle(circle1, circle2, circle3): Converted to python by Martin Buerbaum 2009 http://www.randelshofer.ch/treeviz/ """ - if (geomType(circle1) != "Circle" - and geomType(circle2) != "Circle" - and geomType(circle3) != "Circle"): + if ( + geomType(circle1) != "Circle" + and geomType(circle2) != "Circle" + and geomType(circle3) != "Circle" + ): print("debug: innerSoddyCircle bad parameters! Must be circles.") return None @@ -146,13 +150,13 @@ def innerSoddyCircle(circle1, circle2, circle3): q2 = (k2 + 0j) * (B.x + B.y * 1j) q3 = (k3 + 0j) * (C.x + C.y * 1j) - temp = ((q1 * q2) + (q2 * q3) + (q3 * q1)) + temp = (q1 * q2) + (q2 * q3) + (q3 * q1) q4 = q1 + q2 + q3 + ((2 + 0j) * cmath.sqrt(temp)) z = q4 / (k4 + 0j) # If the formula is not solvable, we return no circle. - if (not z or not (1 / k4)): + if not z or not (1 / k4): return None X = z.real @@ -186,9 +190,11 @@ def circleFrom3CircleTangents(circle1, circle2, circle3): inversion pole and the radical center) with the circle. * This gives us all the tangent points. """ - if (geomType(circle1) != "Circle" - and geomType(circle2) != "Circle" - and geomType(circle3) == "Circle"): + if ( + geomType(circle1) != "Circle" + and geomType(circle2) != "Circle" + and geomType(circle3) == "Circle" + ): print("debug: circleFrom3CircleTangents bad input! Must be circles") return None @@ -222,4 +228,5 @@ def circleFrom3CircleTangents(circle1, circle2, circle3): # Some circles are inside each other or an error has occurred. return None + ## @} diff --git a/src/Mod/Draft/draftgeoutils/circles_incomplete.py b/src/Mod/Draft/draftgeoutils/circles_incomplete.py index e410e0bb66..2498f141bc 100644 --- a/src/Mod/Draft/draftgeoutils/circles_incomplete.py +++ b/src/Mod/Draft/draftgeoutils/circles_incomplete.py @@ -57,11 +57,13 @@ import FreeCAD from draftutils.messages import _wrn from draftgeoutils.general import geomType -from draftgeoutils.circles import (circlefrom2Lines1Point, - circleFrom2LinesRadius, - circlefrom1Line2Points, - circleFromPointLineRadius, - circleFrom3LineTangents) +from draftgeoutils.circles import ( + circlefrom2Lines1Point, + circleFrom2LinesRadius, + circlefrom1Line2Points, + circleFromPointLineRadius, + circleFrom3LineTangents, +) from draftgeoutils.circles_apollonius import circleFrom3CircleTangents @@ -81,24 +83,28 @@ def circleFrom2tan1pt(tan1, tan2, point): The tangents should be edges, and they may be either straight line edges or circular edges, so four combinations are possible. """ - if (geomType(tan1) == "Line" - and geomType(tan2) == "Line" - and isinstance(point, FreeCAD.Vector)): + if geomType(tan1) == "Line" and geomType(tan2) == "Line" and isinstance(point, FreeCAD.Vector): return circlefrom2Lines1Point(tan1, tan2, point) - elif (geomType(tan1) == "Circle" - and geomType(tan2) == "Line" - and isinstance(point, FreeCAD.Vector)): + elif ( + geomType(tan1) == "Circle" + and geomType(tan2) == "Line" + and isinstance(point, FreeCAD.Vector) + ): return circlefromCircleLinePoint(tan1, tan2, point) - elif (geomType(tan2) == "Circle" - and geomType(tan1) == "Line" - and isinstance(point, FreeCAD.Vector)): + elif ( + geomType(tan2) == "Circle" + and geomType(tan1) == "Line" + and isinstance(point, FreeCAD.Vector) + ): return circlefromCircleLinePoint(tan2, tan1, point) - elif (geomType(tan2) == "Circle" - and geomType(tan1) == "Circle" - and isinstance(point, FreeCAD.Vector)): + elif ( + geomType(tan2) == "Circle" + and geomType(tan1) == "Circle" + and isinstance(point, FreeCAD.Vector) + ): return circlefrom2Circles1Point(tan2, tan1, point) @@ -142,14 +148,18 @@ def circleFrom1tan2pt(tan1, p1, p2): The tangents should be edges, and they may be either straight line edges or circular edges, so two combinations are possible. """ - if (geomType(tan1) == "Line" - and isinstance(p1, FreeCAD.Vector) - and isinstance(p2, FreeCAD.Vector)): + if ( + geomType(tan1) == "Line" + and isinstance(p1, FreeCAD.Vector) + and isinstance(p2, FreeCAD.Vector) + ): return circlefrom1Line2Points(tan1, p1, p2) - elif (geomType(tan1) == "Circle" - and isinstance(p1, FreeCAD.Vector) - and isinstance(p2, FreeCAD.Vector)): + elif ( + geomType(tan1) == "Circle" + and isinstance(p1, FreeCAD.Vector) + and isinstance(p2, FreeCAD.Vector) + ): return circlefrom1Circle2Points(tan1, p1, p2) @@ -187,13 +197,13 @@ def circleFrom3tan(tan1, tan2, tan3): The tangents should be edges, and they may be either straight line edges or circular edges, so eight combinations are possible. """ - tan1IsLine = (geomType(tan1) == "Line") - tan2IsLine = (geomType(tan2) == "Line") - tan3IsLine = (geomType(tan3) == "Line") + tan1IsLine = geomType(tan1) == "Line" + tan2IsLine = geomType(tan2) == "Line" + tan3IsLine = geomType(tan3) == "Line" - tan1IsCircle = (geomType(tan1) == "Circle") - tan2IsCircle = (geomType(tan2) == "Circle") - tan3IsCircle = (geomType(tan3) == "Circle") + tan1IsCircle = geomType(tan1) == "Circle" + tan2IsCircle = geomType(tan2) == "Circle" + tan3IsCircle = geomType(tan3) == "Circle" if tan1IsLine and tan2IsLine and tan3IsLine: return circleFrom3LineTangents(tan1, tan2, tan3) @@ -219,4 +229,5 @@ def circleFrom3tan(tan1, tan2, tan3): elif tan1IsCircle and tan2IsCircle and tan3IsLine: return circleFrom2Circle1Lines(tan1, tan2, tan3) + ## @} diff --git a/src/Mod/Draft/draftgeoutils/cuboids.py b/src/Mod/Draft/draftgeoutils/cuboids.py index 833e46634c..7eb5216e2a 100644 --- a/src/Mod/Draft/draftgeoutils/cuboids.py +++ b/src/Mod/Draft/draftgeoutils/cuboids.py @@ -43,9 +43,7 @@ def isCubic(shape): and all angles are 90 degrees between its edges. """ # first we try fast methods - if (len(shape.Vertexes) != 8 - or len(shape.Faces) != 6 - or len(shape.Edges) != 12): + if len(shape.Vertexes) != 8 or len(shape.Faces) != 6 or len(shape.Edges) != 12: return False for e in shape.Edges: @@ -60,10 +58,10 @@ def isCubic(shape): for i in range(4): e1 = vec(f.Edges[i]) if i < 3: - e2 = vec(f.Edges[i+1]) + e2 = vec(f.Edges[i + 1]) else: e2 = vec(f.Edges[0]) - rpi = [0.0, round(math.pi/2, precision())] + rpi = [0.0, round(math.pi / 2, precision())] if round(e1.getAngle(e2), precision()) not in rpi: return False @@ -109,7 +107,7 @@ def getCubicDimensions(shape): # getting height vz = None - rpi = round(math.pi/2, precision()) + rpi = round(math.pi / 2, precision()) for i in range(1, 6): for e in shape.Faces[i].Edges: if basepoint in [e.Vertexes[0].Point, e.Vertexes[1].Point]: @@ -128,9 +126,12 @@ def getCubicDimensions(shape): mat.rotateY(rotY) mat.rotateZ(rotZ) - return [App.Placement(mat), - round(vx.Length, precision()), - round(vy.Length, precision()), - round(vz.Length, precision())] + return [ + App.Placement(mat), + round(vx.Length, precision()), + round(vy.Length, precision()), + round(vz.Length, precision()), + ] + ## @} diff --git a/src/Mod/Draft/draftgeoutils/edges.py b/src/Mod/Draft/draftgeoutils/edges.py index c7ba1b2e5a..eb27be1a6e 100644 --- a/src/Mod/Draft/draftgeoutils/edges.py +++ b/src/Mod/Draft/draftgeoutils/edges.py @@ -44,10 +44,8 @@ def findEdge(anEdge, aList): """Return True if edge is found in list of edges.""" for e in range(len(aList)): if str(anEdge.Curve) == str(aList[e].Curve): - if DraftVecUtils.equals(anEdge.Vertexes[0].Point, - aList[e].Vertexes[0].Point): - if DraftVecUtils.equals(anEdge.Vertexes[-1].Point, - aList[e].Vertexes[-1].Point): + if DraftVecUtils.equals(anEdge.Vertexes[0].Point, aList[e].Vertexes[0].Point): + if DraftVecUtils.equals(anEdge.Vertexes[-1].Point, aList[e].Vertexes[-1].Point): return e return None @@ -75,19 +73,15 @@ def orientEdge(edge, normal=None, make_arc=False): if angle: edge.rotate(base, axis, angle) if isinstance(edge.Curve, Part.Line): - return Part.LineSegment(edge.Curve, - edge.FirstParameter, - edge.LastParameter) + return Part.LineSegment(edge.Curve, edge.FirstParameter, edge.LastParameter) elif make_arc and isinstance(edge.Curve, Part.Circle) and not edge.Closed: - return Part.ArcOfCircle(edge.Curve, - edge.FirstParameter, - edge.LastParameter, - edge.Curve.Axis.z > 0) + return Part.ArcOfCircle( + edge.Curve, edge.FirstParameter, edge.LastParameter, edge.Curve.Axis.z > 0 + ) elif make_arc and isinstance(edge.Curve, Part.Ellipse) and not edge.Closed: - return Part.ArcOfEllipse(edge.Curve, - edge.FirstParameter, - edge.LastParameter, - edge.Curve.Axis.z > 0) + return Part.ArcOfEllipse( + edge.Curve, edge.FirstParameter, edge.LastParameter, edge.Curve.Axis.z > 0 + ) return edge.Curve @@ -98,15 +92,13 @@ def isSameLine(e1, e2): if not isinstance(e2.Curve, Part.LineSegment): return False - if (DraftVecUtils.equals(e1.Vertexes[0].Point, - e2.Vertexes[0].Point) - and DraftVecUtils.equals(e1.Vertexes[-1].Point, - e2.Vertexes[-1].Point)): + if DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point) and DraftVecUtils.equals( + e1.Vertexes[-1].Point, e2.Vertexes[-1].Point + ): return True - elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, - e2.Vertexes[0].Point) - and DraftVecUtils.equals(e1.Vertexes[0].Point, - e2.Vertexes[-1].Point)): + elif DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point) and DraftVecUtils.equals( + e1.Vertexes[0].Point, e2.Vertexes[-1].Point + ): return True return False @@ -114,15 +106,15 @@ def isSameLine(e1, e2): def is_line(bspline): """Return True if the given BSpline curve is a straight line.""" -# previous implementation may fail for a multipole straight spline due -# a second order error in tolerance, which introduce a difference of 1e-14 -# in the values of the tangents. Also, may fail on a periodic spline. -# step = bspline.LastParameter/10 -# b = bspline.tangent(0) -# -# for i in range(10): -# if bspline.tangent(i * step) != b: -# return False + # previous implementation may fail for a multipole straight spline due + # a second order error in tolerance, which introduce a difference of 1e-14 + # in the values of the tangents. Also, may fail on a periodic spline. + # step = bspline.LastParameter/10 + # b = bspline.tangent(0) + # + # for i in range(10): + # if bspline.tangent(i * step) != b: + # return False start_point = bspline.StartPoint end_point = bspline.EndPoint @@ -133,7 +125,6 @@ def is_line(bspline): return False - def invert(shape): """Return an inverted copy of the edge or wire contained in the shape.""" if shape.ShapeType == "Wire": @@ -144,17 +135,13 @@ def invert(shape): if len(shape.Vertexes) == 1: return shape if geomType(shape) == "Line": - return Part.LineSegment(shape.Vertexes[-1].Point, - shape.Vertexes[0].Point).toShape() + return Part.LineSegment(shape.Vertexes[-1].Point, shape.Vertexes[0].Point).toShape() elif geomType(shape) == "Circle": mp = findMidpoint(shape) - return Part.Arc(shape.Vertexes[-1].Point, - mp, - shape.Vertexes[0].Point).toShape() + return Part.Arc(shape.Vertexes[-1].Point, mp, shape.Vertexes[0].Point).toShape() elif geomType(shape) in ["BSplineCurve", "BezierCurve"]: if isLine(shape.Curve): - return Part.LineSegment(shape.Vertexes[-1].Point, - shape.Vertexes[0].Point).toShape() + return Part.LineSegment(shape.Vertexes[-1].Point, shape.Vertexes[0].Point).toShape() print("DraftGeomUtils.invert: unable to invert", shape.Curve) return shape @@ -168,7 +155,7 @@ def findMidpoint(edge): if edge.Length == 0: return None else: - return edge.valueAt(edge.Curve.parameterAtDistance(edge.Length/2, edge.FirstParameter)) + return edge.valueAt(edge.Curve.parameterAtDistance(edge.Length / 2, edge.FirstParameter)) def getTangent(edge, from_point=None): @@ -180,8 +167,7 @@ def getTangent(edge, from_point=None): if geomType(edge) == "Line": return vec(edge) - elif (geomType(edge) == "BSplineCurve" - or geomType(edge) == "BezierCurve"): + elif geomType(edge) == "BSplineCurve" or geomType(edge) == "BezierCurve": if not from_point: return None cp = edge.Curve.parameter(from_point) @@ -199,7 +185,7 @@ def getTangent(edge, from_point=None): def get_referenced_edges(property_value): """Return the Edges referenced by the value of a App:PropertyLink, App::PropertyLinkList, - App::PropertyLinkSub or App::PropertyLinkSubList property.""" + App::PropertyLinkSub or App::PropertyLinkSubList property.""" edges = [] if not isinstance(property_value, list): property_value = [property_value] @@ -219,6 +205,7 @@ def get_referenced_edges(property_value): edges.append(object.Shape.Edges[edge_number]) return edges + # compatibility layer isLine = is_line diff --git a/src/Mod/Draft/draftgeoutils/faces.py b/src/Mod/Draft/draftgeoutils/faces.py index 06469daa11..d5c2c38cd3 100644 --- a/src/Mod/Draft/draftgeoutils/faces.py +++ b/src/Mod/Draft/draftgeoutils/faces.py @@ -48,8 +48,10 @@ def concatenate(shape): wires = [Part.Wire(edges) for edges in sorted_edges] face = Part.makeFace(wires, "Part::FaceMakerBullseye") except Base.FreeCADError: - print("DraftGeomUtils: Fails to join faces into one. " - + "The precision of the faces would be insufficient") + print( + "DraftGeomUtils: Fails to join faces into one. " + + "The precision of the faces would be insufficient" + ) return shape else: if not wires[0].isClosed(): @@ -106,6 +108,7 @@ def is_coplanar(faces, tol=-1): return True + isCoplanar = is_coplanar @@ -122,10 +125,8 @@ def bind(w1, w2, per_segment=False): def create_face(w1, w2): try: - w3 = Part.LineSegment(w1.Vertexes[0].Point, - w2.Vertexes[0].Point).toShape() - w4 = Part.LineSegment(w1.Vertexes[-1].Point, - w2.Vertexes[-1].Point).toShape() + w3 = Part.LineSegment(w1.Vertexes[0].Point, w2.Vertexes[0].Point).toShape() + w4 = Part.LineSegment(w1.Vertexes[-1].Point, w2.Vertexes[-1].Point).toShape() except Part.OCCError: print("DraftGeomUtils: unable to bind wires") return None @@ -138,12 +139,10 @@ def bind(w1, w2, per_segment=False): print("DraftGeomUtils: unable to bind wires") return None - if (per_segment - and len(w1.Edges) > 1 - and len(w1.Edges) == len(w2.Edges)): + if per_segment and len(w1.Edges) > 1 and len(w1.Edges) == len(w2.Edges): faces = [] faces_list = [] - for (edge1, edge2) in zip(w1.Edges, w2.Edges): + for edge1, edge2 in zip(w1.Edges, w2.Edges): # Find touching edges due to ArchWall Align in opposite # directions, and/or opposite edge orientations. # @@ -181,32 +180,40 @@ def bind(w1, w2, per_segment=False): # 1) there are only 2 series, connecting would return invalid shape # 2) 1st series of faces happens to be [], i.e. 1st edge pairs touch # - if w1.isClosed() and w2.isClosed() \ - and len(faces_list) > 1 and faces_list[0]: - faces_list[0].extend(faces) # TODO: To be reviewed, 'afterthought' on 2025.3.29, seems by 'extend', faces in 1st and last faces are not in sequential order + if w1.isClosed() and w2.isClosed() and len(faces_list) > 1 and faces_list[0]: + faces_list[0].extend( + faces + ) # TODO: To be reviewed, 'afterthought' on 2025.3.29, seems by 'extend', faces in 1st and last faces are not in sequential order else: faces_list.append(faces) # Break into separate list from collections import Counter + if faces_list: faces_fused_list = [] for faces in faces_list: dir = [] countDir = None for f in faces: - dir.append(f.normalAt(0,0).z) + dir.append(f.normalAt(0, 0).z) countDir = Counter(dir) l = len(faces) m = max(countDir.values()) # max(countDir, key=countDir.get) if m != l: - print("DraftGeomUtils: Problem, the direction of " + str(l-m) + " out of " + str(l) + " segment is reversed, please check!") - if len(faces) > 1 : + print( + "DraftGeomUtils: Problem, the direction of " + + str(l - m) + + " out of " + + str(l) + + " segment is reversed, please check!" + ) + if len(faces) > 1: # Below not good if a face is self-intersecting or reversed - #faces_fused = faces[0].fuse(faces[1:]).removeSplitter().Faces[0] + # faces_fused = faces[0].fuse(faces[1:]).removeSplitter().Faces[0] rf = faces[0] for f in faces[1:]: rf = rf.fuse(f).removeSplitter().Faces[0] - #rf = rf.fuse(f) # Not working - #rf = rf.removeSplitter().Faces[0] # Not working + # rf = rf.fuse(f) # Not working + # rf = rf.removeSplitter().Faces[0] # Not working faces_fused_list.append(rf) # faces might be empty list [], see above; skip if empty elif faces: @@ -217,19 +224,25 @@ def bind(w1, w2, per_segment=False): dir = [] countDir = None for f in faces: - dir.append(f.normalAt(0,0).z) + dir.append(f.normalAt(0, 0).z) countDir = Counter(dir) l = len(faces) m = max(countDir.values()) # max(countDir, key=countDir.get) if m != l: - print("DraftGeomUtils: Problem, the direction of " + str(l-m) + " out of " + str(l) + " segment is reversed, please check!") + print( + "DraftGeomUtils: Problem, the direction of " + + str(l - m) + + " out of " + + str(l) + + " segment is reversed, please check!" + ) # Below not good if a face is self-intersecting or reversed - #return faces[0].fuse(faces[1:]).removeSplitter().Faces[0] + # return faces[0].fuse(faces[1:]).removeSplitter().Faces[0] rf = faces[0] for f in faces[1:]: rf = rf.fuse(f).removeSplitter().Faces[0] - #rf = rf.fuse(f) # Not working - #rf = rf.removeSplitter().Faces[0] # Not working + # rf = rf.fuse(f) # Not working + # rf = rf.removeSplitter().Faces[0] # Not working return rf elif w1.isClosed() and w2.isClosed(): @@ -385,4 +398,5 @@ def removeSplitter(shape): return None + ## @} diff --git a/src/Mod/Draft/draftgeoutils/fillets.py b/src/Mod/Draft/draftgeoutils/fillets.py index 2ab56ebf31..af7260628c 100644 --- a/src/Mod/Draft/draftgeoutils/fillets.py +++ b/src/Mod/Draft/draftgeoutils/fillets.py @@ -54,14 +54,13 @@ def fillet(lEdges, r, chamfer=False): The dictionary contains edges with keys 'Arc' and 'Line'. """ if not existingCurveType: - existingCurveType = {'Line': [], - 'Arc': []} + existingCurveType = {"Line": [], "Arc": []} if issubclass(type(edge.Curve), Part.LineSegment): - existingCurveType['Line'] += [edge] + existingCurveType["Line"] += [edge] elif issubclass(type(edge.Curve), Part.Line): - existingCurveType['Line'] += [edge] + existingCurveType["Line"] += [edge] elif issubclass(type(edge.Curve), Part.Circle): - existingCurveType['Arc'] += [edge] + existingCurveType["Arc"] += [edge] else: raise ValueError("Edge's curve must be either Line or Arc") return existingCurveType @@ -93,7 +92,7 @@ def fillet(lEdges, r, chamfer=False): else: lVertexes = [rndEdges[0].Vertexes[0], rndEdges[0].Vertexes[-1], rndEdges[1].Vertexes[0]] - if len(curveType['Line']) == 2: + if len(curveType["Line"]) == 2: # Deals with 2-line-edges lists U1 = lVertexes[0].Point.sub(lVertexes[1].Point) U1.normalize() @@ -104,14 +103,12 @@ def fillet(lEdges, r, chamfer=False): alpha = U1.getAngle(U2) # Edges have same direction - if (round(alpha, precision()) == 0 - or round(alpha - math.pi, precision()) == 0): - print("DraftGeomUtils.fillet: Warning: " - "edges have same direction. Did nothing") + if round(alpha, precision()) == 0 or round(alpha - math.pi, precision()) == 0: + print("DraftGeomUtils.fillet: Warning: " "edges have same direction. Did nothing") return rndEdges - dToCenter = r / math.sin(alpha/2.0) - dToTangent = (dToCenter**2-r**2)**(0.5) + dToCenter = r / math.sin(alpha / 2.0) + dToTangent = (dToCenter**2 - r**2) ** (0.5) dirVect = App.Vector(U1) dirVect.scale(dToTangent, dToTangent, dToTangent) arcPt1 = lVertexes[1].Point.add(dirVect) @@ -126,8 +123,7 @@ def fillet(lEdges, r, chamfer=False): arcPt3 = lVertexes[1].Point.add(dirVect) if (dToTangent > rndEdges[0].Length) or (dToTangent > rndEdges[1].Length): - print("DraftGeomUtils.fillet: Error: radius value ", r, - " is too high") + print("DraftGeomUtils.fillet: Error: radius value ", r, " is too high") return rndEdges if chamfer: @@ -139,19 +135,17 @@ def fillet(lEdges, r, chamfer=False): # fillet consumes entire first edge rndEdges.pop(0) else: - rndEdges[0] = Part.Edge(Part.LineSegment(lVertexes[0].Point, - arcPt1)) + rndEdges[0] = Part.Edge(Part.LineSegment(lVertexes[0].Point, arcPt1)) if lVertexes[2].Point != arcPt3: # fillet does not consume entire second edge - rndEdges += [Part.Edge(Part.LineSegment(arcPt3, - lVertexes[2].Point))] + rndEdges += [Part.Edge(Part.LineSegment(arcPt3, lVertexes[2].Point))] return rndEdges - elif len(curveType['Arc']) == 1: + elif len(curveType["Arc"]) == 1: # Deals with lists containing an arc and a line - if rndEdges[0] in curveType['Arc']: + if rndEdges[0] in curveType["Arc"]: lineEnd = lVertexes[2] arcEnd = lVertexes[0] arcFirst = True @@ -159,10 +153,10 @@ def fillet(lEdges, r, chamfer=False): lineEnd = lVertexes[0] arcEnd = lVertexes[2] arcFirst = False - arcCenter = curveType['Arc'][0].Curve.Center - arcRadius = curveType['Arc'][0].Curve.Radius - arcAxis = curveType['Arc'][0].Curve.Axis - arcLength = curveType['Arc'][0].Length + arcCenter = curveType["Arc"][0].Curve.Center + arcRadius = curveType["Arc"][0].Curve.Radius + arcAxis = curveType["Arc"][0].Curve.Axis + arcLength = curveType["Arc"][0].Length U1 = lineEnd.Point.sub(lVertexes[1].Point) U1.normalize() @@ -183,20 +177,19 @@ def fillet(lEdges, r, chamfer=False): if round(projCenter, precision()) > 0: newRadius = arcRadius - r - elif (round(projCenter, precision()) < 0 - or (round(projCenter, precision()) == 0 and U1.dot(T) > 0)): + elif round(projCenter, precision()) < 0 or ( + round(projCenter, precision()) == 0 and U1.dot(T) > 0 + ): newRadius = arcRadius + r else: - print("DraftGeomUtils.fillet: Warning: " - "edges are already tangent. Did nothing") + print("DraftGeomUtils.fillet: Warning: " "edges are already tangent. Did nothing") return rndEdges toNewCent = newRadius**2 - dCenterToLine**2 if toNewCent > 0: - toNewCent = abs(abs(projCenter) - toNewCent**(0.5)) + toNewCent = abs(abs(projCenter) - toNewCent ** (0.5)) else: - print("DraftGeomUtils.fillet: Error: radius value ", r, - " is too high") + print("DraftGeomUtils.fillet: Error: radius value ", r, " is too high") return rndEdges U1.scale(toNewCent, toNewCent, toNewCent) @@ -232,9 +225,8 @@ def fillet(lEdges, r, chamfer=False): toCenter.scale(-1, -1, -1) delLength = arcRadius * V[0].sub(arcCenter).getAngle(toCenter) - if delLength > arcLength or toNewCent > curveType['Line'][0].Length: - print("DraftGeomUtils.fillet: Error: radius value ", r, - " is too high") + if delLength > arcLength or toNewCent > curveType["Line"][0].Length: + print("DraftGeomUtils.fillet: Error: radius value ", r, " is too high") return rndEdges arcAsEdge = arcFrom2Pts(V[-arcFirst], V[-myTrick], arcCenter, arcAxis) @@ -245,26 +237,29 @@ def fillet(lEdges, r, chamfer=False): rndEdges[not arcFirst] = arcAsEdge rndEdges[arcFirst] = lineAsEdge if chamfer: - rndEdges[1:1] = [Part.Edge(Part.LineSegment(arcPt[- arcFirst], - arcPt[- myTrick]))] + rndEdges[1:1] = [Part.Edge(Part.LineSegment(arcPt[-arcFirst], arcPt[-myTrick]))] else: - rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[- arcFirst], - arcPt[1], - arcPt[- myTrick]))] + rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[-arcFirst], arcPt[1], arcPt[-myTrick]))] return rndEdges - elif len(curveType['Arc']) == 2: + elif len(curveType["Arc"]) == 2: # Deals with lists of 2 arc-edges - (arcCenter, arcRadius, - arcAxis, arcLength, - toCenter, T, newRadius) = [], [], [], [], [], [], [] + (arcCenter, arcRadius, arcAxis, arcLength, toCenter, T, newRadius) = ( + [], + [], + [], + [], + [], + [], + [], + ) for i in range(2): - arcCenter += [curveType['Arc'][i].Curve.Center] - arcRadius += [curveType['Arc'][i].Curve.Radius] - arcAxis += [curveType['Arc'][i].Curve.Axis] - arcLength += [curveType['Arc'][i].Length] + arcCenter += [curveType["Arc"][i].Curve.Center] + arcRadius += [curveType["Arc"][i].Curve.Radius] + arcAxis += [curveType["Arc"][i].Curve.Axis] + arcLength += [curveType["Arc"][i].Length] toCenter += [arcCenter[i].sub(lVertexes[1].Point)] T += [arcAxis[0].cross(toCenter[0])] @@ -272,7 +267,7 @@ def fillet(lEdges, r, chamfer=False): CentToCent = toCenter[1].sub(toCenter[0]) dCentToCent = CentToCent.Length - sameDirection = (arcAxis[0].dot(arcAxis[1]) > 0) + sameDirection = arcAxis[0].dot(arcAxis[1]) > 0 TcrossT = T[0].cross(T[1]) if sameDirection: @@ -286,8 +281,7 @@ def fillet(lEdges, r, chamfer=False): newRadius += [arcRadius[0] + r] newRadius += [arcRadius[1] + r] else: - print("DraftGeomUtils.fillet: Warning: " - "edges are already tangent. Did nothing") + print("DraftGeomUtils.fillet: Warning: " "edges are already tangent. Did nothing") return rndEdges elif not sameDirection: @@ -305,24 +299,22 @@ def fillet(lEdges, r, chamfer=False): newRadius += [arcRadius[0] + r] newRadius += [arcRadius[1] - r] else: - print("DraftGeomUtils.fillet: Warning: " - "arcs are coincident. Did nothing") + print("DraftGeomUtils.fillet: Warning: " "arcs are coincident. Did nothing") return rndEdges else: - print("DraftGeomUtils.fillet: Warning: " - "edges are already tangent. Did nothing") + print("DraftGeomUtils.fillet: Warning: " "edges are already tangent. Did nothing") return rndEdges - if (newRadius[0] + newRadius[1] < dCentToCent - or newRadius[0] - newRadius[1] > dCentToCent - or newRadius[1] - newRadius[0] > dCentToCent): - print("DraftGeomUtils.fillet: Error: radius value ", r, - " is too high") + if ( + newRadius[0] + newRadius[1] < dCentToCent + or newRadius[0] - newRadius[1] > dCentToCent + or newRadius[1] - newRadius[0] > dCentToCent + ): + print("DraftGeomUtils.fillet: Error: radius value ", r, " is too high") return rndEdges - x = ((dCentToCent**2 + newRadius[0]**2 - newRadius[1]**2) - / (2*dCentToCent)) - y = (newRadius[0]**2 - x**2)**(0.5) + x = (dCentToCent**2 + newRadius[0] ** 2 - newRadius[1] ** 2) / (2 * dCentToCent) + y = (newRadius[0] ** 2 - x**2) ** (0.5) CentToCent.normalize() toCenter[0].normalize() @@ -336,8 +328,7 @@ def fillet(lEdges, r, chamfer=False): CentToCent.scale(x, x, x) normVect.scale(y, y, y) newCent = arcCenter[0].add(CentToCent.add(normVect)) - CentToNewCent = [newCent.sub(arcCenter[0]), - newCent.sub(arcCenter[1])] + CentToNewCent = [newCent.sub(arcCenter[0]), newCent.sub(arcCenter[1])] for i in range(2): CentToNewCent[i].normalize() @@ -357,24 +348,19 @@ def fillet(lEdges, r, chamfer=False): arcAsEdge = [] for i in range(2): toCenter[i].scale(-1, -1, -1) - delLength = (arcRadius[i] - * arcPt[-i].sub(arcCenter[i]).getAngle(toCenter[i])) + delLength = arcRadius[i] * arcPt[-i].sub(arcCenter[i]).getAngle(toCenter[i]) if delLength > arcLength[i]: - print("DraftGeomUtils.fillet: Error: radius value ", r, - " is too high") + print("DraftGeomUtils.fillet: Error: radius value ", r, " is too high") return rndEdges V = [arcPt[-i], lVertexes[-i].Point] - arcAsEdge += [arcFrom2Pts(V[i-1], V[-i], - arcCenter[i], arcAxis[i])] + arcAsEdge += [arcFrom2Pts(V[i - 1], V[-i], arcCenter[i], arcAxis[i])] rndEdges[0] = arcAsEdge[0] rndEdges[1] = arcAsEdge[1] if chamfer: rndEdges[1:1] = [Part.Edge(Part.LineSegment(arcPt[0], arcPt[2]))] else: - rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[0], - arcPt[1], - arcPt[2]))] + rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[0], arcPt[1], arcPt[2]))] return rndEdges @@ -390,7 +376,7 @@ def filletWire(aWire, r, chamfer=False): filEdges = [edges[0]] for i in range(len(edges) - 1): - result = fillet([filEdges[-1], edges[i+1]], r, chamfer) + result = fillet([filEdges[-1], edges[i + 1]], r, chamfer) if len(result) > 2: filEdges[-1:] = result[0:3] else: @@ -404,4 +390,5 @@ def filletWire(aWire, r, chamfer=False): return Part.Wire(filEdges) + ## @} diff --git a/src/Mod/Draft/draftgeoutils/general.py b/src/Mod/Draft/draftgeoutils/general.py index 0323c54852..2a624b9f1e 100644 --- a/src/Mod/Draft/draftgeoutils/general.py +++ b/src/Mod/Draft/draftgeoutils/general.py @@ -59,7 +59,7 @@ def precision(): return precisionInt -def vec(edge, use_orientation = False): +def vec(edge, use_orientation=False): """Return a vector from an edge or a Part.LineSegment. If use_orientation is True, it takes into account the edges orientation. @@ -114,8 +114,7 @@ def isNull(something): else: return False elif isinstance(something, App.Placement): - if (something.Base == App.Vector(0, 0, 0) - and something.Rotation.Q == (0, 0, 0, 1)): + if something.Base == App.Vector(0, 0, 0) and something.Rotation.Q == (0, 0, 0, 1): return True else: return False @@ -148,6 +147,7 @@ def isAligned(edge, axis="x"): The axis can be 'x', 'y' or 'z'. """ + def is_same(a, b): return round(a, precision()) == round(b, precision()) @@ -193,12 +193,9 @@ def getQuad(face): v2 = vec(face.Edges[1]) v3 = vec(face.Edges[2]) v4 = vec(face.Edges[3]) - angles90 = [round(math.pi*0.5, precision()), - round(math.pi*1.5, precision())] + angles90 = [round(math.pi * 0.5, precision()), round(math.pi * 1.5, precision())] - angles180 = [0, - round(math.pi, precision()), - round(math.pi*2, precision())] + angles180 = [0, round(math.pi, precision()), round(math.pi * 2, precision())] for ov in [v2, v3, v4]: if not (round(v1.getAngle(ov), precision()) in angles90 + angles180): return None @@ -267,7 +264,7 @@ def geomType(edge): return "Ellipse" else: return "Unknown" - except Exception: # catch all errors, no only TypeError + except Exception: # catch all errors, no only TypeError return "Unknown" @@ -319,10 +316,10 @@ def getBoundaryAngles(angle, alist): negs = False for i in range(len(alist)): if alist[i] < 0: - alist[i] = 2*math.pi + alist[i] + alist[i] = 2 * math.pi + alist[i] negs = True if angle < 0: - angle = 2*math.pi + angle + angle = 2 * math.pi + angle negs = True lower = None @@ -350,11 +347,12 @@ def getBoundaryAngles(angle, alist): higher = a if higher is None: - higher = 2*math.pi + higher = 2 * math.pi for a in alist: if a < higher: higher = a return lower, higher + ## @} diff --git a/src/Mod/Draft/draftgeoutils/geo_arrays.py b/src/Mod/Draft/draftgeoutils/geo_arrays.py index a39c29a1a2..5b8ee53d2e 100644 --- a/src/Mod/Draft/draftgeoutils/geo_arrays.py +++ b/src/Mod/Draft/draftgeoutils/geo_arrays.py @@ -48,7 +48,7 @@ Part = lz.LazyLoader("Part", globals(), "Part") def print_places(places, title="Places"): """Print a vector with a title.""" - _msg(12*"-") + _msg(12 * "-") _msg(title) for i in places: _msg("{}".format(i)) @@ -87,8 +87,7 @@ def get_twisted_placements(path, count=15, rot_factor=0.25): """Get the placements of the twisted array elements.""" count = max(count, 1) - (norm, edge, - step, inc) = get_init_values(path, count) + (norm, edge, step, inc) = get_init_values(path, count) increment = 0 places = [] @@ -111,24 +110,18 @@ def get_twisted_placements(path, count=15, rot_factor=0.25): def get_twisted_array_shape(base, path, count=15, rot_factor=0.25): """Get the twisted array shape as a compound.""" - places, _ = get_twisted_placements(path, - count=count, - rot_factor=rot_factor) + places, _ = get_twisted_placements(path, count=count, rot_factor=rot_factor) shapes, _ = create_frames(base, places) shape = Part.makeCompound(shapes) return shape -def get_twisted_bridge_shape(base, path, count=15, rot_factor=0.25, - width=100, - thickness=10): +def get_twisted_bridge_shape(base, path, count=15, rot_factor=0.25, width=100, thickness=10): """Get the twisted bridge array shape as a compound.""" compound = list() - places, _ = get_twisted_placements(path, - count=count, - rot_factor=rot_factor) + places, _ = get_twisted_placements(path, count=count, rot_factor=rot_factor) # print_places(places) shapes, profiles = create_frames(base, places) @@ -175,7 +168,7 @@ def make_walkway(path, width=100, thickness=10): """Construct the walkway of the twisted bridge array.""" spine = path.Shape.Edges[0] - half_size = width/2 + half_size = width / 2 offset_height = thickness norm1 = App.Vector(0, 0, 1) @@ -187,8 +180,7 @@ def make_walkway(path, width=100, thickness=10): place.Rotation = App.Rotation(binorm1, norm1, tan1) place.move(v1 - App.Vector(0, 0, 3 * offset_height)) - plane = Part.makePlane(width, thickness, - App.Vector(-half_size, -2 * offset_height, 0)) + plane = Part.makePlane(width, thickness, App.Vector(-half_size, -2 * offset_height, 0)) face = Part.Face(plane) face.Placement = place.multiply(face.Placement) @@ -197,4 +189,5 @@ def make_walkway(path, width=100, thickness=10): return sweep + ## @} diff --git a/src/Mod/Draft/draftgeoutils/geometry.py b/src/Mod/Draft/draftgeoutils/geometry.py index 1c24d0738f..b53b917394 100644 --- a/src/Mod/Draft/draftgeoutils/geometry.py +++ b/src/Mod/Draft/draftgeoutils/geometry.py @@ -111,8 +111,7 @@ def findDistance(point, edge, strict=False): if strict: s1 = newpoint.sub(edge[0]) s2 = newpoint.sub(edge[1]) - if (s1.Length <= segment.Length - and s2.Length <= segment.Length): + if s1.Length <= segment.Length and s2.Length <= segment.Length: return dist else: return None @@ -131,14 +130,13 @@ def findDistance(point, edge, strict=False): newpoint = point.add(dist) - if (dist.Length == 0): + if dist.Length == 0: return None if strict: s1 = newpoint.sub(edge.Vertexes[0].Point) s2 = newpoint.sub(edge.Vertexes[-1].Point) - if (s1.Length <= segment.Length - and s2.Length <= segment.Length): + if s1.Length <= segment.Length and s2.Length <= segment.Length: return dist else: return None @@ -170,7 +168,7 @@ def findDistance(point, edge, strict=False): ang1 = DraftVecUtils.angle(ve1.sub(center)) ang2 = DraftVecUtils.angle(ve2.sub(center)) angpt = DraftVecUtils.angle(newpoint.sub(center)) - if ang1 >= ang2: # Arc does not cross the 9 o'clock point. + if ang1 >= ang2: # Arc does not cross the 9 o'clock point. if ang1 >= angpt and angpt >= ang2: return dist else: @@ -182,15 +180,13 @@ def findDistance(point, edge, strict=False): else: return dist - elif (geomType(edge) == "BSplineCurve" - or geomType(edge) == "BezierCurve"): + elif geomType(edge) == "BSplineCurve" or geomType(edge) == "BezierCurve": try: pr = edge.Curve.parameter(point) np = edge.Curve.value(pr) dist = np.sub(point) except Part.OCCError: - print("DraftGeomUtils: Unable to get curve parameter " - "for point ", point) + print("DraftGeomUtils: Unable to get curve parameter " "for point ", point) return None else: return dist @@ -263,7 +259,9 @@ def get_shape_normal(shape): if not is_straight_line(shape): return None start_edge = shape.Edges[0] - x_vec = start_edge.tangentAt(start_edge.FirstParameter) # Return vector is in global coordinate + x_vec = start_edge.tangentAt( + start_edge.FirstParameter + ) # Return vector is in global coordinate local_x_vec = shape_rot.inverted().multVec(x_vec) # local_rot = App.Rotation(local_x_vec, App.Vector(0, 1, 0), App.Vector(0, 0, 1), "XZY") # see https://blog.freecad.org/2023/01/16/the-rotation-api-in-freecad/ for App.Rotation(vecx, vecy, vecz, string) @@ -275,7 +273,7 @@ def get_shape_normal(shape): # Now, check the normal direction of the plane (plane.Axis). # The final deduced normal should be 'in the direction' of the z-direction of the shape's placement, # if plane.Axis is in the 'opposite' direction of the Z direction of the shape's placement, reverse it. - if normal.getAngle(shape_normal) > math.pi/2: + if normal.getAngle(shape_normal) > math.pi / 2: normal = normal.negative() return normal @@ -392,8 +390,8 @@ def is_straight_line(shape, tol=-1): dir_start_edge = start_edge.tangentAt(start_edge.FirstParameter) point_start_edge = start_edge.firstVertex().Point - #set tolerance - if tol <=0: + # set tolerance + if tol <= 0: err = shape.globalTolerance(tol) else: err = tol @@ -405,8 +403,8 @@ def is_straight_line(shape, tol=-1): # check if edge is curve or no parallel to start_edge # because sin(x) = x + O(x**3), for small angular deflection it's # enough use the cross product of directions (or dot with a normal) - if (abs(edge.Length - first_point.distanceToPoint(last_point)) > err - + if ( + abs(edge.Length - first_point.distanceToPoint(last_point)) > err # https://forum.freecad.org/viewtopic.php?p=726101#p726101 # Shape with parallel edges but not colinear used to return True # by this function, below line added fixes this bug. @@ -423,9 +421,9 @@ def is_straight_line(shape, tol=-1): # ./draftfunctions/upgrade.py # ./draftgeoutils/geometry.py # ./draftmake/make_wire.py - or first_point.distanceToLine(point_start_edge, dir_start_edge) > err \ - # - or dir_start_edge.cross(dir_edge).Length > err): + or first_point.distanceToLine(point_start_edge, dir_start_edge) > err # + or dir_start_edge.cross(dir_edge).Length > err + ): return False return True @@ -446,8 +444,8 @@ def are_coplanar(shape_a, shape_b, tol=-1): plane_a = find_plane(shape_a, tol) plane_b = find_plane(shape_b, tol) - #set tolerance - if tol <=0: + # set tolerance + if tol <= 0: err = 1e-7 else: err = tol @@ -456,8 +454,7 @@ def are_coplanar(shape_a, shape_b, tol=-1): normal_a = plane_a.Axis normal_b = plane_b.Axis proj = plane_a.projectPoint(plane_b.Position) - if (normal_a.cross(normal_b).Length > err - or plane_b.Position.sub(proj).Length > err): + if normal_a.cross(normal_b).Length > err or plane_b.Position.sub(proj).Length > err: return False else: return True @@ -502,8 +499,8 @@ def get_spline_surface_normal(shape, tol=-1): if len(shape.Faces) == 0: return None - #set tolerance - if tol <=0: + # set tolerance + if tol <= 0: err = shape.globalTolerance(tol) else: err = tol @@ -515,8 +512,8 @@ def get_spline_surface_normal(shape, tol=-1): # find bounds of first_surf u0, u1, v0, v1 = first_surf.bounds() - u = (u0 + u1)/2 - v = (v0 + v1)/2 + u = (u0 + u1) / 2 + v = (v0 + v1) / 2 first_normal = first_surf.normal(u, v) # check if all faces are planar and parallel for face in shape.Faces: @@ -524,8 +521,8 @@ def get_spline_surface_normal(shape, tol=-1): if not surf.isPlanar(tol): return None u0, u1, v0, v1 = surf.bounds() - u = (u0 + u1)/2 - v = (v0 + v1)/2 + u = (u0 + u1) / 2 + v = (v0 + v1) / 2 surf_normal = surf.normal(u, v) if first_normal.cross(surf_normal).Length > err: return None @@ -534,6 +531,7 @@ def get_spline_surface_normal(shape, tol=-1): return normal + def find_plane(shape, tol=-1): """Find the plane containing the shape if possible. Use this function as a workaround due Part.Shape.findPlane @@ -832,13 +830,13 @@ def project_point_on_plane(point, base, normal, direction=None, force_projection return point - delta_ax_proj / cos * direction -#compatibility layer +# compatibility layer getSplineNormal = get_spline_normal getNormal = get_normal -isPlanar = is_planar +isPlanar = is_planar ## @} diff --git a/src/Mod/Draft/draftgeoutils/intersections.py b/src/Mod/Draft/draftgeoutils/intersections.py index 844c4a2567..25ed99a739 100644 --- a/src/Mod/Draft/draftgeoutils/intersections.py +++ b/src/Mod/Draft/draftgeoutils/intersections.py @@ -41,10 +41,9 @@ Part = lz.LazyLoader("Part", globals(), "Part") # @{ -def findIntersection(edge1, edge2, - infinite1=False, infinite2=False, - ex1=False, ex2=False, - dts=True, findAll=False): +def findIntersection( + edge1, edge2, infinite1=False, infinite2=False, ex1=False, ex2=False, dts=True, findAll=False +): """Return a list containing the intersection points of 2 edges. You can also feed 4 points instead of `edge1` and `edge2`. @@ -86,12 +85,13 @@ def findIntersection(edge1, edge2, list A list of intersection points """ + def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2): if pt1: # first check if we don't already have coincident endpoints if pt1 in [pt3, pt4]: return [pt1] - elif (pt2 in [pt3, pt4]): + elif pt2 in [pt3, pt4]: return [pt2] norm1 = pt2.sub(pt1).cross(pt3.sub(pt1)) norm2 = pt2.sub(pt4).cross(pt3.sub(pt4)) @@ -121,9 +121,11 @@ def findIntersection(edge1, edge2, norm3 = vec1.cross(vec2) denom = norm3.x + norm3.y + norm3.z if not DraftVecUtils.isNull(norm3) and denom != 0: - k = ((pt3.z - pt1.z) * (vec2.x - vec2.y) - + (pt3.y - pt1.y) * (vec2.z - vec2.x) - + (pt3.x - pt1.x) * (vec2.y - vec2.z))/denom + k = ( + (pt3.z - pt1.z) * (vec2.x - vec2.y) + + (pt3.y - pt1.y) * (vec2.z - vec2.x) + + (pt3.x - pt1.x) * (vec2.y - vec2.z) + ) / denom vec1.scale(k, k, k) intp = pt1.add(vec1) @@ -142,19 +144,27 @@ def findIntersection(edge1, edge2, tol = pow(10, -precision()) # First, check bound boxes - if (isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge) - and (not infinite1) and (not infinite2)): + if ( + isinstance(edge1, Part.Edge) + and isinstance(edge2, Part.Edge) + and (not infinite1) + and (not infinite2) + ): bb1 = edge1.BoundBox bb1.enlarge(tol) # enlarge one box to account for rounding errors if not bb1.intersect(edge2.BoundBox): return [] # bound boxes don't intersect # First, try to use Shape.section if possible - if dts \ - and ((isinstance(edge1, Part.Edge) and isinstance(edge2, (Part.Edge, Part.Face))) - or (isinstance(edge1, (Part.Edge, Part.Face)) and isinstance(edge2, Part.Edge))) \ - and (not infinite1) \ - and (not infinite2): + if ( + dts + and ( + (isinstance(edge1, Part.Edge) and isinstance(edge2, (Part.Edge, Part.Face))) + or (isinstance(edge1, (Part.Edge, Part.Face)) and isinstance(edge2, Part.Edge)) + ) + and (not infinite1) + and (not infinite2) + ): return [v.Point for v in edge1.section((edge2), tol).Vertexes] pt1 = None @@ -171,14 +181,20 @@ def findIntersection(edge1, edge2, elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line"): # we have 2 straight lines - pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point, - edge1.Vertexes[1].Point, - edge2.Vertexes[0].Point, - edge2.Vertexes[1].Point] + pt1, pt2, pt3, pt4 = [ + edge1.Vertexes[0].Point, + edge1.Vertexes[1].Point, + edge2.Vertexes[0].Point, + edge2.Vertexes[1].Point, + ] return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2) - elif ((geomType(edge1) == "Circle") and (geomType(edge2) == "Line") - or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle")): + elif ( + (geomType(edge1) == "Circle") + and (geomType(edge2) == "Line") + or (geomType(edge1) == "Line") + and (geomType(edge2) == "Circle") + ): # deals with an arc or circle and a line edges = [edge1, edge2] @@ -218,7 +234,7 @@ def findIntersection(edge1, edge2, toLine = pt1.sub(center).add(onLine) if toLine.Length < arc.Curve.Radius: - dOnLine = (arc.Curve.Radius**2 - toLine.Length**2)**(0.5) + dOnLine = (arc.Curve.Radius**2 - toLine.Length**2) ** (0.5) onLine = App.Vector(dirVec) onLine.scale(dOnLine, dOnLine, dOnLine) int += [center.add(toLine).add(onLine)] @@ -240,10 +256,9 @@ def findIntersection(edge1, edge2, return [] dToPlane = center.sub(pt1).dot(toPlane) toPlane = App.Vector(pt1) - toPlane.scale(dToPlane/d, dToPlane/d, dToPlane/d) + toPlane.scale(dToPlane / d, dToPlane / d, dToPlane / d) ptOnPlane = toPlane.add(pt1) - if round(ptOnPlane.sub(center).Length - arc.Curve.Radius, - precision()) == 0: + if round(ptOnPlane.sub(center).Length - arc.Curve.Radius, precision()) == 0: int = [ptOnPlane] else: return [] @@ -277,9 +292,11 @@ def findIntersection(edge1, edge2, dc2c = c2c.Length if not DraftVecUtils.isNull(c2c): c2c.normalize() - if (round(rad1 + rad2 - dc2c, precision()) < 0 - or round(rad1 - dc2c - rad2, precision()) > 0 - or round(rad2 - dc2c - rad1, precision()) > 0): + if ( + round(rad1 + rad2 - dc2c, precision()) < 0 + or round(rad1 - dc2c - rad2, precision()) > 0 + or round(rad2 - dc2c - rad1, precision()) > 0 + ): return [] else: norm = c2c.cross(axis1) @@ -288,8 +305,8 @@ def findIntersection(edge1, edge2, if DraftVecUtils.isNull(norm): x = 0 else: - x = (dc2c**2 + rad1**2 - rad2**2) / (2*dc2c) - y = abs(rad1**2 - x**2)**(0.5) + x = (dc2c**2 + rad1**2 - rad2**2) / (2 * dc2c) + y = abs(rad1**2 - x**2) ** (0.5) c2c.scale(x, x, x) if round(y, precision()) != 0: norm.scale(y, y, y) @@ -307,14 +324,13 @@ def findIntersection(edge1, edge2, V = axis1.cross(U) dToPlane = c2c.dot(axis2) d = V.add(cent1).dot(axis2) - V.scale(dToPlane/d, dToPlane/d, dToPlane/d) + V.scale(dToPlane / d, dToPlane / d, dToPlane / d) PtOn2Planes = V.add(cent1) planeIntersectionVector = U.add(PtOn2Planes) - intTemp = findIntersection(planeIntersectionVector, - edge1, True, True) + intTemp = findIntersection(planeIntersectionVector, edge1, True, True) int = [] for pt in intTemp: - if round(pt.sub(cent2).Length-rad2, precision()) == 0: + if round(pt.sub(cent2).Length - rad2, precision()) == 0: int += [pt] if infinite1 is False: @@ -328,8 +344,10 @@ def findIntersection(edge1, edge2, return int else: - print("DraftGeomUtils: Unsupported curve type: " - "(" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")") + print( + "DraftGeomUtils: Unsupported curve type: " + "(" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")" + ) return [] @@ -344,10 +362,11 @@ def wiresIntersect(wire1, wire2): return True return False + def connect(edges, closed=False, wireNedge=False): """Connect the edges in the given list by their intersections.""" - inters_list = [] # List of intersections (with the previous edge). + inters_list = [] # List of intersections (with the previous edge). for i, curr in enumerate(edges): if i > 0: prev = edges[i - 1] @@ -357,14 +376,15 @@ def connect(edges, closed=False, wireNedge=False): inters_list.append(None) continue - curr_inters_list = (findIntersection(prev, curr, True, True)) + curr_inters_list = findIntersection(prev, curr, True, True) if len(curr_inters_list) == 0: inters_list.append(None) elif len(curr_inters_list) == 1: inters_list.append(curr_inters_list[0]) else: - inters = curr_inters_list[DraftVecUtils.closest(curr.Vertexes[0].Point, - curr_inters_list)] + inters = curr_inters_list[ + DraftVecUtils.closest(curr.Vertexes[0].Point, curr_inters_list) + ] inters_list.append(inters) new_edges_full = [] @@ -418,9 +438,7 @@ def connect(edges, closed=False, wireNedge=False): except Part.OCCError: print("DraftGeomUtils.connect: unable to connect edges") for edge in new_edges: - print(edge.Curve, " ", - edge.Vertexes[0].Point, " ", - edge.Vertexes[-1].Point) + print(edge.Curve, " ", edge.Vertexes[0].Point, " ", edge.Vertexes[-1].Point) return None @@ -450,4 +468,5 @@ def angleBisection(edge1, edge2): return Part.LineSegment(origin, origin.add(direction)).toShape() + ## @} diff --git a/src/Mod/Draft/draftgeoutils/linear_algebra.py b/src/Mod/Draft/draftgeoutils/linear_algebra.py index 0a83b4692b..c14a27b3ba 100644 --- a/src/Mod/Draft/draftgeoutils/linear_algebra.py +++ b/src/Mod/Draft/draftgeoutils/linear_algebra.py @@ -52,10 +52,10 @@ def linearFromPoints(p1, p2): return None line = {} - line['dx'] = (p2.x - p1.x) - line['dy'] = (p2.y - p1.y) - line['slope'] = line['dy'] / line['dx'] - line['offset'] = p1.y - line['slope'] * p1.x + line["dx"] = p2.x - p1.x + line["dy"] = p2.y - p1.y + line["slope"] = line["dy"] / line["dx"] + line["offset"] = p1.y - line["slope"] * p1.x return line @@ -65,7 +65,7 @@ def determinant(mat, n): It recursively expands the minors. """ matTemp = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] - if (n > 1): + if n > 1: if n == 2: d = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1] else: @@ -77,12 +77,12 @@ def determinant(mat, n): for j in range(n): if j == j1: continue - matTemp[i-1][j2] = mat[i][j] + matTemp[i - 1][j2] = mat[i][j] j2 += 1 - d += ((-1.0)**(1.0 + j1 + 1.0) - * mat[0][j1] * determinant(matTemp, n-1)) + d += (-1.0) ** (1.0 + j1 + 1.0) * mat[0][j1] * determinant(matTemp, n - 1) return d else: return 0 + ## @} diff --git a/src/Mod/Draft/draftgeoutils/offsets.py b/src/Mod/Draft/draftgeoutils/offsets.py index e09ba1ddec..564d22e4e1 100644 --- a/src/Mod/Draft/draftgeoutils/offsets.py +++ b/src/Mod/Draft/draftgeoutils/offsets.py @@ -80,9 +80,7 @@ def pocket2d(shape, offset): if len(innerWire.Edges) == 1: e = innerWire.Edges[0] if isinstance(e.Curve, Part.Circle): - e = Part.makeCircle(e.Curve.Radius + offset, - e.Curve.Center, - e.Curve.Axis) + e = Part.makeCircle(e.Curve.Radius + offset, e.Curve.Center, e.Curve.Axis) i = Part.Wire(e) if i.Wires: # print("offsetting island ", innerWire, " : ", i.Wires) @@ -108,12 +106,14 @@ def pocket2d(shape, offset): else: a = w.BoundBox b = ow.BoundBox - if ((a.XMin <= b.XMin) - and (a.YMin <= b.YMin) - and (a.ZMin <= b.ZMin) - and (a.XMax >= b.XMax) - and (a.YMax >= b.YMax) - and (a.ZMax >= b.ZMax)): + if ( + (a.XMin <= b.XMin) + and (a.YMin <= b.YMin) + and (a.ZMin <= b.ZMin) + and (a.XMax >= b.XMax) + and (a.YMax >= b.YMax) + and (a.ZMax >= b.ZMax) + ): # print("this wire is bigger than " # "the outer wire") offsetWires[j] = None @@ -151,8 +151,7 @@ def offset(edge, vector, trim=False): Part.Shape The offset shape """ - if (not isinstance(edge, Part.Shape) - or not isinstance(vector, App.Vector)): + if not isinstance(edge, Part.Shape) or not isinstance(vector, App.Vector): return None if geomType(edge) == "Line": @@ -165,27 +164,34 @@ def offset(edge, vector, trim=False): curve = Part.Circle(edge.Curve) curve.Radius = App.Vector.add(rad, vector).Length if trim: - return Part.ArcOfCircle(curve, - edge.FirstParameter, - edge.LastParameter).toShape() + return Part.ArcOfCircle(curve, edge.FirstParameter, edge.LastParameter).toShape() elif geomType(edge) == "Ellipse": rad = edge.Vertexes[0].Point.sub(edge.Curve.Center) curve = edge.Curve.copy() if vector.getAngle(rad) < 1: - curve.MajorRadius = curve.MajorRadius+vector.Length - curve.MinorRadius = curve.MinorRadius+vector.Length + curve.MajorRadius = curve.MajorRadius + vector.Length + curve.MinorRadius = curve.MinorRadius + vector.Length else: - curve.MajorRadius = curve.MajorRadius-vector.Length - curve.MinorRadius = curve.MinorRadius-vector.Length + curve.MajorRadius = curve.MajorRadius - vector.Length + curve.MinorRadius = curve.MinorRadius - vector.Length return curve.toShape() else: return None -def offsetWire(wire, dvec, bind=False, occ=False, - widthList=None, offsetMode=None, alignList=[], - normal=None, basewireOffset=0, wireNedge=False): - # normal=None, basewireOffset=0): +def offsetWire( + wire, + dvec, + bind=False, + occ=False, + widthList=None, + offsetMode=None, + alignList=[], + normal=None, + basewireOffset=0, + wireNedge=False, +): + # normal=None, basewireOffset=0): """Offset the wire along the given vector. Parameters @@ -244,8 +250,7 @@ def offsetWire(wire, dvec, bind=False, occ=False, edges = [wire] closed = wire.isClosed() else: - print("Either Part.Wire or Part.Edges should be provided, " - "returning None") + print("Either Part.Wire or Part.Edges should be provided, " "returning None") return None # For sketch with a number of wires, getNormal() may result @@ -291,15 +296,15 @@ def offsetWire(wire, dvec, bind=False, occ=False, # Check the direction / offset of starting edge firstDir = None try: - if alignListC[0] == 'Left': + if alignListC[0] == "Left": firstDir = 1 - firstAlign = 'Left' - elif alignListC[0] == 'Right': + firstAlign = "Left" + elif alignListC[0] == "Right": firstDir = -1 - firstAlign = 'Right' - elif alignListC[0] == 'Center': + firstAlign = "Right" + elif alignListC[0] == "Center": firstDir = 1 - firstAlign = 'Center' + firstAlign = "Center" except IndexError: # Should no longer happen for ArchWall # as aligns are 'filled in' by ArchWall @@ -312,7 +317,7 @@ def offsetWire(wire, dvec, bind=False, occ=False, # ('legacy/backward-compatible' mode) if not firstDir: # need to test against Part.Circle, not Part.ArcOfCircle - if isinstance(e.Curve, (Part.Circle,Part.Ellipse)): + if isinstance(e.Curve, (Part.Circle, Part.Ellipse)): v0 = e.tangentAt(e.FirstParameter).cross(norm) else: v0 = vec(e).cross(norm) @@ -324,17 +329,17 @@ def offsetWire(wire, dvec, bind=False, occ=False, if v0.isEqual(v1, 0.0001): # "Left Offset" (Left Align or 'left offset' in Centre Align) firstDir = 1 - firstAlign = 'Left' - alignListC.append('Left') + firstAlign = "Left" + alignListC.append("Left") elif v0.isEqual(v1.negative(), 0.0001): # "Right Offset" (Right Align or 'right offset' in Centre Align) firstDir = -1 - firstAlign = 'Right' - alignListC.append('Right') + firstAlign = "Right" + alignListC.append("Right") else: print(" something wrong with firstDir ") - firstAlign = 'Left' - alignListC.append('Left') + firstAlign = "Left" + alignListC.append("Left") if not isinstance(basewireOffset, list): basewireOffset = [basewireOffset] @@ -357,9 +362,9 @@ def offsetWire(wire, dvec, bind=False, occ=False, # record current edge's Orientation, and set Delta if i != 0: # else: # TODO Should also calculate 1st edge direction above - if isinstance(curredge.Curve, (Part.Circle,Part.Ellipse)): - # Seems Circle/Ellipse (1 geometry) would be sorted in 1 list, - # so i=0; should not happen here in fact (i != 0). 2024.8.25. + if isinstance(curredge.Curve, (Part.Circle, Part.Ellipse)): + # Seems Circle/Ellipse (1 geometry) would be sorted in 1 list, + # so i=0; should not happen here in fact (i != 0). 2024.8.25. delta = curredge.tangentAt(curredge.FirstParameter).cross(norm) else: delta = vec(curredge).cross(norm) @@ -396,31 +401,31 @@ def offsetWire(wire, dvec, bind=False, occ=False, # Consider individual edge Align direction # - ArchWall should now always provide alignList if i == 0: - if alignListC[0] == 'Center': - delta = DraftVecUtils.scaleTo(delta, delta.Length/2) + if alignListC[0] == "Center": + delta = DraftVecUtils.scaleTo(delta, delta.Length / 2) # No need to do anything for 'Left' and 'Right' as original dvec # have set both the direction and amount of offset correct # elif alignListC[i] == 'Left': #elif alignListC[i] == 'Right': if i != 0: try: - if alignListC[i] == 'Left': + if alignListC[i] == "Left": curDir = 1 - curAlign = 'Left' - elif alignListC[i] == 'Right': + curAlign = "Left" + elif alignListC[i] == "Right": curDir = -1 - curAlign = 'Right' + curAlign = "Right" delta = delta.negative() - elif alignListC[i] == 'Center': + elif alignListC[i] == "Center": curDir = 1 - curAlign = 'Center' - delta = DraftVecUtils.scaleTo(delta, delta.Length/2) + curAlign = "Center" + delta = DraftVecUtils.scaleTo(delta, delta.Length / 2) except IndexError: curDir = firstDir curAlign = firstAlign - if firstAlign == 'Right': + if firstAlign == "Right": delta = delta.negative() - elif firstAlign == 'Center': - delta = DraftVecUtils.scaleTo(delta, delta.Length/2) + elif firstAlign == "Center": + delta = DraftVecUtils.scaleTo(delta, delta.Length / 2) # Consider whether generating the 'offset wire' or the 'base wire' if offsetMode is None: @@ -430,16 +435,16 @@ def offsetWire(wire, dvec, bind=False, occ=False, # This is a xor if (curOrientation == firstOrientation) != (curDir == firstDir): - if curAlign in ['Left', 'Right']: + if curAlign in ["Left", "Right"]: # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) if currOffset: delta = DraftVecUtils.scaleTo(delta, currOffset) - nedge = offset(curredge,delta,trim=True) + nedge = offset(curredge, delta, trim=True) else: nedge = curredge - elif curAlign == 'Center': + elif curAlign == "Center": delta = delta.negative() nedge = offset(curredge, delta, trim=True) else: @@ -449,32 +454,32 @@ def offsetWire(wire, dvec, bind=False, occ=False, # the basewire before creating the base profile of wall # (not applicable to 'Center' align) if currOffset: - if curAlign in ['Left', 'Right']: - delta = DraftVecUtils.scaleTo(delta, - delta.Length + currOffset) + if curAlign in ["Left", "Right"]: + delta = DraftVecUtils.scaleTo(delta, delta.Length + currOffset) nedge = offset(curredge, delta, trim=True) # TODO arc always in counter-clockwise directinon # ... ( not necessarily 'reversed') if curOrientation == "Reversed": - if not isinstance(curredge.Curve, (Part.Circle,Part.Ellipse)): + if not isinstance(curredge.Curve, (Part.Circle, Part.Ellipse)): # assume straight line, reverse it nedge = Part.Edge(nedge.Vertexes[1], nedge.Vertexes[0]) elif nedge.isClosed(): pass else: - midParameter = nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter)/2 + midParameter = ( + nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter) / 2 + ) midOfArc = nedge.valueAt(midParameter) - nedge = Part.ArcOfCircle(nedge.Vertexes[1].Point, - midOfArc, - nedge.Vertexes[0].Point).toShape() + nedge = Part.ArcOfCircle( + nedge.Vertexes[1].Point, midOfArc, nedge.Vertexes[0].Point + ).toShape() # TODO any better solution than to calculate midpoint # of arc to reverse? elif offsetMode in ["BasewireMode"]: - if (not (curOrientation == firstOrientation) - != (curDir == firstDir)): - if curAlign in ['Left', 'Right']: + if not (curOrientation == firstOrientation) != (curDir == firstDir): + if curAlign in ["Left", "Right"]: # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) @@ -483,32 +488,33 @@ def offsetWire(wire, dvec, bind=False, occ=False, nedge = offset(curredge, delta, trim=True) else: nedge = curredge - elif curAlign == 'Center': + elif curAlign == "Center": delta = delta.negative() nedge = offset(curredge, delta, trim=True) else: - if curAlign in ['Left', 'Right']: + if curAlign in ["Left", "Right"]: # ArchWall has an Offset properties for user to offset # the basewire before creating the base profile of wall # (not applicable to 'Center' align) if currOffset: - delta = DraftVecUtils.scaleTo(delta, - delta.Length + currOffset) + delta = DraftVecUtils.scaleTo(delta, delta.Length + currOffset) nedge = offset(curredge, delta, trim=True) - elif curAlign == 'Center': + elif curAlign == "Center": nedge = offset(curredge, delta, trim=True) if curOrientation == "Reversed": - if not isinstance(curredge.Curve, (Part.Circle,Part.Ellipse)): + if not isinstance(curredge.Curve, (Part.Circle, Part.Ellipse)): # assume straight line, reverse it nedge = Part.Edge(nedge.Vertexes[1], nedge.Vertexes[0]) elif nedge.isClosed(): pass else: - midParameter = nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter)/2 + midParameter = ( + nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter) / 2 + ) midOfArc = nedge.valueAt(midParameter) - nedge = Part.ArcOfCircle(nedge.Vertexes[1].Point, - midOfArc, - nedge.Vertexes[0].Point).toShape() + nedge = Part.ArcOfCircle( + nedge.Vertexes[1].Point, midOfArc, nedge.Vertexes[0].Point + ).toShape() # TODO any better solution than to calculate midpoint # of arc to reverse? else: @@ -523,7 +529,7 @@ def offsetWire(wire, dvec, bind=False, occ=False, if len(edges) > 1: # TODO May phase out wire if bind() can do without it later and do with # only connectEdges so no need bind() to find 'touching edges' there - wire,connectEdgesF,connectEdges = connect(nedges,closed,wireNedge=True) + wire, connectEdgesF, connectEdges = connect(nedges, closed, wireNedge=True) else: # TODO May phase out wire if bind() can do without it later and do with # only connectEdges so no need bind() to find 'touching edges' there @@ -531,19 +537,18 @@ def offsetWire(wire, dvec, bind=False, occ=False, connectEdgesF = connectEdges = nedges # nedges[0] if bind and not closed: - e1 = Part.LineSegment(edges[0].Vertexes[0].Point, - wire[0].Vertexes[0].Point).toShape() - e2 = Part.LineSegment(edges[-1].Vertexes[-1].Point, - wire[-1].Vertexes[-1].Point).toShape() - #nedges[-1].Vertexes[-1].Point).toShape() + e1 = Part.LineSegment(edges[0].Vertexes[0].Point, wire[0].Vertexes[0].Point).toShape() + e2 = Part.LineSegment(edges[-1].Vertexes[-1].Point, wire[-1].Vertexes[-1].Point).toShape() + # nedges[-1].Vertexes[-1].Point).toShape() alledges = edges.extend(nedges) # TODO nedges is a wire or are edges? alledges = alledges.extend([e1, e2]) w = Part.Wire(alledges) return w else: if wireNedge: - return (wire,connectEdgesF,connectEdges,nedges) + return (wire, connectEdgesF, connectEdges, nedges) else: return wire + ## @} diff --git a/src/Mod/Draft/draftgeoutils/sort_edges.py b/src/Mod/Draft/draftgeoutils/sort_edges.py index 9f9e0c7eab..3862f86e04 100644 --- a/src/Mod/Draft/draftgeoutils/sort_edges.py +++ b/src/Mod/Draft/draftgeoutils/sort_edges.py @@ -142,10 +142,10 @@ def sortEdgesOld(lEdges, aVertex=None): linstances = [] # lists the instances of aVertex for i in range(len(inEdges)): for j in range(2): - if aVertex.Point == inEdges[i].Vertexes[j-1].Point: + if aVertex.Point == inEdges[i].Vertexes[j - 1].Point: instance = inEdges[i] count += 1 - linstances += [i, j-1, instance] + linstances += [i, j - 1, instance] return [count] + linstances if len(lEdges) < 2: @@ -158,18 +158,22 @@ def sortEdgesOld(lEdges, aVertex=None): return lEdges else: if geomType(result[3]) == "Line": - return [Part.LineSegment(aVertex.Point, - result[3].Vertexes[0].Point).toShape()] + return [ + Part.LineSegment(aVertex.Point, result[3].Vertexes[0].Point).toShape() + ] elif geomType(result[3]) == "Circle": mp = findMidpoint(result[3]) - return [Part.Arc(aVertex.Point, - mp, - result[3].Vertexes[0].Point).toShape()] - elif (geomType(result[3]) == "BSplineCurve" - or geomType(result[3]) == "BezierCurve"): + return [Part.Arc(aVertex.Point, mp, result[3].Vertexes[0].Point).toShape()] + elif ( + geomType(result[3]) == "BSplineCurve" + or geomType(result[3]) == "BezierCurve" + ): if isLine(result[3].Curve): - return [Part.LineSegment(aVertex.Point, - result[3].Vertexes[0].Point).toShape()] + return [ + Part.LineSegment( + aVertex.Point, result[3].Vertexes[0].Point + ).toShape() + ] else: return lEdges else: @@ -177,12 +181,11 @@ def sortEdgesOld(lEdges, aVertex=None): olEdges = [] # ol stands for ordered list if aVertex is None: - for i in range(len(lEdges)*2): - if len(lEdges[i/2].Vertexes) > 1: - result = lookfor(lEdges[i/2].Vertexes[i % 2], lEdges) + for i in range(len(lEdges) * 2): + if len(lEdges[i / 2].Vertexes) > 1: + result = lookfor(lEdges[i / 2].Vertexes[i % 2], lEdges) if result[0] == 1: # Have we found an end ? - olEdges = sortEdgesOld(lEdges, - result[3].Vertexes[result[2]]) + olEdges = sortEdgesOld(lEdges, result[3].Vertexes[result[2]]) return olEdges # if the wire is closed there is no end so choose 1st Vertex # print("closed wire, starting from ",lEdges[0].Vertexes[0].Point) @@ -192,8 +195,7 @@ def sortEdgesOld(lEdges, aVertex=None): result = lookfor(aVertex, lEdges) if result[0] != 0: del lEdges[result[1]] - _next = sortEdgesOld(lEdges, - result[3].Vertexes[-((-result[2])^1)]) + _next = sortEdgesOld(lEdges, result[3].Vertexes[-((-result[2]) ^ 1)]) # print("result ", result[3].Vertexes[0].Point, " ", # result[3].Vertexes[1].Point, " compared to ",aVertex.Point) if aVertex.Point == result[3].Vertexes[0].Point: @@ -202,20 +204,17 @@ def sortEdgesOld(lEdges, aVertex=None): else: # print("inverting", result[3].Curve) if geomType(result[3]) == "Line": - newedge = Part.LineSegment(aVertex.Point, - result[3].Vertexes[0].Point).toShape() + newedge = Part.LineSegment(aVertex.Point, result[3].Vertexes[0].Point).toShape() olEdges += [newedge] + _next elif geomType(result[3]) == "Circle": mp = findMidpoint(result[3]) - newedge = Part.Arc(aVertex.Point, - mp, - result[3].Vertexes[0].Point).toShape() + newedge = Part.Arc(aVertex.Point, mp, result[3].Vertexes[0].Point).toShape() olEdges += [newedge] + _next - elif (geomType(result[3]) == "BSplineCurve" - or geomType(result[3]) == "BezierCurve"): + elif geomType(result[3]) == "BSplineCurve" or geomType(result[3]) == "BezierCurve": if isLine(result[3].Curve): - newedge = Part.LineSegment(aVertex.Point, - result[3].Vertexes[0].Point).toShape() + newedge = Part.LineSegment( + aVertex.Point, result[3].Vertexes[0].Point + ).toShape() olEdges += [newedge] + _next else: olEdges += [result[3]] + _next @@ -225,4 +224,5 @@ def sortEdgesOld(lEdges, aVertex=None): else: return [] + ## @} diff --git a/src/Mod/Draft/draftgeoutils/wires.py b/src/Mod/Draft/draftgeoutils/wires.py index 751f29de52..cdda3a87e7 100644 --- a/src/Mod/Draft/draftgeoutils/wires.py +++ b/src/Mod/Draft/draftgeoutils/wires.py @@ -59,17 +59,13 @@ def findWiresOld2(edgeslist): return False if len(e2.Vertexes) < 2: return False - if DraftVecUtils.equals(e1.Vertexes[0].Point, - e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point): return True - if DraftVecUtils.equals(e1.Vertexes[0].Point, - e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point): return True - if DraftVecUtils.equals(e1.Vertexes[-1].Point, - e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point): return True - if DraftVecUtils.equals(e1.Vertexes[-1].Point, - e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point): return True return False @@ -119,12 +115,12 @@ def findWiresOld(edges): Find connected edges in the list. """ - raise DeprecationWarning("This function shouldn't be called anymore. " - "Use findWires() instead") + raise DeprecationWarning( + "This function shouldn't be called anymore. " "Use findWires() instead" + ) def verts(shape): - return [shape.Vertexes[0].Point, - shape.Vertexes[-1].Point] + return [shape.Vertexes[0].Point, shape.Vertexes[-1].Point] def group(shapes): shapesIn = shapes[:] @@ -138,8 +134,7 @@ def findWiresOld(edges): for v in verts(s): for i in range(len(shapesOut)): if clean and (v in verts(shapesOut[i])): - shapesOut[i] = Part.Wire(shapesOut[i].Edges - + s.Edges) + shapesOut[i] = Part.Wire(shapesOut[i].Edges + s.Edges) changed = True clean = False if clean: @@ -184,6 +179,7 @@ def superWire(edgeslist, closed=False): Forces a wire between edges that don't necessarily have coincident endpoints. If closed=True, the wire will always be closed. """ + def median(v1, v2): vd = v2.sub(v1) vd.scale(0.5, 0.5, 0.5) @@ -209,7 +205,7 @@ def superWire(edgeslist, closed=False): else: _next = None else: - _next = edges[i+1] + _next = edges[i + 1] print(i, prev, curr, _next) @@ -290,7 +286,7 @@ def rebaseWire(wire, vidx=0): return wire # This can be done in one step - return Part.Wire(wire.Edges[vidx-1:] + wire.Edges[:vidx-1]) + return Part.Wire(wire.Edges[vidx - 1 :] + wire.Edges[: vidx - 1]) def removeInterVertices(wire): @@ -348,8 +344,7 @@ def cleanProjection(shape, tessellate=True, seglength=0.05): newedges.append(e) elif typ in ["BSplineCurve", "BezierCurve"]: if isLine(e.Curve): - line = Part.LineSegment(e.Vertexes[0].Point, - e.Vertexes[-1].Point) + line = Part.LineSegment(e.Vertexes[0].Point, e.Vertexes[-1].Point) newedges.append(line) elif tessellate: newedges.append(Part.Wire(curvetowire(e, seglength))) @@ -387,6 +382,7 @@ def tessellateProjection(shape, seglen): return Part.makeCompound(newedges) + def get_placement_perpendicular_to_wire(wire): """Return the placement whose base is the wire's first vertex and it's z axis aligned to the wire's tangent.""" pl = App.Placement() @@ -399,7 +395,9 @@ def get_placement_perpendicular_to_wire(wire): zaxis = first_edge.tangentAt(first_edge.LastParameter) pl.Rotation = App.Rotation(App.Vector(1, 0, 0), App.Vector(0, 0, 1), zaxis, "ZYX") else: - App.Console.PrintError("debug: get_placement_perpendicular_to_wire called with a zero-length wire.\n") + App.Console.PrintError( + "debug: get_placement_perpendicular_to_wire called with a zero-length wire.\n" + ) return pl @@ -410,27 +408,33 @@ def get_extended_wire(wire, offset_start, offset_end): get_extended_wire(wire, 0.0, 100.0) -> returns a copy of the wire extended by 100 mm after it's last vertex """ if min(offset_start, offset_end, offset_start + offset_end) <= -wire.Length: - App.Console.PrintError("debug: get_extended_wire error, wire's length insufficient for trimming.\n") + App.Console.PrintError( + "debug: get_extended_wire error, wire's length insufficient for trimming.\n" + ) return wire - if offset_start < 0: # Trim the wire from the first vertex + if offset_start < 0: # Trim the wire from the first vertex offset_start = -offset_start out_edges = [] for edge in wire.OrderedEdges: - if offset_start >= edge.Length: # Remove entire edge + if offset_start >= edge.Length: # Remove entire edge offset_start -= edge.Length - elif round(offset_start, precision()) > 0: # Split edge, to remove the required length + elif round(offset_start, precision()) > 0: # Split edge, to remove the required length if edge.Orientation == "Forward": new_edge = edge.split(edge.getParameterByLength(offset_start)).OrderedEdges[1] else: - new_edge = edge.split(edge.getParameterByLength(edge.Length - offset_start)).OrderedEdges[0] - new_edge.Placement = edge.Placement # Strangely, edge.split discards the placement and orientation + new_edge = edge.split( + edge.getParameterByLength(edge.Length - offset_start) + ).OrderedEdges[0] + new_edge.Placement = ( + edge.Placement + ) # Strangely, edge.split discards the placement and orientation new_edge.Orientation = edge.Orientation out_edges.append(new_edge) offset_start = 0 - else: # Keep the remaining entire edges + else: # Keep the remaining entire edges out_edges.append(edge) wire = Part.Wire(out_edges) - elif offset_start > 0: # Extend the first edge along its normal + elif offset_start > 0: # Extend the first edge along its normal first_edge = wire.OrderedEdges[0] if first_edge.Orientation == "Forward": start, end = first_edge.FirstParameter, first_edge.LastParameter @@ -438,31 +442,39 @@ def get_extended_wire(wire, offset_start, offset_end): else: start, end = first_edge.LastParameter, first_edge.FirstParameter vec = -first_edge.tangentAt(start).multiply(offset_start) - if geomType(first_edge) == "Line": # Replace first edge with the extended new edge - new_edge = Part.LineSegment(first_edge.valueAt(start).sub(vec), first_edge.valueAt(end)).toShape() + if geomType(first_edge) == "Line": # Replace first edge with the extended new edge + new_edge = Part.LineSegment( + first_edge.valueAt(start).sub(vec), first_edge.valueAt(end) + ).toShape() wire = Part.Wire([new_edge] + wire.OrderedEdges[1:]) - else: # Add a straight edge before the first vertex - new_edge = Part.LineSegment(first_edge.valueAt(start).sub(vec), first_edge.valueAt(start)).toShape() + else: # Add a straight edge before the first vertex + new_edge = Part.LineSegment( + first_edge.valueAt(start).sub(vec), first_edge.valueAt(start) + ).toShape() wire = Part.Wire([new_edge] + wire.OrderedEdges) - if offset_end < 0: # Trim the wire from the last vertex + if offset_end < 0: # Trim the wire from the last vertex offset_end = -offset_end out_edges = [] for edge in reversed(wire.OrderedEdges): - if offset_end >= edge.Length: # Remove entire edge + if offset_end >= edge.Length: # Remove entire edge offset_end -= edge.Length - elif round(offset_end, precision()) > 0: # Split edge, to remove the required length + elif round(offset_end, precision()) > 0: # Split edge, to remove the required length if edge.Orientation == "Forward": - new_edge = edge.split(edge.getParameterByLength(edge.Length - offset_end)).OrderedEdges[0] + new_edge = edge.split( + edge.getParameterByLength(edge.Length - offset_end) + ).OrderedEdges[0] else: new_edge = edge.split(edge.getParameterByLength(offset_end)).OrderedEdges[1] - new_edge.Placement = edge.Placement # Strangely, edge.split discards the placement and orientation + new_edge.Placement = ( + edge.Placement + ) # Strangely, edge.split discards the placement and orientation new_edge.Orientation = edge.Orientation out_edges.insert(0, new_edge) offset_end = 0 - else: # Keep the remaining entire edges + else: # Keep the remaining entire edges out_edges.insert(0, edge) wire = Part.Wire(out_edges) - elif offset_end > 0: # Extend the last edge along its normal + elif offset_end > 0: # Extend the last edge along its normal last_edge = wire.OrderedEdges[-1] if last_edge.Orientation == "Forward": start, end = last_edge.FirstParameter, last_edge.LastParameter @@ -470,12 +482,17 @@ def get_extended_wire(wire, offset_start, offset_end): else: start, end = last_edge.LastParameter, last_edge.FirstParameter vec = -last_edge.tangentAt(end).multiply(offset_end) - if geomType(last_edge) == "Line": # Replace last edge with the extended new edge - new_edge = Part.LineSegment(last_edge.valueAt(start), last_edge.valueAt(end).add(vec)).toShape() + if geomType(last_edge) == "Line": # Replace last edge with the extended new edge + new_edge = Part.LineSegment( + last_edge.valueAt(start), last_edge.valueAt(end).add(vec) + ).toShape() wire = Part.Wire(wire.OrderedEdges[:-1] + [new_edge]) - else: # Add a straight edge after the last vertex - new_edge = Part.LineSegment(last_edge.valueAt(end), last_edge.valueAt(end).add(vec)).toShape() + else: # Add a straight edge after the last vertex + new_edge = Part.LineSegment( + last_edge.valueAt(end), last_edge.valueAt(end).add(vec) + ).toShape() wire = Part.Wire(wire.OrderedEdges + [new_edge]) return wire + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py b/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py index c7d801da1c..ec64a56496 100644 --- a/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py +++ b/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py @@ -63,7 +63,9 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): """ def __init__(self): - super(AnnotationStyleEditor, self).__init__(name=translate("draft","Annotation Style Editor")) + super(AnnotationStyleEditor, self).__init__( + name=translate("draft", "Annotation Style Editor") + ) self.doc = None self.styles = {} self.renamed = {} @@ -72,11 +74,14 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': ":icons/Draft_Annotation_Style.svg", - 'MenuText': QT_TRANSLATE_NOOP("Draft_AnnotationStyleEditor", - "Annotation Styles"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_AnnotationStyleEditor", - "Opens an editor to manage or create annotation styles")} + return { + "Pixmap": ":icons/Draft_Annotation_Style.svg", + "MenuText": QT_TRANSLATE_NOOP("Draft_AnnotationStyleEditor", "Annotation Styles"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_AnnotationStyleEditor", + "Opens an editor to manage or create annotation styles", + ), + } def Activated(self): """Execute when the command is called. @@ -99,9 +104,9 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): # center the dialog over FreeCAD window mw = Gui.getMainWindow() - self.form.move(mw.frameGeometry().topLeft() - + mw.rect().center() - - self.form.rect().center()) + self.form.move( + mw.frameGeometry().topLeft() + mw.rect().center() - self.form.rect().center() + ) # set icons self.form.setWindowIcon(QtGui.QIcon(":/icons/Draft_Annotation_Style.svg")) @@ -156,8 +161,7 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): strvalue = json.dumps(value) except Exception: print("debug: unable to serialize this:", value) - if ("Draft_Style_" + key in meta - and meta["Draft_Style_" + key] != strvalue): + if "Draft_Style_" + key in meta and meta["Draft_Style_" + key] != strvalue: changedstyles.append(key) meta["Draft_Style_" + key] = strvalue @@ -184,7 +188,10 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): if vobj.AnnotationStyle in self.renamed: # the style has been renamed # temporarily add the new style and switch to it - vobj.AnnotationStyle = [vobj.AnnotationStyle, self.renamed[vobj.AnnotationStyle]] + vobj.AnnotationStyle = [ + vobj.AnnotationStyle, + self.renamed[vobj.AnnotationStyle], + ] vobj.AnnotationStyle = self.renamed[vobj.AnnotationStyle] if vobj.AnnotationStyle in styles: if vobj.AnnotationStyle in changedstyles: @@ -210,21 +217,25 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): self.form.pushButtonRename.setEnabled(False) elif index == 1: # Add new... entry - reply = QtWidgets.QInputDialog.getText(None, - translate("draft", "New Style"), - translate("draft", "Style name")) + reply = QtWidgets.QInputDialog.getText( + None, translate("draft", "New Style"), translate("draft", "Style name") + ) if reply[1]: # OK or Enter pressed name = reply[0].strip() if name == "": - QtWidgets.QMessageBox.information(None, - translate("draft", "Style name required"), - translate("draft", "No style name specified")) + QtWidgets.QMessageBox.information( + None, + translate("draft", "Style name required"), + translate("draft", "No style name specified"), + ) self.form.comboBoxStyles.setCurrentIndex(0) elif name in self.styles: - QtWidgets.QMessageBox.information(None, - translate("draft", "Style exists"), - translate("draft", "This style name already exists")) + QtWidgets.QMessageBox.information( + None, + translate("draft", "Style exists"), + translate("draft", "This style name already exists"), + ) self.form.comboBoxStyles.setCurrentIndex(0) else: # create new style from current editor values @@ -251,11 +262,13 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): style = self.form.comboBoxStyles.itemText(index) if self.get_style_users(style): - reply = QtWidgets.QMessageBox.question(None, - translate("draft", "Style in use"), - translate("draft", "This style is used by some objects in this document. Proceed?"), - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No) + reply = QtWidgets.QMessageBox.question( + None, + translate("draft", "Style in use"), + translate("draft", "This style is used by some objects in this document. Proceed?"), + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, + QtWidgets.QMessageBox.No, + ) if reply == QtWidgets.QMessageBox.No: return @@ -277,18 +290,22 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): index = self.form.comboBoxStyles.currentIndex() style = self.form.comboBoxStyles.itemText(index) - reply = QtWidgets.QInputDialog.getText(None, - translate("draft", "Rename Style"), - translate("draft", "New name"), - QtWidgets.QLineEdit.Normal, - style) + reply = QtWidgets.QInputDialog.getText( + None, + translate("draft", "Rename Style"), + translate("draft", "New name"), + QtWidgets.QLineEdit.Normal, + style, + ) if reply[1]: # OK or Enter pressed newname = reply[0] if newname in self.styles: - reply = QtWidgets.QMessageBox.information(None, - translate("draft", "Style exists"), - translate("draft", "This style name already exists")) + reply = QtWidgets.QMessageBox.information( + None, + translate("draft", "Style exists"), + translate("draft", "This style name already exists"), + ) else: self.form.comboBoxStyles.setItemText(index, newname) value = self.styles[style] @@ -301,9 +318,10 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): """Import styles from a json file.""" filename = QtWidgets.QFileDialog.getOpenFileName( QtWidgets.QApplication.activeWindow(), - translate("draft","Open Styles File"), + translate("draft", "Open Styles File"), None, - translate("draft","JSON files (*.json *.JSON)")) + translate("draft", "JSON files (*.json *.JSON)"), + ) if filename and filename[0]: nstyles = {} with open(filename[0]) as f: @@ -314,20 +332,21 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): for style in self.styles.keys(): if self.form.comboBoxStyles.findText(style) == -1: self.form.comboBoxStyles.addItem(style) - self.fill_editor(self.current_style) # The current style may have changed. + self.fill_editor(self.current_style) # The current style may have changed. print("Styles updated from " + filename[0]) def on_export(self): """Export styles to a json file.""" filename = QtWidgets.QFileDialog.getSaveFileName( QtWidgets.QApplication.activeWindow(), - translate("draft","Save Styles File"), + translate("draft", "Save Styles File"), None, - translate("draft","JSON file (*.json)")) + translate("draft", "JSON file (*.json)"), + ) if filename and filename[0]: self.update_style() - with open(filename[0],"w") as f: - json.dump(self.styles,f,indent=4) + with open(filename[0], "w") as f: + json.dump(self.styles, f, indent=4) print("Styles saved to " + filename[0]) def fill_editor(self, style=None): @@ -414,6 +433,6 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): return users -Gui.addCommand('Draft_AnnotationStyleEditor', AnnotationStyleEditor()) +Gui.addCommand("Draft_AnnotationStyleEditor", AnnotationStyleEditor()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_arcs.py b/src/Mod/Draft/draftguitools/gui_arcs.py index 3eae3114e6..26a3aa0e15 100644 --- a/src/Mod/Draft/draftguitools/gui_arcs.py +++ b/src/Mod/Draft/draftguitools/gui_arcs.py @@ -58,10 +58,14 @@ class Arc(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Arc", - "Accel": "A, R", - "MenuText": QT_TRANSLATE_NOOP("Draft_Arc", "Arc"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Arc", "Creates a circular arc from a center point and a radius")} + return { + "Pixmap": "Draft_Arc", + "Accel": "A, R", + "MenuText": QT_TRANSLATE_NOOP("Draft_Arc", "Arc"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Arc", "Creates a circular arc from a center point and a radius" + ), + } def Activated(self): """Execute when the command is called.""" @@ -149,8 +153,7 @@ class Arc(gui_base_original.Creator): self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: - viewdelta = DraftVecUtils.project(self.point.sub(self.center), - self.wp.axis) + viewdelta = DraftVecUtils.project(self.point.sub(self.center), self.wp.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center @@ -164,16 +167,16 @@ class Arc(gui_base_original.Creator): self.ui.switchUi(False) elif self.step == 1: # choose radius if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], - self.tangents[1], - self.point) + cir = DraftGeomUtils.circleFrom2tan1pt( + self.tangents[0], self.tangents[1], self.point + ) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], - self.tanpoints[0], - self.point) + cir = DraftGeomUtils.circleFrom1tan2pt( + self.tangents[0], self.tanpoints[0], self.point + ) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) @@ -181,19 +184,21 @@ class Arc(gui_base_original.Creator): if not self.altdown: self.altdown = True if info: - ob = self.doc.getObject(info['Object']) - num = int(info['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(info["Object"]) + num = int(info["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], - self.tangents[1], - ed) + cir = DraftGeomUtils.circleFrom3tan( + self.tangents[0], self.tangents[1], ed + ) cl = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: - self.rad = self.center.add(DraftGeomUtils.findDistance(self.center, ed).sub(self.center)).Length + self.rad = self.center.add( + DraftGeomUtils.findDistance(self.center, ed).sub(self.center) + ).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: @@ -205,23 +210,31 @@ class Arc(gui_base_original.Creator): self.linetrack.p1(self.center) self.linetrack.p2(self.point) self.linetrack.on() - elif (self.step == 2): # choose first angle + elif self.step == 2: # choose first angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: - angle = DraftVecUtils.angle(self.wp.u, self.point.sub(self.center), self.wp.axis) + angle = DraftVecUtils.angle( + self.wp.u, self.point.sub(self.center), self.wp.axis + ) else: angle = 0 - self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) + self.linetrack.p2( + DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center) + ) self.ui.setRadiusValue(math.degrees(angle), unit="Angle") self.firstangle = angle else: # choose second angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: - angle = DraftVecUtils.angle(self.wp.u, self.point.sub(self.center), self.wp.axis) + angle = DraftVecUtils.angle( + self.wp.u, self.point.sub(self.center), self.wp.axis + ) else: angle = 0 - self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) + self.linetrack.p2( + DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center) + ) self.updateAngle(angle) self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle") self.arctrack.setApertureAngle(self.angle) @@ -234,14 +247,14 @@ class Arc(gui_base_original.Creator): if self.step == 0: # choose center if not self.support: gui_tool_utils.getSupport(arg) - (self.point, - ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) + (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): - snapped = self.view.getObjectInfo((arg["Position"][0], - arg["Position"][1])) + snapped = self.view.getObjectInfo( + (arg["Position"][0], arg["Position"][1]) + ) if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(snapped["Object"]) + num = int(snapped["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: @@ -259,8 +272,9 @@ class Arc(gui_base_original.Creator): self.node = [self.point] self.arctrack.setCenter(self.center) self.linetrack.p1(self.center) - self.linetrack.p2(self.view.getPoint(arg["Position"][0], - arg["Position"][1])) + self.linetrack.p2( + self.view.getPoint(arg["Position"][0], arg["Position"][1]) + ) self.arctrack.on() self.ui.radiusUi() self.step = 1 @@ -283,9 +297,9 @@ class Arc(gui_base_original.Creator): elif self.step == 2: # choose first angle self.ui.labelRadius.setText(translate("draft", "Aperture angle")) self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) - ang_offset = DraftVecUtils.angle(self.wp.u, - self.arctrack.getDeviation(), - self.wp.axis) + ang_offset = DraftVecUtils.angle( + self.wp.u, self.arctrack.getDeviation(), self.wp.axis + ) self.arctrack.setStartAngle(self.firstangle - ang_offset) self.step = 3 _toolmsg(translate("draft", "Pick aperture")) @@ -305,37 +319,39 @@ class Arc(gui_base_original.Creator): if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object _base = DraftVecUtils.toString(self.center) - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Circle", "Circle")' - _cmd_list = ['circle = ' + _cmd, - 'circle.Radius = ' + str(self.rad), - 'pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + _base, - 'circle.Placement = pl', - 'Draft.autogroup(circle)', - 'Draft.select(circle)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Circle (Part)"), - _cmd_list) + _cmd_list = [ + "circle = " + _cmd, + "circle.Radius = " + str(self.rad), + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + _base, + "circle.Placement = pl", + "Draft.autogroup(circle)", + "Draft.select(circle)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Circle (Part)"), _cmd_list) else: # Insert a Draft circle _base = DraftVecUtils.toString(self.center) - _cmd = 'Draft.make_circle' - _cmd += '(' - _cmd += 'radius=' + str(self.rad) + ', ' - _cmd += 'placement=pl, ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl=FreeCAD.Placement()', - 'pl.Rotation.Q=' + rot, - 'pl.Base=' + _base, - 'circle = ' + _cmd, - 'Draft.autogroup(circle)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Circle"), - _cmd_list) + _cmd = "Draft.make_circle" + _cmd += "(" + _cmd += "radius=" + str(self.rad) + ", " + _cmd += "placement=pl, " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl=FreeCAD.Placement()", + "pl.Rotation.Q=" + rot, + "pl.Base=" + _base, + "circle = " + _cmd, + "Draft.autogroup(circle)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Circle"), _cmd_list) except Exception: _err("Draft: error delaying commit") else: @@ -352,41 +368,43 @@ class Arc(gui_base_original.Creator): if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object _base = DraftVecUtils.toString(self.center) - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Circle", "Circle")' - _cmd_list = ['circle = ' + _cmd, - 'circle.Radius = ' + str(self.rad), - 'circle.Angle1 = ' + str(sta), - 'circle.Angle2 = ' + str(end), - 'pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + _base, - 'circle.Placement = pl', - 'Draft.autogroup(circle)', - 'Draft.select(circle)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Arc (Part)"), - _cmd_list) + _cmd_list = [ + "circle = " + _cmd, + "circle.Radius = " + str(self.rad), + "circle.Angle1 = " + str(sta), + "circle.Angle2 = " + str(end), + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + _base, + "circle.Placement = pl", + "Draft.autogroup(circle)", + "Draft.select(circle)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Arc (Part)"), _cmd_list) else: # Insert a Draft circle _base = DraftVecUtils.toString(self.center) - _cmd = 'Draft.make_circle' - _cmd += '(' - _cmd += 'radius=' + str(self.rad) + ', ' - _cmd += 'placement=pl, ' - _cmd += 'face=' + fil + ', ' - _cmd += 'startangle=' + str(sta) + ', ' - _cmd += 'endangle=' + str(end) + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + _base, - 'circle = ' + _cmd, - 'Draft.autogroup(circle)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Arc"), - _cmd_list) + _cmd = "Draft.make_circle" + _cmd += "(" + _cmd += "radius=" + str(self.rad) + ", " + _cmd += "placement=pl, " + _cmd += "face=" + fil + ", " + _cmd += "startangle=" + str(sta) + ", " + _cmd += "endangle=" + str(end) + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + _base, + "circle = " + _cmd, + "Draft.autogroup(circle)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Arc"), _cmd_list) except Exception: _err("Draft: error delaying commit") @@ -420,18 +438,14 @@ class Arc(gui_base_original.Creator): if self.step == 1: self.rad = rad if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], - self.tangents[1], - rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: _c = DraftGeomUtils.findClosestCircle(self.center, cir) self.center = _c.Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0], - self.tanpoints[0], - rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0], self.tanpoints[0], rad) if self.center: _c = DraftGeomUtils.findClosestCircle(self.center, cir) self.center = _c.Center @@ -453,9 +467,7 @@ class Arc(gui_base_original.Creator): self.ui.labelRadius.setText(translate("draft", "Aperture angle")) self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) self.firstangle = math.radians(rad) - ang_offset = DraftVecUtils.angle(self.wp.u, - self.arctrack.getDeviation(), - self.wp.axis) + ang_offset = DraftVecUtils.angle(self.wp.u, self.arctrack.getDeviation(), self.wp.axis) self.arctrack.setStartAngle(self.firstangle - ang_offset) self.step = 3 self.ui.radiusValue.setText("") @@ -470,28 +482,24 @@ class Arc(gui_base_original.Creator): def get_hints(self): if self.step == 0: - hints = [ - Gui.InputHint(translate("draft", "%1 pick center"), Gui.UserInput.MouseLeft) - ] + hints = [Gui.InputHint(translate("draft", "%1 pick center"), Gui.UserInput.MouseLeft)] elif self.step == 1: - hints = [ - Gui.InputHint(translate("draft", "%1 pick radius"), Gui.UserInput.MouseLeft) - ] + hints = [Gui.InputHint(translate("draft", "%1 pick radius"), Gui.UserInput.MouseLeft)] elif self.step == 2: hints = [ Gui.InputHint(translate("draft", "%1 pick start angle"), Gui.UserInput.MouseLeft) ] else: - hints = [ - Gui.InputHint(translate("draft", "%1 pick aperture"), Gui.UserInput.MouseLeft) - ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + hints = [Gui.InputHint(translate("draft", "%1 pick aperture"), Gui.UserInput.MouseLeft)] + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Arc', Arc()) +Gui.addCommand("Draft_Arc", Arc()) class Arc_3Points(gui_base.GuiCommandBase): @@ -502,10 +510,14 @@ class Arc_3Points(gui_base.GuiCommandBase): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Arc_3Points", - "Accel": "A, T", - "MenuText": QT_TRANSLATE_NOOP("Draft_Arc_3Points", "Arc From 3 Points"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Arc_3Points", "Creates a circular arc from 3 points")} + return { + "Pixmap": "Draft_Arc_3Points", + "Accel": "A, T", + "MenuText": QT_TRANSLATE_NOOP("Draft_Arc_3Points", "Arc From 3 Points"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Arc_3Points", "Creates a circular arc from 3 points" + ), + } def Activated(self): """Execute when the command is called.""" @@ -521,13 +533,14 @@ class Arc_3Points(gui_base.GuiCommandBase): # with the indicated callbacks: one for when the user clicks # on the 3D view, and another for when the user moves the pointer. import WorkingPlane + WorkingPlane.get_working_plane() - Gui.Snapper.getPoint(callback=self.getPoint, - movecallback=self.drawArc) + Gui.Snapper.getPoint(callback=self.getPoint, movecallback=self.drawArc) Gui.Snapper.ui.sourceCmd = self - Gui.Snapper.ui.setTitle(title=translate("draft", "Arc From 3 Points"), - icon="Draft_Arc_3Points") + Gui.Snapper.ui.setTitle( + title=translate("draft", "Arc From 3 Points"), icon="Draft_Arc_3Points" + ) Gui.Snapper.ui.continueCmd.show() self.update_hints() @@ -567,12 +580,13 @@ class Arc_3Points(gui_base.GuiCommandBase): # the arc tracker to show the preview of the final curve. if len(self.points) == 2: self.tracker.on() - Gui.Snapper.getPoint(last=self.points[-1], - callback=self.getPoint, - movecallback=self.drawArc) + Gui.Snapper.getPoint( + last=self.points[-1], callback=self.getPoint, movecallback=self.drawArc + ) Gui.Snapper.ui.sourceCmd = self - Gui.Snapper.ui.setTitle(title=translate("draft", "Arc From 3 Points"), - icon="Draft_Arc_3Points") + Gui.Snapper.ui.setTitle( + title=translate("draft", "Arc From 3 Points"), icon="Draft_Arc_3Points" + ) Gui.Snapper.ui.continueCmd.show() self.update_hints() @@ -590,9 +604,11 @@ class Arc_3Points(gui_base.GuiCommandBase): _cmd += ", placement=pl" _cmd += ", primitive=" + str(params.get_param("UsePartPrimitives")) _cmd += ")" - _cmd_list = ["pl = WorkingPlane.get_working_plane().get_placement()", - "circle = " + _cmd, - "Draft.autogroup(circle)"] + _cmd_list = [ + "pl = WorkingPlane.get_working_plane().get_placement()", + "circle = " + _cmd, + "Draft.autogroup(circle)", + ] if params.get_param("UsePartPrimitives"): _cmd_list.append("Draft.select(circle)") _cmd_list.append("FreeCAD.ActiveDocument.recompute()") @@ -615,9 +631,7 @@ class Arc_3Points(gui_base.GuiCommandBase): """ if len(self.points) == 2: if point.sub(self.points[1]).Length > 0.001: - self.tracker.setBy3Points(self.points[0], - self.points[1], - point) + self.tracker.setBy3Points(self.points[0], self.points[1], point) def finish(self, cont=False): """Terminate the operation. @@ -646,14 +660,16 @@ class Arc_3Points(gui_base.GuiCommandBase): hints = [ Gui.InputHint(translate("draft", "%1 pick third point"), Gui.UserInput.MouseLeft) ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) Draft_Arc_3Points = Arc_3Points -Gui.addCommand('Draft_Arc_3Points', Arc_3Points()) +Gui.addCommand("Draft_Arc_3Points", Arc_3Points()) class ArcGroup: @@ -661,18 +677,22 @@ class ArcGroup: def GetResources(self): """Set icon, menu and tooltip.""" - return {"MenuText": QT_TRANSLATE_NOOP("Draft_ArcTools", "Arc Tools"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ArcTools", "Tools to create various types of circular arcs")} + return { + "MenuText": QT_TRANSLATE_NOOP("Draft_ArcTools", "Arc Tools"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ArcTools", "Tools to create various types of circular arcs" + ), + } def GetCommands(self): """Return a tuple of commands in the group.""" - return ('Draft_Arc', 'Draft_Arc_3Points') + return ("Draft_Arc", "Draft_Arc_3Points") def IsActive(self): """Return True when this command should be available.""" return bool(gui_utils.get_3d_view()) -Gui.addCommand('Draft_ArcTools', ArcGroup()) +Gui.addCommand("Draft_ArcTools", ArcGroup()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_arrays.py b/src/Mod/Draft/draftguitools/gui_arrays.py index c98e5c399e..ced33555b1 100644 --- a/src/Mod/Draft/draftguitools/gui_arrays.py +++ b/src/Mod/Draft/draftguitools/gui_arrays.py @@ -53,24 +53,35 @@ class ArrayGroup: def GetCommands(self): """Tuple of array commands.""" - return ("Draft_OrthoArray", - "Draft_PolarArray", "Draft_CircularArray", - "Draft_PathArray", "Draft_PathLinkArray", - "Draft_PointArray", "Draft_PointLinkArray", - "Draft_PathTwistedArray", "Draft_PathTwistedLinkArray") + return ( + "Draft_OrthoArray", + "Draft_PolarArray", + "Draft_CircularArray", + "Draft_PathArray", + "Draft_PathLinkArray", + "Draft_PointArray", + "Draft_PointLinkArray", + "Draft_PathTwistedArray", + "Draft_PathTwistedLinkArray", + ) def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Array", - "MenuText": QT_TRANSLATE_NOOP("Draft_ArrayTools", "Array Tools"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ArrayTools", "Tools to create various types of arrays, including rectangular, polar, circular, path, and point arrays")} + return { + "Pixmap": "Draft_Array", + "MenuText": QT_TRANSLATE_NOOP("Draft_ArrayTools", "Array Tools"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ArrayTools", + "Tools to create various types of arrays, including rectangular, polar, circular, path, and point arrays", + ), + } def IsActive(self): """Return True when this command should be available.""" return bool(gui_utils.get_3d_view()) -Gui.addCommand('Draft_ArrayTools', ArrayGroup()) +Gui.addCommand("Draft_ArrayTools", ArrayGroup()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_base.py b/src/Mod/Draft/draftguitools/gui_base.py index abd9860093..f842fdfa90 100644 --- a/src/Mod/Draft/draftguitools/gui_base.py +++ b/src/Mod/Draft/draftguitools/gui_base.py @@ -90,7 +90,7 @@ class GuiCommandSimplest: Also update the `doc` attribute. """ self.doc = App.activeDocument() - _toolmsg("{}".format(16*"-")) + _toolmsg("{}".format(16 * "-")) _toolmsg("GuiCommand: {}".format(self.featureName)) @@ -170,7 +170,7 @@ class GuiCommandBase: if params.get_param("showPlaneTracker"): self.planetrack = trackers.PlaneTracker() - _toolmsg("{}".format(16*"-")) + _toolmsg("{}".format(16 * "-")) _toolmsg("GuiCommand: {}".format(self.featureName)) def update_hints(self): @@ -218,4 +218,5 @@ class GuiCommandBase: """ self.commit_list.append((name, func)) + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_base_original.py b/src/Mod/Draft/draftguitools/gui_base_original.py index 3d1e6a448e..617410989d 100644 --- a/src/Mod/Draft/draftguitools/gui_base_original.py +++ b/src/Mod/Draft/draftguitools/gui_base_original.py @@ -132,7 +132,7 @@ class DraftTool: if hasattr(Gui, "Snapper"): Gui.Snapper.setTrackers() - _toolmsg("{}".format(16*"-")) + _toolmsg("{}".format(16 * "-")) _toolmsg("GuiCommand: {}".format(self.featureName)) # update hints after the tool is fully initialized @@ -231,18 +231,18 @@ class DraftTool: # Support object if self.support and params.get_param("useSupport"): - sup = 'FreeCAD.ActiveDocument.getObject' + sup = "FreeCAD.ActiveDocument.getObject" sup += '("{}")'.format(self.support.Name) else: - sup = 'None' + sup = "None" # Contents of self.node - points = '[' + points = "[" for n in self.node: if len(points) > 1: - points += ', ' + points += ", " points += DraftVecUtils.toString(n) - points += ']' + points += "]" # Make face if self.ui: @@ -293,4 +293,6 @@ class Modifier(DraftTool): super().Activated(name, is_subtool) # call _save to sync with _restore called in finish method self.wp._save() + + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_beziers.py b/src/Mod/Draft/draftguitools/gui_beziers.py index bb44e1224b..f459708172 100644 --- a/src/Mod/Draft/draftguitools/gui_beziers.py +++ b/src/Mod/Draft/draftguitools/gui_beziers.py @@ -61,19 +61,24 @@ class BezCurve(gui_lines.Line): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_BezCurve", - "Accel": "B, Z", - "MenuText": QT_TRANSLATE_NOOP("Draft_BezCurve", "Bézier Curve"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_BezCurve", "Creates an n-degree Bézier curve. The more points, the higher the degree.")} + return { + "Pixmap": "Draft_BezCurve", + "Accel": "B, Z", + "MenuText": QT_TRANSLATE_NOOP("Draft_BezCurve", "Bézier Curve"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_BezCurve", + "Creates an n-degree Bézier curve. The more points, the higher the degree.", + ), + } def Activated(self): """Execute when the command is called. Activate the specific Bézier curve tracker. """ - super().Activated(name="BezCurve", - icon="Draft_BezCurve", - task_title=translate("draft", "Bézier Curve")) + super().Activated( + name="BezCurve", icon="Draft_BezCurve", task_title=translate("draft", "Bézier Curve") + ) if self.doc: self.bezcurvetrack = trackers.bezcurveTracker() @@ -131,7 +136,7 @@ class BezCurve(gui_lines.Line): # by placing ends close to each other # with tol = Draft tolerance # old code has been to insensitive - if (self.point-self.node[0]).Length < utils.tolerance(): + if (self.point - self.node[0]).Length < utils.tolerance(): self.undolast() self.finish(cont=None, closed=True) @@ -158,13 +163,16 @@ class BezCurve(gui_lines.Line): def updateShape(self, pts): """Create shape for display during creation process.""" import Part + edges = [] if len(pts) >= 2: # allow lower degree segment poles = pts[1:] else: poles = [] if self.degree: - segpoleslst = [poles[x:x+self.degree] for x in range(0, len(poles), (self.degree or 1))] + segpoleslst = [ + poles[x : x + self.degree] for x in range(0, len(poles), (self.degree or 1)) + ] else: segpoleslst = [pts] startpoint = pts[0] @@ -201,19 +209,20 @@ class BezCurve(gui_lines.Line): try: rot, sup, pts, fil = self.getStrings() Gui.addModule("Draft") - _cmd = 'Draft.make_bezcurve' - _cmd += '(' - _cmd += 'points, ' - _cmd += 'closed=' + str(closed) + ', ' - _cmd += 'support=' + sup + ', ' - _cmd += 'degree=' + str(self.degree) - _cmd += ')' - _cmd_list = ['points = ' + pts, - 'bez = ' + _cmd, - 'Draft.autogroup(bez)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Bézier Curve"), - _cmd_list) + _cmd = "Draft.make_bezcurve" + _cmd += "(" + _cmd += "points, " + _cmd += "closed=" + str(closed) + ", " + _cmd += "support=" + sup + ", " + _cmd += "degree=" + str(self.degree) + _cmd += ")" + _cmd_list = [ + "points = " + pts, + "bez = " + _cmd, + "Draft.autogroup(bez)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Bézier Curve"), _cmd_list) except Exception: _err("Draft: error delaying commit") @@ -228,7 +237,7 @@ class BezCurve(gui_lines.Line): self.Activated() -Gui.addCommand('Draft_BezCurve', BezCurve()) +Gui.addCommand("Draft_BezCurve", BezCurve()) class CubicBezCurve(gui_lines.Line): @@ -249,10 +258,15 @@ class CubicBezCurve(gui_lines.Line): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_CubicBezCurve", - # "Accel": "B, Z", - "MenuText": QT_TRANSLATE_NOOP("Draft_CubicBezCurve", "Cubic Bézier Curve"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_CubicBezCurve", "Creates a Bézier curve made of 2nd degree (quadratic) and 3rd degree (cubic) segments. Clicking and dragging allows to define segments.\nControl points and properties of each knot can be edited after creation.")} + return { + "Pixmap": "Draft_CubicBezCurve", + # "Accel": "B, Z", + "MenuText": QT_TRANSLATE_NOOP("Draft_CubicBezCurve", "Cubic Bézier Curve"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_CubicBezCurve", + "Creates a Bézier curve made of 2nd degree (quadratic) and 3rd degree (cubic) segments. Clicking and dragging allows to define segments.\nControl points and properties of each knot can be edited after creation.", + ), + } def Activated(self): """Execute when the command is called. @@ -262,9 +276,11 @@ class CubicBezCurve(gui_lines.Line): self.old_EnableSelection = params.get_param_view("EnableSelection") params.set_param_view("EnableSelection", False) - super().Activated(name="CubicBezCurve", - icon="Draft_CubicBezCurve", - task_title=translate("draft", "Cubic Bézier Curve")) + super().Activated( + name="CubicBezCurve", + icon="Draft_CubicBezCurve", + task_title=translate("draft", "Cubic Bézier Curve"), + ) if self.doc: self.bezcurvetrack = trackers.bezcurveTracker() @@ -291,14 +307,13 @@ class CubicBezCurve(gui_lines.Line): if (len(self.node) - 1) % self.degree == 0 and len(self.node) > 2: prevctrl = 2 * self.node[-1] - self.point # Existing points + this pointer position - self.bezcurvetrack.update(self.node[0:-2] - + [prevctrl] - + [self.node[-1]] - + [self.point], degree=self.degree) + self.bezcurvetrack.update( + self.node[0:-2] + [prevctrl] + [self.node[-1]] + [self.point], + degree=self.degree, + ) else: # Existing points + this pointer position - self.bezcurvetrack.update(self.node - + [self.point], degree=self.degree) + self.bezcurvetrack.update(self.node + [self.point], degree=self.degree) gui_tool_utils.redraw3DView() return if arg["Type"] != "SoMouseButtonEvent": @@ -394,6 +409,7 @@ class CubicBezCurve(gui_lines.Line): def updateShape(self, pts): """Create shape for display during creation process.""" import Part + # Not quite right. draws 1 big bez. sb segmented edges = [] @@ -403,7 +419,9 @@ class CubicBezCurve(gui_lines.Line): poles = [] if self.degree: - segpoleslst = [poles[x:x+self.degree] for x in range(0, len(poles), (self.degree or 1))] + segpoleslst = [ + poles[x : x + self.degree] for x in range(0, len(poles), (self.degree or 1)) + ] else: segpoleslst = [pts] @@ -450,19 +468,20 @@ class CubicBezCurve(gui_lines.Line): # to be committed through the `draftutils.todo.ToDo` class. rot, sup, pts, fil = self.getStrings() Gui.addModule("Draft") - _cmd = 'Draft.make_bezcurve' - _cmd += '(' - _cmd += 'points, ' - _cmd += 'closed=' + str(closed) + ', ' - _cmd += 'support=' + sup + ', ' - _cmd += 'degree=' + str(self.degree) - _cmd += ')' - _cmd_list = ['points = ' + pts, - 'bez = ' + _cmd, - 'Draft.autogroup(bez)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Bézier Curve"), - _cmd_list) + _cmd = "Draft.make_bezcurve" + _cmd += "(" + _cmd += "points, " + _cmd += "closed=" + str(closed) + ", " + _cmd += "support=" + sup + ", " + _cmd += "degree=" + str(self.degree) + _cmd += ")" + _cmd_list = [ + "points = " + pts, + "bez = " + _cmd, + "Draft.autogroup(bez)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Bézier Curve"), _cmd_list) except Exception: _err("Draft: error delaying commit") @@ -478,17 +497,21 @@ class CubicBezCurve(gui_lines.Line): def get_hints(self): if len(self.node) < 2: - return [Gui.InputHint( - translate("draft", "%1 click and drag to define first point and knot"), - Gui.UserInput.MouseLeft - )] - return [Gui.InputHint( - translate("draft", "%1 click and drag to define next point and knot"), - Gui.UserInput.MouseLeft - )] + return [ + Gui.InputHint( + translate("draft", "%1 click and drag to define first point and knot"), + Gui.UserInput.MouseLeft, + ) + ] + return [ + Gui.InputHint( + translate("draft", "%1 click and drag to define next point and knot"), + Gui.UserInput.MouseLeft, + ) + ] -Gui.addCommand('Draft_CubicBezCurve', CubicBezCurve()) +Gui.addCommand("Draft_CubicBezCurve", CubicBezCurve()) class BezierGroup: @@ -496,18 +519,22 @@ class BezierGroup: def GetResources(self): """Set icon, menu and tooltip.""" - return {"MenuText": QT_TRANSLATE_NOOP("Draft_BezierTools", "Bézier Tools"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_BezierTools", "Tools to create various types of Bézier curves")} + return { + "MenuText": QT_TRANSLATE_NOOP("Draft_BezierTools", "Bézier Tools"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_BezierTools", "Tools to create various types of Bézier curves" + ), + } def GetCommands(self): """Return a tuple of commands in the group.""" - return ('Draft_CubicBezCurve', 'Draft_BezCurve') + return ("Draft_CubicBezCurve", "Draft_BezCurve") def IsActive(self): """Return True when this command should be available.""" return bool(gui_utils.get_3d_view()) -Gui.addCommand('Draft_BezierTools', BezierGroup()) +Gui.addCommand("Draft_BezierTools", BezierGroup()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_circles.py b/src/Mod/Draft/draftguitools/gui_circles.py index 536e7583ab..3989d7a362 100644 --- a/src/Mod/Draft/draftguitools/gui_circles.py +++ b/src/Mod/Draft/draftguitools/gui_circles.py @@ -75,12 +75,14 @@ class Circle(gui_arcs.Arc): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Circle', - 'Accel': "C, I", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Circle", "Circle"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Circle", "Creates a circle (full circular arc)")} + return { + "Pixmap": "Draft_Circle", + "Accel": "C, I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Circle", "Circle"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Circle", "Creates a circle (full circular arc)"), + } -Gui.addCommand('Draft_Circle', Circle()) +Gui.addCommand("Draft_Circle", Circle()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_circulararray.py b/src/Mod/Draft/draftguitools/gui_circulararray.py index ae579c260c..d694e3872f 100644 --- a/src/Mod/Draft/draftguitools/gui_circulararray.py +++ b/src/Mod/Draft/draftguitools/gui_circulararray.py @@ -51,9 +51,14 @@ class CircularArray(gui_base.GuiCommandBase): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_CircularArray", - "MenuText": QT_TRANSLATE_NOOP("Draft_CircularArray", "Circular Array"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_CircularArray", "Creates copies of the selected object in a radial pattern with 1 or more circular layers")} + return { + "Pixmap": "Draft_CircularArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_CircularArray", "Circular Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_CircularArray", + "Creates copies of the selected object in a radial pattern with 1 or more circular layers", + ), + } def Activated(self): """Execute when the command is called. @@ -65,10 +70,8 @@ class CircularArray(gui_base.GuiCommandBase): self.location = coin.SoLocation2Event.getClassTypeId() self.mouse_event = coin.SoMouseButtonEvent.getClassTypeId() - self.callback_move = \ - self.view.addEventCallbackPivy(self.location, self.move) - self.callback_click = \ - self.view.addEventCallbackPivy(self.mouse_event, self.click) + self.callback_move = self.view.addEventCallbackPivy(self.location, self.move) + self.callback_click = self.view.addEventCallbackPivy(self.mouse_event, self.click) self.ui = task_circulararray.TaskPanelCircularArray() # The calling class (this one) is saved in the object @@ -99,8 +102,10 @@ class CircularArray(gui_base.GuiCommandBase): """ if event_cb: event = event_cb.getEvent() - if (event.getState() != coin.SoMouseButtonEvent.DOWN - or event.getButton() != coin.SoMouseButtonEvent.BUTTON1): + if ( + event.getState() != coin.SoMouseButtonEvent.DOWN + or event.getButton() != coin.SoMouseButtonEvent.BUTTON1 + ): return if self.ui and self.point: # The accept function of the interface @@ -128,6 +133,6 @@ class CircularArray(gui_base.GuiCommandBase): self.finish() -Gui.addCommand('Draft_CircularArray', CircularArray()) +Gui.addCommand("Draft_CircularArray", CircularArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_clone.py b/src/Mod/Draft/draftguitools/gui_clone.py index 7ca25edc0f..1fd9a5d072 100644 --- a/src/Mod/Draft/draftguitools/gui_clone.py +++ b/src/Mod/Draft/draftguitools/gui_clone.py @@ -66,10 +66,12 @@ class Clone(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Clone", - "Accel": "C, L", - "MenuText": QT_TRANSLATE_NOOP("Draft_Clone", "Clone"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Clone", "Creates a clone of the selected objects")} + return { + "Pixmap": "Draft_Clone", + "Accel": "C, L", + "MenuText": QT_TRANSLATE_NOOP("Draft_Clone", "Clone"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Clone", "Creates a clone of the selected objects"), + } def Activated(self): """Execute when the command is called.""" @@ -121,6 +123,6 @@ class Clone(gui_base_original.Modifier): Draft_Clone = Clone -Gui.addCommand('Draft_Clone', Clone()) +Gui.addCommand("Draft_Clone", Clone()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_dimension_ops.py b/src/Mod/Draft/draftguitools/gui_dimension_ops.py index d4ed46dadd..5b717fa853 100644 --- a/src/Mod/Draft/draftguitools/gui_dimension_ops.py +++ b/src/Mod/Draft/draftguitools/gui_dimension_ops.py @@ -52,24 +52,26 @@ class FlipDimension(gui_base.GuiCommandNeedsSelection): """ def __init__(self): - super(Draft_FlipDimension, self).__init__(name=translate("draft","Flip Dimension")) + super(Draft_FlipDimension, self).__init__(name=translate("draft", "Flip Dimension")) def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_FlipDimension', - 'MenuText': QT_TRANSLATE_NOOP("Draft_FlipDimension", - "Flip Dimension"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_FlipDimension", - "Flips the normal direction of the selected dimensions (linear, radial, angular).\nIf other objects are selected they are ignored.")} + return { + "Pixmap": "Draft_FlipDimension", + "MenuText": QT_TRANSLATE_NOOP("Draft_FlipDimension", "Flip Dimension"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_FlipDimension", + "Flips the normal direction of the selected dimensions (linear, radial, angular).\nIf other objects are selected they are ignored.", + ), + } def Activated(self): """Execute when the command is called.""" super(Draft_FlipDimension, self).Activated() for o in Gui.Selection.getSelection(): - if utils.get_type(o) in ("Dimension", - "LinearDimension", "AngularDimension"): + if utils.get_type(o) in ("Dimension", "LinearDimension", "AngularDimension"): self.doc.openTransaction("Flip dimension") _cmd = "App.activeDocument()." + o.Name + ".Normal" _cmd += " = " @@ -80,6 +82,6 @@ class FlipDimension(gui_base.GuiCommandNeedsSelection): Draft_FlipDimension = FlipDimension -Gui.addCommand('Draft_FlipDimension', FlipDimension()) +Gui.addCommand("Draft_FlipDimension", FlipDimension()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_dimensions.py b/src/Mod/Draft/draftguitools/gui_dimensions.py index c244858d59..0d694f0517 100644 --- a/src/Mod/Draft/draftguitools/gui_dimensions.py +++ b/src/Mod/Draft/draftguitools/gui_dimensions.py @@ -74,7 +74,7 @@ class Dimension(gui_base_original.Creator): def __init__(self): super().__init__() self.max = 2 - self.chain = None # Last chain's leg in ChainMode + self.chain = None # Last chain's leg in ChainMode self.contMode = None self.dir = None self.featureName = "Dimension" @@ -82,10 +82,15 @@ class Dimension(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Dimension', - 'Accel': "D, I", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Dimension", "Dimension"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Dimension", "Creates a linear dimension for a straight edge, a circular edge, or 2 picked points, or an angular dimension for 2 straight edges")} + return { + "Pixmap": "Draft_Dimension", + "Accel": "D, I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Dimension", "Dimension"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Dimension", + "Creates a linear dimension for a straight edge, a circular edge, or 2 picked points, or an angular dimension for 2 straight edges", + ), + } def Activated(self, dir_vec=None): """Execute when the command is called.""" @@ -123,9 +128,11 @@ class Dimension(gui_base_original.Creator): def set_selection(self): """Fill the nodes according to the selected geometry.""" sel = Gui.Selection.getSelectionEx() - if (len(sel) == 1 - and len(sel[0].SubElementNames) == 1 - and "Edge" in sel[0].SubElementNames[0]): + if ( + len(sel) == 1 + and len(sel[0].SubElementNames) == 1 + and "Edge" in sel[0].SubElementNames[0] + ): # The selection is just a single `Edge` sel_object = sel[0] edge = sel_object.SubObjects[0] @@ -137,8 +144,7 @@ class Dimension(gui_base_original.Creator): self.indices.append(n) if DraftGeomUtils.geomType(edge) == "Line": - self.node.extend([edge.Vertexes[0].Point, - edge.Vertexes[1].Point]) + self.node.extend([edge.Vertexes[0].Point, edge.Vertexes[1].Point]) # Iterate over the vertices of the parent `Object`; # when the vertices match those of the selected `edge` @@ -151,11 +157,10 @@ class Dimension(gui_base_original.Creator): if v.Point == edge.Vertexes[1].Point: v2 = i - if v1 is not None and v2 is not None: # note that v1 or v2 can be zero + if v1 is not None and v2 is not None: # note that v1 or v2 can be zero self.link = [sel_object.Object, v1, v2] elif DraftGeomUtils.geomType(edge) == "Circle": - self.node.extend([edge.Curve.Center, - edge.Vertexes[0].Point]) + self.node.extend([edge.Curve.Center, edge.Vertexes[0].Point]) self.edges = [edge] self.arcmode = "diameter" self.link = [sel_object.Object, n] @@ -172,10 +177,9 @@ class Dimension(gui_base_original.Creator): super().finish() def angle_dimension_normal(self, edge1, edge2): - rot = App.Rotation(DraftGeomUtils.vec(edge1), - DraftGeomUtils.vec(edge2), - self.wp.axis, - "XYZ") + rot = App.Rotation( + DraftGeomUtils.vec(edge1), DraftGeomUtils.vec(edge2), self.wp.axis, "XYZ" + ) norm = rot.multVec(App.Vector(0, 0, 1)) vnorm = gui_utils.get_3d_view().getViewDirection() if vnorm.getAngle(norm) < math.pi / 2: @@ -188,36 +192,38 @@ class Dimension(gui_base_original.Creator): ang2 = math.degrees(self.angledata[0]) norm = self.angle_dimension_normal(self.edges[0], self.edges[1]) - _cmd = 'Draft.make_angular_dimension' - _cmd += '(' - _cmd += 'center=' + DraftVecUtils.toString(self.center) + ', ' - _cmd += 'angles=' - _cmd += '[' - _cmd += str(ang1) + ', ' + _cmd = "Draft.make_angular_dimension" + _cmd += "(" + _cmd += "center=" + DraftVecUtils.toString(self.center) + ", " + _cmd += "angles=" + _cmd += "[" + _cmd += str(ang1) + ", " _cmd += str(ang2) - _cmd += '], ' - _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[-1]) + ', ' - _cmd += 'normal=' + DraftVecUtils.toString(norm) - _cmd += ')' - _cmd_list = ['_dim_ = ' + _cmd, - 'Draft.autogroup(_dim_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Dimension"), - _cmd_list) + _cmd += "], " + _cmd += "dim_line=" + DraftVecUtils.toString(self.node[-1]) + ", " + _cmd += "normal=" + DraftVecUtils.toString(norm) + _cmd += ")" + _cmd_list = [ + "_dim_ = " + _cmd, + "Draft.autogroup(_dim_)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Dimension"), _cmd_list) def create_linear_dimension(self): """Create a simple linear dimension, not linked to an edge.""" - _cmd = 'Draft.make_linear_dimension' - _cmd += '(' - _cmd += DraftVecUtils.toString(self.node[0]) + ', ' - _cmd += DraftVecUtils.toString(self.node[1]) + ', ' - _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2]) - _cmd += ')' - _cmd_list = ['_dim_ = ' + _cmd, - 'Draft.autogroup(_dim_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Dimension"), - _cmd_list) + _cmd = "Draft.make_linear_dimension" + _cmd += "(" + _cmd += DraftVecUtils.toString(self.node[0]) + ", " + _cmd += DraftVecUtils.toString(self.node[1]) + ", " + _cmd += "dim_line=" + DraftVecUtils.toString(self.node[2]) + _cmd += ")" + _cmd_list = [ + "_dim_ = " + _cmd, + "Draft.autogroup(_dim_)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Dimension"), _cmd_list) def create_linear_dimension_obj(self, direction=None): """Create a linear dimension linked to an edge. @@ -230,41 +236,40 @@ class Dimension(gui_base_original.Creator): with 1, that is, `Vertex1`. Therefore the value in `link` has to be incremented by 1. """ - _cmd = 'Draft.make_linear_dimension_obj' - _cmd += '(' - _cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', ' - _cmd += 'i1=' + str(self.link[1] + 1) + ', ' - _cmd += 'i2=' + str(self.link[2] + 1) + ', ' - _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2]) - _cmd += ')' - _cmd_list = ['_dim_ = ' + _cmd] + _cmd = "Draft.make_linear_dimension_obj" + _cmd += "(" + _cmd += "FreeCAD.ActiveDocument." + self.link[0].Name + ", " + _cmd += "i1=" + str(self.link[1] + 1) + ", " + _cmd += "i2=" + str(self.link[2] + 1) + ", " + _cmd += "dim_line=" + DraftVecUtils.toString(self.node[2]) + _cmd += ")" + _cmd_list = ["_dim_ = " + _cmd] dir_u = DraftVecUtils.toString(self.wp.u) dir_v = DraftVecUtils.toString(self.wp.v) if direction == "X": - _cmd_list += ['_dim_.Direction = ' + dir_u] + _cmd_list += ["_dim_.Direction = " + dir_u] elif direction == "Y": - _cmd_list += ['_dim_.Direction = ' + dir_v] + _cmd_list += ["_dim_.Direction = " + dir_v] - _cmd_list += ['Draft.autogroup(_dim_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Dimension"), - _cmd_list) + _cmd_list += ["Draft.autogroup(_dim_)", "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Create Dimension"), _cmd_list) def create_radial_dimension_obj(self): """Create a radial dimension linked to a circular edge.""" - _cmd = 'Draft.make_radial_dimension_obj' - _cmd += '(' - _cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', ' - _cmd += 'index=' + str(self.link[1] + 1) + ', ' + _cmd = "Draft.make_radial_dimension_obj" + _cmd += "(" + _cmd += "FreeCAD.ActiveDocument." + self.link[0].Name + ", " + _cmd += "index=" + str(self.link[1] + 1) + ", " _cmd += 'mode="' + str(self.arcmode) + '", ' - _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2]) - _cmd += ')' - _cmd_list = ['_dim_ = ' + _cmd, - 'Draft.autogroup(_dim_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Dimension"), - _cmd_list) + _cmd += "dim_line=" + DraftVecUtils.toString(self.node[2]) + _cmd += ")" + _cmd_list = [ + "_dim_ = " + _cmd, + "Draft.autogroup(_dim_)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Dimension"), _cmd_list) def createObject(self): """Create the actual object in the current document.""" @@ -325,23 +330,23 @@ class Dimension(gui_base_original.Creator): shift = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key()) if self.arcmode or self.point2: gui_tool_utils.setMod(arg, gui_tool_utils.get_mod_constrain_key(), False) - (self.point, - ctrlPoint, self.info) = gui_tool_utils.getPoint(self, arg, - noTracker=(len(self.node)>0)) - if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) - or self.selectmode) and (len(self.node) < 3): + (self.point, ctrlPoint, self.info) = gui_tool_utils.getPoint( + self, arg, noTracker=(len(self.node) > 0) + ) + if ( + gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) or self.selectmode + ) and (len(self.node) < 3): self.dimtrack.off() if not self.altdown: self.altdown = True self.ui.switchUi(True) if hasattr(Gui, "Snapper"): Gui.Snapper.setSelectMode(True) - snapped = self.view.getObjectInfo((arg["Position"][0], - arg["Position"][1])) + snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if snapped: - ob = self.doc.getObject(snapped['Object']) - if "Edge" in snapped['Component']: - num = int(snapped['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(snapped["Object"]) + if "Edge" in snapped["Component"]: + num = int(snapped["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] v1 = ed.Vertexes[0].Point v2 = ed.Vertexes[-1].Point @@ -367,11 +372,9 @@ class Dimension(gui_base_original.Creator): a = self.arctrack.getAngle(self.point) pair = DraftGeomUtils.getBoundaryAngles(a, self.angles) if not (pair[0] < a < pair[1]): - self.angledata = [4 * math.pi - pair[0], - 2 * math.pi - pair[1]] + self.angledata = [4 * math.pi - pair[0], 2 * math.pi - pair[1]] else: - self.angledata = [2 * math.pi - pair[0], - 2 * math.pi - pair[1]] + self.angledata = [2 * math.pi - pair[0], 2 * math.pi - pair[1]] self.arctrack.setStartAngle(self.angledata[0]) self.arctrack.setEndAngle(self.angledata[1]) if self.altdown: @@ -380,8 +383,7 @@ class Dimension(gui_base_original.Creator): if hasattr(Gui, "Snapper"): Gui.Snapper.setSelectMode(False) if self.node and self.dir and len(self.node) < 2: - _p = DraftVecUtils.project(self.point.sub(self.node[0]), - self.dir) + _p = DraftVecUtils.project(self.point.sub(self.node[0]), self.dir) self.point = self.node[0].add(_p) if len(self.node) == 2: if self.arcmode and self.edges: @@ -418,8 +420,7 @@ class Dimension(gui_base_original.Creator): # self.point2 = None # update the dimline if self.node and not self.arcmode: - self.dimtrack.update(self.node - + [self.point] + [self.chain]) + self.dimtrack.update(self.node + [self.point] + [self.chain]) gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): @@ -427,13 +428,15 @@ class Dimension(gui_base_original.Creator): self.ui.redraw() if (not self.node) and (not self.support): gui_tool_utils.getSupport(arg) - if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) - or self.selectmode) and (len(self.node) < 3): + if ( + gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) + or self.selectmode + ) and (len(self.node) < 3): # print("snapped: ",self.info) if self.info: - ob = self.doc.getObject(self.info['Object']) - if 'Edge' in self.info['Component']: - num = int(self.info['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(self.info["Object"]) + if "Edge" in self.info["Component"]: + num = int(self.info["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] v1 = ed.Vertexes[0].Point v2 = ed.Vertexes[-1].Point @@ -461,26 +464,37 @@ class Dimension(gui_base_original.Creator): self.edges.append(ed) # self.node now has the 4 endpoints self.node.extend([v1, v2]) - c = DraftGeomUtils.findIntersection(self.node[0], - self.node[1], - self.node[2], - self.node[3], - True, True) + c = DraftGeomUtils.findIntersection( + self.node[0], + self.node[1], + self.node[2], + self.node[3], + True, + True, + ) if c: # print("centers:",c) self.center = c[0] self.arctrack.setCenter(self.center) - self.arctrack.normal = self.angle_dimension_normal(self.edges[0], self.edges[1]) + self.arctrack.normal = self.angle_dimension_normal( + self.edges[0], self.edges[1] + ) self.arctrack.on() for e in self.edges: - if e.Length < 0.00003: # Edge must be long enough for the tolerance of 0.00001mm to make sense. + if ( + e.Length < 0.00003 + ): # Edge must be long enough for the tolerance of 0.00001mm to make sense. _msg(translate("draft", "Edge too short!")) self.finish() return for i in [0, 1]: pt = e.Vertexes[i].Point - if pt.isEqual(self.center, 0.00001): # A relatively high tolerance is required. - pt = e.Vertexes[i - 1].Point # Use the other point instead. + if pt.isEqual( + self.center, 0.00001 + ): # A relatively high tolerance is required. + pt = e.Vertexes[ + i - 1 + ].Point # Use the other point instead. self.angles.append(self.arctrack.getAngle(pt)) self.link = [self.link[0], ob] else: @@ -545,27 +559,27 @@ class Dimension(gui_base_original.Creator): if not self.proj_point1 or not self.proj_point2: self.proj_point1 = self.wp.project_point(self.node[0]) self.proj_point2 = self.wp.project_point(self.node[1]) - proj_u= self.wp.u.dot(self.proj_point2 - self.proj_point1) - proj_v= self.wp.v.dot(self.proj_point2 - self.proj_point1) + proj_u = self.wp.u.dot(self.proj_point2 - self.proj_point1) + proj_v = self.wp.v.dot(self.proj_point2 - self.proj_point1) active_view = Gui.ActiveDocument.ActiveView cursor = active_view.getCursorPos() cursor_point = active_view.getPoint(cursor) self.point = self.wp.project_point(cursor_point) if not self.force: - ref_point = self.point - (self.proj_point2 + self.proj_point1)*1/2 + ref_point = self.point - (self.proj_point2 + self.proj_point1) * 1 / 2 ref_angle = abs(ref_point.getAngle(self.wp.u)) - if (ref_angle > math.pi/4) and (ref_angle <= 0.75*math.pi): + if (ref_angle > math.pi / 4) and (ref_angle <= 0.75 * math.pi): self.force = 2 else: self.force = 1 if self.force == 1: self.node[0] = self.proj_point1 - self.node[1] = self.proj_point1 + self.wp.v*proj_v + self.node[1] = self.proj_point1 + self.wp.v * proj_v elif self.force == 2: self.node[0] = self.proj_point1 - self.node[1] = self.proj_point1 + self.wp.u*proj_u + self.node[1] = self.proj_point1 + self.wp.u * proj_u -Gui.addCommand('Draft_Dimension', Dimension()) +Gui.addCommand("Draft_Dimension", Dimension()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_downgrade.py b/src/Mod/Draft/draftguitools/gui_downgrade.py index 9d10fa8a75..167a779498 100644 --- a/src/Mod/Draft/draftguitools/gui_downgrade.py +++ b/src/Mod/Draft/draftguitools/gui_downgrade.py @@ -53,10 +53,15 @@ class Downgrade(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Downgrade', - 'Accel': "D, N", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Downgrade", "Downgrade"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Downgrade", "Downgrades the selected objects into simpler shapes.\nThe result of the operation depends on the types of objects, which may be downgraded several times in a row.\nFor example, a 3D solid is deconstructed into separate faces, wires, and then edges. Faces can also be subtracted.")} + return { + "Pixmap": "Draft_Downgrade", + "Accel": "D, N", + "MenuText": QT_TRANSLATE_NOOP("Draft_Downgrade", "Downgrade"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Downgrade", + "Downgrades the selected objects into simpler shapes.\nThe result of the operation depends on the types of objects, which may be downgraded several times in a row.\nFor example, a 3D solid is deconstructed into separate faces, wires, and then edges. Faces can also be subtracted.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -76,18 +81,16 @@ class Downgrade(gui_base_original.Modifier): self.end_callbacks(self.call) if Gui.Selection.getSelection(): Gui.addModule("Draft") - _cmd = 'Draft.downgrade' - _cmd += '(' - _cmd += 'FreeCADGui.Selection.getSelection(), ' - _cmd += 'delete=True' - _cmd += ')' - _cmd_list = ['_objs_ = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Downgrade"), - _cmd_list) + _cmd = "Draft.downgrade" + _cmd += "(" + _cmd += "FreeCADGui.Selection.getSelection(), " + _cmd += "delete=True" + _cmd += ")" + _cmd_list = ["_objs_ = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Downgrade"), _cmd_list) self.finish() -Gui.addCommand('Draft_Downgrade', Downgrade()) +Gui.addCommand("Draft_Downgrade", Downgrade()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_draft2sketch.py b/src/Mod/Draft/draftguitools/gui_draft2sketch.py index ba6c1491b2..9a94832a7b 100644 --- a/src/Mod/Draft/draftguitools/gui_draft2sketch.py +++ b/src/Mod/Draft/draftguitools/gui_draft2sketch.py @@ -53,9 +53,14 @@ class Draft2Sketch(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Draft2Sketch', - 'MenuText': QT_TRANSLATE_NOOP("Draft_Draft2Sketch", "Draft to Sketch"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Draft2Sketch", "Converts bidirectionally between Draft objects and sketches.\nMultiple selected Draft objects are converted into a single sketch.\nHowever, a single sketch with disconnected traces is converted into several individual Draft objects.")} + return { + "Pixmap": "Draft_Draft2Sketch", + "MenuText": QT_TRANSLATE_NOOP("Draft_Draft2Sketch", "Draft to Sketch"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Draft2Sketch", + "Converts bidirectionally between Draft objects and sketches.\nMultiple selected Draft objects are converted into a single sketch.\nHowever, a single sketch with disconnected traces is converted into several individual Draft objects.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -80,8 +85,9 @@ class Draft2Sketch(gui_base_original.Modifier): for obj in sel: if obj.isDerivedFrom("Sketcher::SketchObject"): allDraft = False - elif (obj.isDerivedFrom("Part::Part2DObjectPython") - or obj.isDerivedFrom("Part::Feature")): + elif obj.isDerivedFrom("Part::Part2DObjectPython") or obj.isDerivedFrom( + "Part::Feature" + ): allSketches = False else: allDraft = False @@ -95,10 +101,8 @@ class Draft2Sketch(gui_base_original.Modifier): _cmd += "FreeCADGui.Selection.getSelection(), " _cmd += "autoconstraints=True" _cmd += ")" - _cmd_list = ['sk = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Convert to Sketch"), - _cmd_list) + _cmd_list = ["sk = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Convert to Sketch"), _cmd_list) elif allSketches: n = 0 _cmd_list = list() @@ -111,9 +115,8 @@ class Draft2Sketch(gui_base_original.Modifier): _cmd_list.append("df" + str(n) + " = " + _cmd) n += 1 - _cmd_list.append('FreeCAD.ActiveDocument.recompute()') - self.commit(translate("draft", "Convert to Draft"), - _cmd_list) + _cmd_list.append("FreeCAD.ActiveDocument.recompute()") + self.commit(translate("draft", "Convert to Draft"), _cmd_list) else: _cmd_list = list() n = 0 @@ -132,20 +135,20 @@ class Draft2Sketch(gui_base_original.Modifier): if obj.isDerivedFrom("Sketcher::SketchObject"): _cmd_list.append("obj" + str(n) + " = " + _cmd_df) - elif (obj.isDerivedFrom("Part::Part2DObjectPython") - or obj.isDerivedFrom("Part::Feature")): + elif obj.isDerivedFrom("Part::Part2DObjectPython") or obj.isDerivedFrom( + "Part::Feature" + ): _cmd_list.append("obj" + str(n) + " = " + _cmd_sk) - #elif obj.isDerivedFrom("Part::Feature"): + # elif obj.isDerivedFrom("Part::Feature"): # # if (len(obj.Shape.Wires) == 1 # # or len(obj.Shape.Edges) == 1): # _cmd_list.append("obj" + str(n) + " = " + _cmd_sk) n += 1 - _cmd_list.append('FreeCAD.ActiveDocument.recompute()') - self.commit(translate("draft", "Convert Draft/Sketch"), - _cmd_list) + _cmd_list.append("FreeCAD.ActiveDocument.recompute()") + self.commit(translate("draft", "Convert Draft/Sketch"), _cmd_list) self.finish() -Gui.addCommand('Draft_Draft2Sketch', Draft2Sketch()) +Gui.addCommand("Draft_Draft2Sketch", Draft2Sketch()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit.py b/src/Mod/Draft/draftguitools/gui_edit.py index fcae555760..f3ca6f2a9a 100644 --- a/src/Mod/Draft/draftguitools/gui_edit.py +++ b/src/Mod/Draft/draftguitools/gui_edit.py @@ -26,8 +26,9 @@ # \brief Provides GUI tools to start the edit mode of different objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Carlo Pavan") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Carlo Pavan" +) __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -55,15 +56,15 @@ from draftguitools import gui_trackers as trackers COLORS = { "default": utils.get_rgba_tuple(params.get_param("snapcolor"))[:3], - "black": (0., 0., 0.), - "white": (1., 1., 1.), - "grey": (.5, .5, .5), - "red": (1., 0., 0.), - "green": (0., 1., 0.), - "blue": (0., 0., 1.), - "yellow": (1., 1., 0.), - "cyan": (0., 1., 1.), - "magenta": (1., 0., 1.) + "black": (0.0, 0.0, 0.0), + "white": (1.0, 1.0, 1.0), + "grey": (0.5, 0.5, 0.5), + "red": (1.0, 0.0, 0.0), + "green": (0.0, 1.0, 0.0), + "blue": (0.0, 0.0, 1.0), + "yellow": (1.0, 1.0, 0.0), + "cyan": (0.0, 1.0, 1.0), + "magenta": (1.0, 0.0, 1.0), } @@ -198,7 +199,7 @@ class Edit(gui_base_original.Modifier): super().__init__() """Initialize Draft_Edit Command.""" self.running = False - self.trackers = {'object': []} + self.trackers = {"object": []} self.overNode = None # preselected node with mouseover self.edited_objects = [] self.obj = None @@ -218,7 +219,7 @@ class Edit(gui_base_original.Modifier): self.max_objects = 5 self.pick_radius = 20 - self.alt_edit_mode = 0 # default edit mode for objects + self.alt_edit_mode = 0 # default edit mode for objects # preview self.ghost = None @@ -226,40 +227,43 @@ class Edit(gui_base_original.Modifier): # setup gui_tools for every supported object self.gui_tools_repository = GuiToolsRepository() - self.gui_tools_repository.add('Wire', edit_draft.DraftWireGuiTools()) - self.gui_tools_repository.add('BSpline', edit_draft.DraftBSplineGuiTools()) - self.gui_tools_repository.add('BezCurve', edit_draft.DraftBezCurveGuiTools()) - self.gui_tools_repository.add('Circle', edit_draft.DraftCircleGuiTools()) - self.gui_tools_repository.add('Rectangle', edit_draft.DraftRectangleGuiTools()) - self.gui_tools_repository.add('Polygon', edit_draft.DraftPolygonGuiTools()) - self.gui_tools_repository.add('Ellipse', edit_draft.DraftEllipseGuiTools()) - self.gui_tools_repository.add('Dimension', edit_draft.DraftDimensionGuiTools()) # Backward compatibility - self.gui_tools_repository.add('LinearDimension', edit_draft.DraftDimensionGuiTools()) - self.gui_tools_repository.add('Label', edit_draft.DraftLabelGuiTools()) + self.gui_tools_repository.add("Wire", edit_draft.DraftWireGuiTools()) + self.gui_tools_repository.add("BSpline", edit_draft.DraftBSplineGuiTools()) + self.gui_tools_repository.add("BezCurve", edit_draft.DraftBezCurveGuiTools()) + self.gui_tools_repository.add("Circle", edit_draft.DraftCircleGuiTools()) + self.gui_tools_repository.add("Rectangle", edit_draft.DraftRectangleGuiTools()) + self.gui_tools_repository.add("Polygon", edit_draft.DraftPolygonGuiTools()) + self.gui_tools_repository.add("Ellipse", edit_draft.DraftEllipseGuiTools()) + self.gui_tools_repository.add( + "Dimension", edit_draft.DraftDimensionGuiTools() + ) # Backward compatibility + self.gui_tools_repository.add("LinearDimension", edit_draft.DraftDimensionGuiTools()) + self.gui_tools_repository.add("Label", edit_draft.DraftLabelGuiTools()) - self.gui_tools_repository.add('Wall', edit_arch.ArchWallGuiTools()) - self.gui_tools_repository.add('Window', edit_arch.ArchWindowGuiTools()) - self.gui_tools_repository.add('Structure', edit_arch.ArchStructureGuiTools()) - self.gui_tools_repository.add('Space', edit_arch.ArchSpaceGuiTools()) - self.gui_tools_repository.add('PanelCut', edit_arch.ArchPanelCutGuiTools()) - self.gui_tools_repository.add('PanelSheet', edit_arch.ArchPanelSheetGuiTools()) + self.gui_tools_repository.add("Wall", edit_arch.ArchWallGuiTools()) + self.gui_tools_repository.add("Window", edit_arch.ArchWindowGuiTools()) + self.gui_tools_repository.add("Structure", edit_arch.ArchStructureGuiTools()) + self.gui_tools_repository.add("Space", edit_arch.ArchSpaceGuiTools()) + self.gui_tools_repository.add("PanelCut", edit_arch.ArchPanelCutGuiTools()) + self.gui_tools_repository.add("PanelSheet", edit_arch.ArchPanelSheetGuiTools()) - self.gui_tools_repository.add('Part::Line', edit_part.PartLineGuiTools()) - self.gui_tools_repository.add('Part::Box', edit_part.PartBoxGuiTools()) - self.gui_tools_repository.add('Part::Cylinder', edit_part.PartCylinderGuiTools()) - self.gui_tools_repository.add('Part::Cone', edit_part.PartConeGuiTools()) - self.gui_tools_repository.add('Part::Sphere', edit_part.PartSphereGuiTools()) - - self.gui_tools_repository.add('Sketcher::SketchObject', edit_sketcher.SketcherSketchObjectGuiTools()) + self.gui_tools_repository.add("Part::Line", edit_part.PartLineGuiTools()) + self.gui_tools_repository.add("Part::Box", edit_part.PartBoxGuiTools()) + self.gui_tools_repository.add("Part::Cylinder", edit_part.PartCylinderGuiTools()) + self.gui_tools_repository.add("Part::Cone", edit_part.PartConeGuiTools()) + self.gui_tools_repository.add("Part::Sphere", edit_part.PartSphereGuiTools()) + self.gui_tools_repository.add( + "Sketcher::SketchObject", edit_sketcher.SketcherSketchObjectGuiTools() + ) def GetResources(self): - return {'Pixmap': 'Draft_Edit', - 'Accel': "D, E", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object") - } - + return { + "Pixmap": "Draft_Edit", + "Accel": "D, E", + "MenuText": QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"), + "ToolTip": QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object"), + } # ------------------------------------------------------------------------- # MAIN FUNCTIONS @@ -286,12 +290,9 @@ class Edit(gui_base_original.Modifier): self.proceed() else: self.ui.selectUi(on_close_call=self.finish) - App.Console.PrintMessage(translate("draft", - "Select a Draft object to edit") - + "\n") + App.Console.PrintMessage(translate("draft", "Select a Draft object to edit") + "\n") self.register_selection_callback() - def proceed(self): """this method set the editTrackers""" self.unregister_selection_callback() @@ -312,7 +313,6 @@ class Edit(gui_base_original.Modifier): self.register_editing_callbacks() - def numericInput(self, numx, numy, numz): """Execute callback by the toolbar to activate the update function. @@ -322,7 +322,6 @@ class Edit(gui_base_original.Modifier): self.endEditing(self.obj, self.editing, App.Vector(numx, numy, numz)) App.ActiveDocument.recompute() - def finish(self, cont=False): """Terminate Edit Tool.""" self.unregister_selection_callback() @@ -341,6 +340,7 @@ class Edit(gui_base_original.Modifier): self.running = False # delay resetting edit mode otherwise it doesn't happen from PySide import QtCore + QtCore.QTimer.singleShot(0, self.reset_edit) def reset_edit(self): @@ -375,14 +375,17 @@ class Edit(gui_base_original.Modifier): self.render_manager = self.view.getViewer().getSoRenderManager() if self._keyPressedCB is None: self._keyPressedCB = self.view.addEventCallbackPivy( - coin.SoKeyboardEvent.getClassTypeId(), self.keyPressed) + coin.SoKeyboardEvent.getClassTypeId(), self.keyPressed + ) if self._mouseMovedCB is None: self._mouseMovedCB = self.view.addEventCallbackPivy( - coin.SoLocation2Event.getClassTypeId(), self.mouseMoved) + coin.SoLocation2Event.getClassTypeId(), self.mouseMoved + ) if self._mousePressedCB is None: self._mousePressedCB = self.view.addEventCallbackPivy( - coin.SoMouseButtonEvent.getClassTypeId(), self.mousePressed) - #App.Console.PrintMessage("Draft edit callbacks registered \n") + coin.SoMouseButtonEvent.getClassTypeId(), self.mousePressed + ) + # App.Console.PrintMessage("Draft edit callbacks registered \n") def unregister_editing_callbacks(self): """ @@ -390,14 +393,20 @@ class Edit(gui_base_original.Modifier): """ try: if self._keyPressedCB: - self.view.removeEventCallbackSWIG(coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB) - #App.Console.PrintMessage("Draft edit keyboard callback unregistered \n") + self.view.removeEventCallbackSWIG( + coin.SoKeyboardEvent.getClassTypeId(), self._keyPressedCB + ) + # App.Console.PrintMessage("Draft edit keyboard callback unregistered \n") if self._mouseMovedCB: - self.view.removeEventCallbackSWIG(coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB) - #App.Console.PrintMessage("Draft edit location callback unregistered \n") + self.view.removeEventCallbackSWIG( + coin.SoLocation2Event.getClassTypeId(), self._mouseMovedCB + ) + # App.Console.PrintMessage("Draft edit location callback unregistered \n") if self._mousePressedCB: - self.view.removeEventCallbackSWIG(coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB) - #App.Console.PrintMessage("Draft edit mouse button callback unregistered \n") + self.view.removeEventCallbackSWIG( + coin.SoMouseButtonEvent.getClassTypeId(), self._mousePressedCB + ) + # App.Console.PrintMessage("Draft edit mouse button callback unregistered \n") except RuntimeError: # the view has been deleted already pass @@ -420,7 +429,9 @@ class Edit(gui_base_original.Modifier): self.finish() if key == 101: # "e" self.display_tracker_menu(event) - if key == 65535 and Gui.Selection.getSelection() is None: # BUG: delete key activate Std::Delete command at the same time! + if ( + key == 65535 and Gui.Selection.getSelection() is None + ): # BUG: delete key activate Std::Delete command at the same time! print("DELETE PRESSED\n") self.delPoint(event) @@ -429,9 +440,9 @@ class Edit(gui_base_original.Modifier): mouse button event handler, calls: startEditing, endEditing, addPoint, delPoint """ event = event_callback.getEvent() - if (event.getState() == coin.SoMouseButtonEvent.DOWN and - event.getButton() == event.BUTTON1 - ):#left click + if ( + event.getState() == coin.SoMouseButtonEvent.DOWN and event.getButton() == event.BUTTON1 + ): # left click if not event.wasAltDown(): if self.editing is None: @@ -474,13 +485,11 @@ class Edit(gui_base_original.Modifier): def startEditing(self, obj, node_idx): """Start editing selected EditNode.""" - self.obj = obj # this is still needed to handle preview + self.obj = obj # this is still needed to handle preview if obj is None: return - App.Console.PrintMessage(obj.Name - + ": editing node number " - + str(node_idx) + "\n") + App.Console.PrintMessage(obj.Name + ": editing node number " + str(node_idx) + "\n") self.ui.lineUi(title=translate("draft", "Edit Node"), icon="Draft_Edit") self.ui.continueCmd.hide() @@ -500,7 +509,7 @@ class Edit(gui_base_original.Modifier): orthoConstrain = False if event.wasShiftDown() == 1: orthoConstrain = True - snappedPos = Gui.Snapper.snap((pos[0],pos[1]),self.node[-1], constrain=orthoConstrain) + snappedPos = Gui.Snapper.snap((pos[0], pos[1]), self.node[-1], constrain=orthoConstrain) self.trackers[self.obj.Name][self.editing].set(snappedPos) self.ui.displayPoint(snappedPos, self.node[-1], mask=Gui.Snapper.affinity) if self.ghost: @@ -526,7 +535,6 @@ class Edit(gui_base_original.Modifier): self.showTrackers() gui_tool_utils.redraw_3d_view() - # ------------------------------------------------------------------------- # EDIT TRACKERS functions # ------------------------------------------------------------------------- @@ -539,14 +547,16 @@ class Edit(gui_base_original.Modifier): _wrn = translate("draft", "No edit point found for selected object") App.Console.PrintWarning(_wrn + "\n") # do not finish if some trackers are still present - if self.trackers == {'object': []}: + if self.trackers == {"object": []}: self.finish() return self.trackers[obj.Name] = [] if obj.Name in self.trackers: self.removeTrackers(obj) for ep in range(len(points)): - self.trackers[obj.Name].append(trackers.editTracker(pos=points[ep], name=obj.Name, idx=ep)) + self.trackers[obj.Name].append( + trackers.editTracker(pos=points[ep], name=obj.Name, idx=ep) + ) def resetTrackers(self, obj): """Reset Edit Trackers and set them again.""" @@ -557,28 +567,28 @@ class Edit(gui_base_original.Modifier): # in future move tracker definition to DraftTrackers size = params.get_param_view("MarkerSize") knotmarkers = ( - Gui.getMarkerIndex("DIAMOND_FILLED", size), # sharp - Gui.getMarkerIndex("SQUARE_FILLED", size), # tangent - Gui.getMarkerIndex("HOURGLASS_FILLED", size) # symmetric + Gui.getMarkerIndex("DIAMOND_FILLED", size), # sharp + Gui.getMarkerIndex("SQUARE_FILLED", size), # tangent + Gui.getMarkerIndex("HOURGLASS_FILLED", size), # symmetric ) - polemarker = Gui.getMarkerIndex("CIRCLE_FILLED", size) # pole + polemarker = Gui.getMarkerIndex("CIRCLE_FILLED", size) # pole self.trackers[obj.Name] = [] cont = obj.Continuity firstknotcont = cont[-1] if (obj.Closed and cont) else 0 - pointswithmarkers = [(obj.Shape.Edges[0].Curve. - getPole(1),knotmarkers[firstknotcont])] + pointswithmarkers = [(obj.Shape.Edges[0].Curve.getPole(1), knotmarkers[firstknotcont])] for edgeindex, edge in enumerate(obj.Shape.Edges): poles = edge.Curve.getPoles() - pointswithmarkers.extend([(point,polemarker) for point in poles[1:-1]]) - if not obj.Closed or len(obj.Shape.Edges) > edgeindex +1: + pointswithmarkers.extend([(point, polemarker) for point in poles[1:-1]]) + if not obj.Closed or len(obj.Shape.Edges) > edgeindex + 1: knotmarkeri = cont[edgeindex] if len(cont) > edgeindex else 0 - pointswithmarkers.append((poles[-1],knotmarkers[knotmarkeri])) + pointswithmarkers.append((poles[-1], knotmarkers[knotmarkeri])) for index, pwm in enumerate(pointswithmarkers): p, marker = pwm p = obj.Placement.inverse().multVec(p) p = obj.getGlobalPlacement().multVec(p) - self.trackers[obj.Name].append(trackers.editTracker(p, obj.Name, - index, obj.ViewObject.LineColor, marker=marker)) + self.trackers[obj.Name].append( + trackers.editTracker(p, obj.Name, index, obj.ViewObject.LineColor, marker=marker) + ) def removeTrackers(self, obj=None): """Remove Edit Trackers. @@ -593,7 +603,7 @@ class Edit(gui_base_original.Modifier): for key in self.trackers: for t in self.trackers[key]: t.finalize() - self.trackers = {'object': []} + self.trackers = {"object": []} else: key = obj.Name if key in self.trackers: @@ -690,7 +700,8 @@ class Edit(gui_base_original.Modifier): if actions is None: return - for (label, callback) in actions: + for label, callback in actions: + def wrapper(callback=callback): callback() self.resetTrackers(obj) @@ -700,16 +711,14 @@ class Edit(gui_base_original.Modifier): self.tracker_menu.popup(Gui.getMainWindow().cursor().pos()) - QtCore.QObject.connect(self.tracker_menu, - QtCore.SIGNAL("triggered(QAction *)"), - self.evaluate_menu_action) - + QtCore.QObject.connect( + self.tracker_menu, QtCore.SIGNAL("triggered(QAction *)"), self.evaluate_menu_action + ) def evaluate_menu_action(self, action): callback = action.data() callback() - # ------------------------------------------------------------------------- # EDIT OBJECT TOOLS # @@ -718,8 +727,7 @@ class Edit(gui_base_original.Modifier): # ------------------------------------------------------------------------- def getEditPoints(self, obj): - """Return a list of App.Vectors according to the given object edit nodes. - """ + """Return a list of App.Vectors according to the given object edit nodes.""" eps = None obj_gui_tools = self.get_obj_gui_tools(obj) @@ -731,7 +739,6 @@ class Edit(gui_base_original.Modifier): else: return None - def update(self, obj, nodeIndex, v): """Apply the App.Vector to the modified point and update obj.""" v = self.localize_vector(obj, v) @@ -744,35 +751,33 @@ class Edit(gui_base_original.Modifier): except AttributeError as err: pass - def update_object(self, obj, nodeIndex, v): - """Update the object according to the given modified editpoint. - """ + """Update the object according to the given modified editpoint.""" obj_gui_tools = self.get_obj_gui_tools(obj) if obj_gui_tools: - eps = obj_gui_tools.update_object_from_edit_points(obj, nodeIndex, v, self.alt_edit_mode) + eps = obj_gui_tools.update_object_from_edit_points( + obj, nodeIndex, v, self.alt_edit_mode + ) obj.recompute() - # ------------------------------------------------------------------------- # UTILS # ------------------------------------------------------------------------- def has_obj_gui_tools(self, obj): - """ Check if the object has the GuiTools to provide information to edit it. - """ - if (hasattr(obj, 'obj_gui_tools') or - (hasattr(obj, 'Proxy') and hasattr(obj.Proxy, 'obj_gui_tools')) or - (utils.get_type(obj) in self.gui_tools_repository.keys()) ): + """Check if the object has the GuiTools to provide information to edit it.""" + if ( + hasattr(obj, "obj_gui_tools") + or (hasattr(obj, "Proxy") and hasattr(obj.Proxy, "obj_gui_tools")) + or (utils.get_type(obj) in self.gui_tools_repository.keys()) + ): return True else: return False - def get_obj_gui_tools(self, obj): - """ Retrieve the obj_gui_tools to support Draft Edit. - """ + """Retrieve the obj_gui_tools to support Draft Edit.""" try: obj_gui_tools = obj.obj_gui_tools except AttributeError: @@ -785,14 +790,13 @@ class Edit(gui_base_original.Modifier): obj_gui_tools = None return obj_gui_tools - def getObjsFromSelection(self): """Evaluate selection and return a valid object to edit. #to be used for app link support for selobj in Gui.Selection.getSelectionEx('', 0): - for sub in selobj.SubElementNames: + for sub in selobj.SubElementNames: obj = selobj.Object obj_matrix = selobj.Object.getSubObject(sub, retType=4) """ @@ -811,20 +815,16 @@ class Edit(gui_base_original.Modifier): App.Console.PrintWarning(obj.Name + _wrn + "\n") return self.edited_objects - def format_objects_for_editing(self, objs): - """Change objects style during editing mode. - """ + """Change objects style during editing mode.""" for obj in objs: obj_gui_tools = self.get_obj_gui_tools(obj) if obj_gui_tools: self.objs_formats[obj.Name] = obj_gui_tools.get_object_style(obj) obj_gui_tools.set_object_editing_style(obj) - def deformat_objects_after_editing(self, objs): - """Restore objects style during editing mode. - """ + """Restore objects style during editing mode.""" for obj in objs: if utils.is_deleted(obj): continue @@ -832,11 +832,9 @@ class Edit(gui_base_original.Modifier): if obj_gui_tools: obj_gui_tools.restore_object_style(obj, self.objs_formats[obj.Name]) - def get_specific_object_info(self, obj, pos): - """Return info of a specific object at a given position. - """ - selobjs = self.view.getObjectsInfo((pos[0],pos[1])) + """Return info of a specific object at a given position.""" + selobjs = self.view.getObjectsInfo((pos[0], pos[1])) if not selobjs: return for info in selobjs: @@ -852,7 +850,7 @@ class Edit(gui_base_original.Modifier): If object is one of the edited objects (self.edited_objects). """ - selobjs = self.view.getObjectsInfo((pos[0],pos[1])) + selobjs = self.view.getObjectsInfo((pos[0], pos[1])) if not selobjs: return for info in selobjs: @@ -913,8 +911,10 @@ class Edit(gui_base_original.Modifier): path = point.getPath() length = path.getLength() point = path.getNode(length - 2) - #import DraftTrackers - if hasattr(point,"subElementName") and 'EditNode' in str(point.subElementName.getValue()): + # import DraftTrackers + if hasattr(point, "subElementName") and "EditNode" in str( + point.subElementName.getValue() + ): return point return None @@ -928,16 +928,16 @@ class Edit(gui_base_original.Modifier): return None - -class GuiToolsRepository(): - """ This object provide a repository to collect all the specific objects +class GuiToolsRepository: + """This object provide a repository to collect all the specific objects editing tools. """ + def __init__(self): - self.obj_gui_tools = {} + self.obj_gui_tools = {} def get(self, obj_type): - return self.obj_gui_tools[obj_type] + return self.obj_gui_tools[obj_type] def add(self, type, gui_tools): self.obj_gui_tools[type] = gui_tools @@ -946,7 +946,6 @@ class GuiToolsRepository(): return self.obj_gui_tools.keys() - -Gui.addCommand('Draft_Edit', Edit()) +Gui.addCommand("Draft_Edit", Edit()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py b/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py index 2ddcd0a02f..0b175b34bc 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_arch_objects.py @@ -26,8 +26,9 @@ # \brief Provides support functions to edit Arch objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Carlo Pavan") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Carlo Pavan" +) __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -42,7 +43,6 @@ import draftutils.utils as utils from draftguitools.gui_edit_base_object import GuiTools - class ArchWallGuiTools(GuiTools): def __init__(self): @@ -61,13 +61,13 @@ class ArchWallGuiTools(GuiTools): return editpoints def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): - ''' if node_idx == 0: + """if node_idx == 0: edit_arch.updateWall(obj, node_idx, v) elif node_idx > 0: if obj.Base: if utils.get_type(obj.Base) in ["Wire", "Circle", "Rectangle", "Polygon", "Sketch"]: - self.update(obj.Base, node_idx - 1, v)''' + self.update(obj.Base, node_idx - 1, v)""" if node_idx == 0: vz = DraftVecUtils.project(v, App.Vector(0, 0, 1)) if vz.Length > 0: @@ -86,9 +86,13 @@ class ArchWindowGuiTools(GuiTools): normal = obj.Normal angle = normal.getAngle(App.Vector(1, 0, 0)) editpoints.append(pos) - editpoints.append(App.Vector(pos.x + float(obj.Width) * math.cos(angle-math.pi / 2.0), - pos.y + float(obj.Width) * math.sin(angle-math.pi / 2.0), - pos.z)) + editpoints.append( + App.Vector( + pos.x + float(obj.Width) * math.cos(angle - math.pi / 2.0), + pos.y + float(obj.Width) * math.sin(angle - math.pi / 2.0), + pos.z, + ) + ) editpoints.append(App.Vector(pos.x, pos.y, h)) return editpoints @@ -127,9 +131,7 @@ class ArchStructureGuiTools(GuiTools): obj.Nodes = nodes def get_object_style(self, obj): - return (obj.ViewObject.DisplayMode, - obj.ViewObject.NodeSize, - obj.ViewObject.ShowNodes) + return (obj.ViewObject.DisplayMode, obj.ViewObject.NodeSize, obj.ViewObject.ShowNodes) def set_object_editing_style(self, obj): obj.ViewObject.DisplayMode = "Wireframe" @@ -195,6 +197,7 @@ class ArchPanelSheetGuiTools(GuiTools): if node_idx == 0: obj.TagPosition = v else: - obj.Group[node_idx-1].Placement.Base = v + obj.Group[node_idx - 1].Placement.Base = v + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit_base_object.py b/src/Mod/Draft/draftguitools/gui_edit_base_object.py index d5d37822ce..6c58f3bf08 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_base_object.py +++ b/src/Mod/Draft/draftguitools/gui_edit_base_object.py @@ -24,7 +24,7 @@ # \brief Provides support functions to edit Arch objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Carlo Pavan") +__author__ = "Carlo Pavan" __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -32,8 +32,7 @@ __url__ = "https://www.freecad.org" class GuiTools: - """ Base class for object editing tools - """ + """Base class for object editing tools""" def __init__(self): pass @@ -62,7 +61,7 @@ class GuiTools: pass def get_edit_point_context_menu(self, edit_command, obj, node_idx): - """ Get the context menu associated to edit points (user is over an editpoint) + """Get the context menu associated to edit points (user is over an editpoint) Return a list of tuples containing menu labels and associated functions: return [ @@ -77,7 +76,7 @@ class GuiTools: pass def get_edit_obj_context_menu(self, edit_command, obj, position): - """ Get the context menu associated to edited object (user is over the object) + """Get the context menu associated to edited object (user is over the object) Return a list of tuples containing menu labels and associated functions: return [ @@ -106,4 +105,5 @@ class GuiTools: def update_preview_object(self, edit_command, obj, node_idx, v): pass + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py b/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py index 2a39673d69..4dfb811344 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_draft_objects.py @@ -38,8 +38,9 @@ TODO: Abstract the code that handles the preview and move the object specific # \brief Provides support functions to edit Draft objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Carlo Pavan") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Carlo Pavan" +) __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -58,7 +59,6 @@ import draftguitools.gui_trackers as trackers from draftguitools.gui_edit_base_object import GuiTools - class DraftWireGuiTools(GuiTools): def __init__(self): @@ -72,8 +72,8 @@ class DraftWireGuiTools(GuiTools): def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): pts = obj.Points - tol = 0.001 # TODO : Use default precision - if (node_idx == 0 and (v - pts[-1]).Length < tol ): + tol = 0.001 # TODO : Use default precision + if node_idx == 0 and (v - pts[-1]).Length < tol: # DNC: user moved first point over last point -> Close curve obj.Closed = True pts[0] = v @@ -88,14 +88,13 @@ class DraftWireGuiTools(GuiTools): return elif v in pts: # DNC: checks if point enter is equal to other, this could cause a OCC problem - _err = translate("draft", "This object does not support possible " - "coincident points") + _err = translate("draft", "This object does not support possible " "coincident points") App.Console.PrintMessage(_err + "\n") return # TODO: Make consistent operation with trackers and open wires # See: https://forum.freecad.org/viewtopic.php?f=23&t=56661 - #if obj.Closed: + # if obj.Closed: # # DNC: project the new point to the plane of the face if present # if hasattr(obj.Shape, "normalAt"): # normal = obj.Shape.normalAt(0,0) @@ -118,16 +117,14 @@ class DraftWireGuiTools(GuiTools): ] def get_open_close_menu_text(self, obj): - """This function is overridden in the DraftBSplineGuiTools class. - """ + """This function is overridden in the DraftBSplineGuiTools class.""" if obj.Closed: return translate("draft", "Open Wire") else: return translate("draft", "Close Wire") def get_reverse_menu_text(self, obj): - """This function is overridden in the DraftBSplineGuiTools class. - """ + """This function is overridden in the DraftBSplineGuiTools class.""" return translate("draft", "Reverse Wire") def init_preview_object(self, obj): @@ -142,13 +139,12 @@ class DraftWireGuiTools(GuiTools): edit_command.ghost.updateFromPointlist(pointList) def add_point(self, edit_command, obj, pos): - """Add point to obj. - """ - info, newPoint = edit_command.get_specific_object_info(obj,pos) + """Add point to obj.""" + info, newPoint = edit_command.get_specific_object_info(obj, pos) if not info: return - if not 'Edge' in info["Component"]: + if not "Edge" in info["Component"]: return edgeIndex = int(info["Component"][4:]) @@ -214,9 +210,8 @@ class DraftBSplineGuiTools(DraftWireGuiTools): edit_command.ghost.update(pointList) def add_point(self, edit_command, obj, pos): - """Add point to obj. - """ - info, global_pt = edit_command.get_specific_object_info(obj,pos) + """Add point to obj.""" + info, global_pt = edit_command.get_specific_object_info(obj, pos) pt = edit_command.localize_vector(obj, global_pt) if not info or (pt is None): @@ -231,7 +226,7 @@ class DraftBSplineGuiTools(DraftWireGuiTools): uPoints = curve.getKnots() for i in range(len(uPoints) - 1): - if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ): + if (uNewPoint > uPoints[i]) and (uNewPoint < uPoints[i + 1]): pts.insert(i + 1, pt) break # DNC: fix: add points to last segment if curve is closed @@ -264,9 +259,9 @@ class DraftRectangleGuiTools(GuiTools): if node_idx == 0: obj.Placement.Base = obj.Placement.multVec(v) elif node_idx == 1: - obj.Length = DraftVecUtils.project(v, App.Vector(1,0,0)).Length + obj.Length = DraftVecUtils.project(v, App.Vector(1, 0, 0)).Length elif node_idx == 2: - obj.Height = DraftVecUtils.project(v, App.Vector(0,1,0)).Length + obj.Height = DraftVecUtils.project(v, App.Vector(0, 1, 0)).Length class DraftCircleGuiTools(GuiTools): @@ -291,12 +286,12 @@ class DraftCircleGuiTools(GuiTools): editpoints.append(App.Vector(0, 0, 0)) if obj.FirstAngle == obj.LastAngle: # obj is a circle - editpoints.append(App.Vector(obj.Radius,0,0)) + editpoints.append(App.Vector(obj.Radius, 0, 0)) else: # obj is an arc - editpoints.append(self.getArcStart(obj))#First endpoint - editpoints.append(self.getArcEnd(obj))#Second endpoint - editpoints.append(self.getArcMid(obj))#Midpoint + editpoints.append(self.getArcStart(obj)) # First endpoint + editpoints.append(self.getArcEnd(obj)) # Second endpoint + editpoints.append(self.getArcMid(obj)) # Midpoint return editpoints def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): @@ -311,6 +306,7 @@ class DraftCircleGuiTools(GuiTools): # obj is an arc if alt_edit_mode == 0: import Part + if node_idx == 0: # center point p1 = self.getArcStart(obj) @@ -322,9 +318,8 @@ class DraftCircleGuiTools(GuiTools): obj.Placement.Base = obj.Placement.multVec(p0) else: - """ Edit arc by 3 points. - """ - v= obj.Placement.multVec(v) + """Edit arc by 3 points.""" + v = obj.Placement.multVec(v) p1 = obj.Placement.multVec(self.getArcStart(obj)) p2 = obj.Placement.multVec(self.getArcMid(obj)) p3 = obj.Placement.multVec(self.getArcEnd(obj)) @@ -336,8 +331,9 @@ class DraftCircleGuiTools(GuiTools): elif node_idx == 2: # second point p3 = v - arc=Part.ArcOfCircle(p1, p2, p3) + arc = Part.ArcOfCircle(p1, p2, p3) import Part + s = arc.toShape() # Part.show(s) DEBUG p0 = arc.Location @@ -354,7 +350,7 @@ class DraftCircleGuiTools(GuiTools): if node_idx == 0: obj.Placement.Base = obj.Placement.multVec(v) else: - dangle = math.degrees(math.atan2(v[1],v[0])) + dangle = math.degrees(math.atan2(v[1], v[0])) if node_idx == 1: obj.FirstAngle = dangle elif node_idx == 2: @@ -362,25 +358,36 @@ class DraftCircleGuiTools(GuiTools): elif node_idx == 3: obj.Radius = v.Length - def get_edit_point_context_menu(self, edit_command, obj, node_idx): actions = None if obj.FirstAngle != obj.LastAngle: if node_idx == 0: # user is over arc start point return [ - (translate("draft", "Move Arc"), lambda: self.handle_move_arc(edit_command, obj, node_idx)), + ( + translate("draft", "Move Arc"), + lambda: self.handle_move_arc(edit_command, obj, node_idx), + ), ] elif node_idx == 1: # user is over arc start point return [ - (translate("draft", "Set First Angle"), lambda: self.handle_set_first_angle(edit_command, obj, node_idx)), + ( + translate("draft", "Set First Angle"), + lambda: self.handle_set_first_angle(edit_command, obj, node_idx), + ), ] elif node_idx == 2: # user is over arc end point return [ - (translate("draft", "Set Last Angle"), lambda: self.handle_set_last_angle(edit_command, obj, node_idx)), + ( + translate("draft", "Set Last Angle"), + lambda: self.handle_set_last_angle(edit_command, obj, node_idx), + ), ] elif node_idx == 3: # user is over arc mid point return [ - (translate("draft", "Set Radius"), lambda: self.handle_set_radius(edit_command, obj, node_idx)), + ( + translate("draft", "Set Radius"), + lambda: self.handle_set_radius(edit_command, obj, node_idx), + ), ] def handle_move_arc(self, edit_command, obj, node_idx): @@ -429,9 +436,13 @@ class DraftCircleGuiTools(GuiTools): # center point p1 = edit_command.localize_vector(obj, obj.Shape.Vertexes[0].Point) p2 = edit_command.localize_vector(obj, obj.Shape.Vertexes[1].Point) - p0 = DraftVecUtils.project(edit_command.localize_vector(obj, v), - edit_command.localize_vector(obj, (self.getArcMid(obj, global_placement=True)))) - edit_command.ghost.autoinvert=False + p0 = DraftVecUtils.project( + edit_command.localize_vector(obj, v), + edit_command.localize_vector( + obj, (self.getArcMid(obj, global_placement=True)) + ), + ) + edit_command.ghost.autoinvert = False edit_command.ghost.setRadius(p1.sub(p0).Length) edit_command.ghost.setStartPoint(obj.Shape.Vertexes[1].Point) edit_command.ghost.setEndPoint(obj.Shape.Vertexes[0].Point) @@ -442,12 +453,12 @@ class DraftCircleGuiTools(GuiTools): p2 = self.getArcMid(obj, global_placement=True) p3 = self.getArcEnd(obj, global_placement=True) if node_idx == 1: - p1=v + p1 = v elif node_idx == 3: - p2=v + p2 = v elif node_idx == 2: - p3=v - edit_command.ghost.setBy3Points(p1,p2,p3) + p3 = v + edit_command.ghost.setBy3Points(p1, p2, p3) elif edit_command.alt_edit_mode == 1: # edit by center radius angles edit_command.ghost.setStartAngle(math.radians(obj.FirstAngle)) @@ -461,27 +472,23 @@ class DraftCircleGuiTools(GuiTools): elif node_idx == 3: edit_command.ghost.setRadius(edit_command.localize_vector(obj, v).Length) - - def getArcStart(self, obj, global_placement=False):#Returns object midpoint + def getArcStart(self, obj, global_placement=False): # Returns object midpoint if utils.get_type(obj) == "Circle": return self.pointOnCircle(obj, obj.FirstAngle, global_placement) - - def getArcEnd(self, obj, global_placement=False):#Returns object midpoint + def getArcEnd(self, obj, global_placement=False): # Returns object midpoint if utils.get_type(obj) == "Circle": return self.pointOnCircle(obj, obj.LastAngle, global_placement) - - def getArcMid(self, obj, global_placement=False):#Returns object midpoint + def getArcMid(self, obj, global_placement=False): # Returns object midpoint if utils.get_type(obj) == "Circle": if obj.LastAngle > obj.FirstAngle: midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0 else: midAngle = obj.FirstAngle + (obj.LastAngle - obj.FirstAngle) / 2.0 - midAngle += App.Units.Quantity(180,App.Units.Angle) + midAngle += App.Units.Quantity(180, App.Units.Angle) return self.pointOnCircle(obj, midAngle, global_placement) - def pointOnCircle(self, obj, angle, global_placement=False): if utils.get_type(obj) == "Circle": px = obj.Radius * math.cos(math.radians(angle)) @@ -492,7 +499,6 @@ class DraftCircleGuiTools(GuiTools): return p return None - def arcInvert(self, obj): obj.FirstAngle, obj.LastAngle = obj.LastAngle, obj.FirstAngle obj.recompute() @@ -533,12 +539,14 @@ class DraftPolygonGuiTools(GuiTools): def get_edit_points(self, obj): editpoints = [] editpoints.append(App.Vector(0, 0, 0)) - if obj.DrawMode == 'inscribed': + if obj.DrawMode == "inscribed": editpoints.append(obj.Placement.inverse().multVec(obj.Shape.Vertexes[0].Point)) else: - editpoints.append(obj.Placement.inverse().multVec((obj.Shape.Vertexes[0].Point + - obj.Shape.Vertexes[1].Point) / 2 - )) + editpoints.append( + obj.Placement.inverse().multVec( + (obj.Shape.Vertexes[0].Point + obj.Shape.Vertexes[1].Point) / 2 + ) + ) return editpoints def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): @@ -589,13 +597,15 @@ class DraftLabelGuiTools(GuiTools): # If StraightDistance == 0.0, editpoint 1 is exactly on editpoint 0 => Move slightly editpoint 1 to allow selection of editpoint 0 editpoints[1] = 0.9 * editpoints[1] + 0.1 * editpoints[2] else: - pass # TODO : support custom direction with any number of points + pass # TODO : support custom direction with any number of points return editpoints def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): if obj.StraightDirection != "Custom": if node_idx == 0: - vector_p1_p2 = obj.Placement.inverse().multVec(obj.Points[1]) - obj.Placement.inverse().multVec(v) + vector_p1_p2 = obj.Placement.inverse().multVec( + obj.Points[1] + ) - obj.Placement.inverse().multVec(v) if obj.StraightDirection == "Horizontal": if round(vector_p1_p2.y, utils.precision()) == 0.0: obj.StraightDistance = vector_p1_p2.x @@ -604,7 +614,9 @@ class DraftLabelGuiTools(GuiTools): obj.StraightDistance = vector_p1_p2.y obj.Placement.Base = v elif node_idx == 1: - vector_p1_p2 = obj.Placement.inverse().multVec(v) - obj.Placement.inverse().multVec(obj.Placement.Base) + vector_p1_p2 = obj.Placement.inverse().multVec(v) - obj.Placement.inverse().multVec( + obj.Placement.Base + ) if obj.StraightDirection == "Horizontal": if round(vector_p1_p2.y, utils.precision()) == 0.0: obj.StraightDistance = vector_p1_p2.x @@ -618,7 +630,7 @@ class DraftLabelGuiTools(GuiTools): elif node_idx == 2: obj.TargetPoint = v else: - pass # TODO : support custom direction with any number of points + pass # TODO : support custom direction with any number of points class DraftBezCurveGuiTools(GuiTools): @@ -626,25 +638,25 @@ class DraftBezCurveGuiTools(GuiTools): def __init__(self): pass - def get_edit_points(self, obj): editpoints = [] for p in obj.Points: editpoints.append(p) return editpoints - def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): pts = obj.Points # DNC: check for coincident startpoint/endpoint to auto close the curve tol = 0.001 - if ( ( node_idx == 0 ) and ( (v - pts[-1]).Length < tol) ) or ( - node_idx == len(pts) - 1 ) and ( (v - pts[0]).Length < tol): + if ( + ((node_idx == 0) and ((v - pts[-1]).Length < tol)) + or (node_idx == len(pts) - 1) + and ((v - pts[0]).Length < tol) + ): obj.Closed = True # DNC: checks if point enter is equal to other, this could cause a OCC problem if v in pts: - _err = translate("draft", "This object does not support possible " - "coincident points") + _err = translate("draft", "This object does not support possible " "coincident points") App.Console.PrintMessage(_err + "\n") return @@ -652,20 +664,25 @@ class DraftBezCurveGuiTools(GuiTools): if obj.Closed: # check that the new point lies on the plane of the wire - if hasattr(obj.Shape,"normalAt"): - normal = obj.Shape.normalAt(0,0) + if hasattr(obj.Shape, "normalAt"): + normal = obj.Shape.normalAt(0, 0) point_on_plane = obj.Shape.Vertexes[0].Point v.projectToPlane(point_on_plane, normal) pts[node_idx] = v obj.Points = pts - def get_edit_point_context_menu(self, edit_command, obj, node_idx): return [ (translate("draft", "Delete Point"), lambda: self.delete_point(obj, node_idx)), (translate("draft", "Make Sharp"), lambda: self.smoothBezPoint(obj, node_idx, "Sharp")), - (translate("draft", "Make Tangent"), lambda: self.smoothBezPoint(obj, node_idx, "Tangent")), - (translate("draft", "Make Symmetric"), lambda: self.smoothBezPoint(obj, node_idx, "Symmetric")), + ( + translate("draft", "Make Tangent"), + lambda: self.smoothBezPoint(obj, node_idx, "Tangent"), + ), + ( + translate("draft", "Make Symmetric"), + lambda: self.smoothBezPoint(obj, node_idx, "Symmetric"), + ), ] def get_edit_obj_context_menu(self, edit_command, obj, position): @@ -686,74 +703,75 @@ class DraftBezCurveGuiTools(GuiTools): def update_preview_object(self, edit_command, obj, node_idx, v): plist = edit_command.globalize_vectors(obj, obj.Points) - pointList = self.recomputePointsBezier(obj,plist,node_idx,v,obj.Degree,moveTrackers=False) + pointList = self.recomputePointsBezier( + obj, plist, node_idx, v, obj.Degree, moveTrackers=False + ) edit_command.ghost.update(pointList, obj.Degree) - def recomputePointsBezier(self, obj, pts, idx, v, - degree, moveTrackers=False): + def recomputePointsBezier(self, obj, pts, idx, v, degree, moveTrackers=False): """ (object, Points as list, nodeIndex as Int, App.Vector of new point, moveTrackers as Bool) return the new point list, applying the App.Vector to the given index point """ # DNC: allows one to close the curve by placing ends close to each other tol = 0.001 - if ( ( idx == 0 ) and ( (v - pts[-1]).Length < tol) ) or ( - idx == len(pts) - 1 ) and ( (v - pts[0]).Length < tol): + if ( + ((idx == 0) and ((v - pts[-1]).Length < tol)) + or (idx == len(pts) - 1) + and ((v - pts[0]).Length < tol) + ): obj.Closed = True # DNC: fix error message if edited point coincides with one of the existing points - #if ( v in pts ) == False: + # if ( v in pts ) == False: knot = None ispole = idx % degree - if ispole == 0: #knot + if ispole == 0: # knot if degree >= 3: - if idx >= 1: #move left pole + if idx >= 1: # move left pole knotidx = idx if idx < len(pts) else 0 - pts[idx-1] = pts[idx-1] + v - pts[knotidx] - #if moveTrackers: # trackers are reset after editing + pts[idx - 1] = pts[idx - 1] + v - pts[knotidx] + # if moveTrackers: # trackers are reset after editing # self.trackers[obj.Name][idx-1].set(pts[idx-1]) - if idx < len(pts)-1: #move right pole - pts[idx+1] = pts[idx+1] + v - pts[idx] - #if moveTrackers: + if idx < len(pts) - 1: # move right pole + pts[idx + 1] = pts[idx + 1] + v - pts[idx] + # if moveTrackers: # self.trackers[obj.Name][idx+1].set(pts[idx+1]) - if idx == 0 and obj.Closed: # move last pole - pts[-1] = pts [-1] + v -pts[idx] - #if moveTrackers: + if idx == 0 and obj.Closed: # move last pole + pts[-1] = pts[-1] + v - pts[idx] + # if moveTrackers: # self.trackers[obj.Name][-1].set(pts[-1]) - elif ispole == 1 and (idx >=2 or obj.Closed): #right pole - knot = idx -1 + elif ispole == 1 and (idx >= 2 or obj.Closed): # right pole + knot = idx - 1 changep = idx - 2 # -1 in case of closed curve - elif ispole == degree-1 and idx <= len(pts)-3: # left pole + elif ispole == degree - 1 and idx <= len(pts) - 3: # left pole knot = idx + 1 changep = idx + 2 - elif ispole == degree-1 and obj.Closed and idx == len(pts)-1: #last pole + elif ispole == degree - 1 and obj.Closed and idx == len(pts) - 1: # last pole knot = 0 changep = 1 if knot is not None: # we need to modify the opposite pole segment = int(knot / degree) - 1 cont = obj.Continuity[segment] if len(obj.Continuity) > segment else 0 - if cont == 1: #tangent - pts[changep] = obj.Proxy.modifytangentpole(pts[knot], - v,pts[changep]) - #if moveTrackers: + if cont == 1: # tangent + pts[changep] = obj.Proxy.modifytangentpole(pts[knot], v, pts[changep]) + # if moveTrackers: # self.trackers[obj.Name][changep].set(pts[changep]) - elif cont == 2: #symmetric - pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot],v) - #if moveTrackers: + elif cont == 2: # symmetric + pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot], v) + # if moveTrackers: # self.trackers[obj.Name][changep].set(pts[changep]) pts[idx] = v return pts # returns the list of new points, taking into account knot continuity - - def smoothBezPoint(self, obj, point, style='Symmetric'): - """called when changing the continuity of a knot - """ - style2cont = {'Sharp':0,'Tangent':1,'Symmetric':2} + def smoothBezPoint(self, obj, point, style="Symmetric"): + """called when changing the continuity of a knot""" + style2cont = {"Sharp": 0, "Tangent": 1, "Symmetric": 2} if point is None: return if not (utils.get_type(obj) == "BezCurve"): @@ -763,95 +781,96 @@ class DraftBezCurveGuiTools(GuiTools): if deg < 2: return if point % deg != 0: # point is a pole - if deg >=3: # allow one to select poles - if (point % deg == 1) and (point > 2 or obj.Closed): #right pole - knot = point -1 + if deg >= 3: # allow one to select poles + if (point % deg == 1) and (point > 2 or obj.Closed): # right pole + knot = point - 1 keepp = point - changep = point -2 - elif point < len(pts) -3 and point % deg == deg -1: #left pole - knot = point +1 + changep = point - 2 + elif point < len(pts) - 3 and point % deg == deg - 1: # left pole + knot = point + 1 keepp = point - changep = point +2 - elif point == len(pts)-1 and obj.Closed: #last pole + changep = point + 2 + elif point == len(pts) - 1 and obj.Closed: # last pole # if the curve is closed the last pole has the last # index in the points lists knot = 0 keepp = point changep = 1 else: - App.Console.PrintWarning(translate("draft", - "Cannot change knot belonging to pole %d"%point) - + "\n") + App.Console.PrintWarning( + translate("draft", "Cannot change knot belonging to pole %d" % point) + "\n" + ) return if knot: - if style == 'Tangent': - pts[changep] = obj.Proxy.modifytangentpole(pts[knot], - pts[keepp],pts[changep]) - elif style == 'Symmetric': - pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot], - pts[keepp]) - else: #sharp - pass # + if style == "Tangent": + pts[changep] = obj.Proxy.modifytangentpole( + pts[knot], pts[keepp], pts[changep] + ) + elif style == "Symmetric": + pts[changep] = obj.Proxy.modifysymmetricpole(pts[knot], pts[keepp]) + else: # sharp + pass # else: - App.Console.PrintWarning(translate("draft", - "Selection is not a knot") - + "\n") + App.Console.PrintWarning(translate("draft", "Selection is not a knot") + "\n") return - else: #point is a knot - if style == 'Sharp': - if obj.Closed and point == len(pts)-1: + else: # point is a knot + if style == "Sharp": + if obj.Closed and point == len(pts) - 1: knot = 0 else: knot = point - elif style == 'Tangent' and point > 0 and point < len(pts)-1: - prev, next = obj.Proxy.tangentpoles(pts[point], pts[point-1], pts[point+1]) - pts[point-1] = prev - pts[point+1] = next + elif style == "Tangent" and point > 0 and point < len(pts) - 1: + prev, next = obj.Proxy.tangentpoles(pts[point], pts[point - 1], pts[point + 1]) + pts[point - 1] = prev + pts[point + 1] = next knot = point # index for continuity - elif style == 'Symmetric' and point > 0 and point < len(pts)-1: - prev, next = obj.Proxy.symmetricpoles(pts[point], pts[point-1], pts[point+1]) - pts[point-1] = prev - pts[point+1] = next + elif style == "Symmetric" and point > 0 and point < len(pts) - 1: + prev, next = obj.Proxy.symmetricpoles(pts[point], pts[point - 1], pts[point + 1]) + pts[point - 1] = prev + pts[point + 1] = next knot = point # index for continuity - elif obj.Closed and (style == 'Symmetric' or style == 'Tangent'): - if style == 'Tangent': + elif obj.Closed and (style == "Symmetric" or style == "Tangent"): + if style == "Tangent": pts[1], pts[-1] = obj.Proxy.tangentpoles(pts[0], pts[1], pts[-1]) - elif style == 'Symmetric': + elif style == "Symmetric": pts[1], pts[-1] = obj.Proxy.symmetricpoles(pts[0], pts[1], pts[-1]) knot = 0 else: - App.Console.PrintWarning(translate("draft", - "Endpoint of Bézier curve cannot be smoothed") - + "\n") + App.Console.PrintWarning( + translate("draft", "Endpoint of Bézier curve cannot be smoothed") + "\n" + ) return segment = knot // deg # segment index newcont = obj.Continuity[:] # don't edit a property inplace !!! - if not obj.Closed and (len(obj.Continuity) == segment -1 or - segment == 0) : - pass # open curve - elif (len(obj.Continuity) >= segment or obj.Closed and segment == 0 and - len(obj.Continuity) >1): - newcont[segment-1] = style2cont.get(style) - else: #should not happen - App.Console.PrintWarning('Continuity indexing error:' - + 'point:%d deg:%d len(cont):%d' % (knot,deg, - len(obj.Continuity))) + if not obj.Closed and (len(obj.Continuity) == segment - 1 or segment == 0): + pass # open curve + elif ( + len(obj.Continuity) >= segment + or obj.Closed + and segment == 0 + and len(obj.Continuity) > 1 + ): + newcont[segment - 1] = style2cont.get(style) + else: # should not happen + App.Console.PrintWarning( + "Continuity indexing error:" + + "point:%d deg:%d len(cont):%d" % (knot, deg, len(obj.Continuity)) + ) obj.Points = pts obj.Continuity = newcont def add_point(self, edit_command, obj, pos): - """Add point to obj and reset trackers. - """ - info, pt = edit_command.get_specific_object_info(obj,pos) + """Add point to obj and reset trackers.""" + info, pt = edit_command.get_specific_object_info(obj, pos) if not info or (pt is None): return import Part pts = obj.Points - if not info['Component'].startswith('Edge'): + if not info["Component"].startswith("Edge"): return # clicked control point - edgeindex = int(info['Component'].lstrip('Edge')) - 1 + edgeindex = int(info["Component"].lstrip("Edge")) - 1 wire = obj.Shape.Wires[0] bz = wire.Edges[edgeindex].Curve param = bz.parameter(pt) @@ -861,11 +880,14 @@ class DraftBezCurveGuiTools(GuiTools): seg2.segment(param, seg2.LastParameter) if edgeindex == len(wire.Edges): # we hit the last segment, we need to fix the degree - degree=wire.Edges[0].Curve.Degree + degree = wire.Edges[0].Curve.Degree seg1.increase(degree) seg2.increase(degree) - edges = wire.Edges[0:edgeindex] + [Part.Edge(seg1),Part.Edge(seg2)] \ - + wire.Edges[edgeindex + 1:] + edges = ( + wire.Edges[0:edgeindex] + + [Part.Edge(seg1), Part.Edge(seg2)] + + wire.Edges[edgeindex + 1 :] + ) pts = edges[0].Curve.getPoles()[0:1] for edge in edges: pts.extend(edge.Curve.getPoles()[1:]) @@ -900,4 +922,5 @@ class DraftBezCurveGuiTools(GuiTools): obj.Points = reversed(obj.Points) obj.recompute() + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit_part_objects.py b/src/Mod/Draft/draftguitools/gui_edit_part_objects.py index 7433cf3869..5d0eed7bbc 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_part_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_part_objects.py @@ -24,8 +24,9 @@ # \brief Provides support functions to edit Part objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Carlo Pavan") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Carlo Pavan" +) __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -43,8 +44,8 @@ class PartLineGuiTools(GuiTools): def get_edit_points(self, obj): editpoints = [] - editpoints.append(App.Vector(obj.X1,obj.Y1,obj.Z1)) - editpoints.append(App.Vector(obj.X2,obj.Y2,obj.Z2)) + editpoints.append(App.Vector(obj.X1, obj.Y1, obj.Z1)) + editpoints.append(App.Vector(obj.X2, obj.Y2, obj.Z2)) return editpoints def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): @@ -125,11 +126,11 @@ class PartConeGuiTools(GuiTools): if node_idx == 0: obj.Placement.Base = obj.Placement.Base + v elif node_idx == 1: - obj.Radius1 = v.Length # TODO: Perhaps better to project on the face? + obj.Radius1 = v.Length # TODO: Perhaps better to project on the face? elif node_idx == 2: v.z = 0 - obj.Radius2 = v.Length # TODO: Perhaps better to project on the face? - elif node_idx == 3: # Height is last to have the priority on the radius + obj.Radius2 = v.Length # TODO: Perhaps better to project on the face? + elif node_idx == 3: # Height is last to have the priority on the radius _vector = DraftVecUtils.project(v, App.Vector(0, 0, 1)) obj.Height = _vector.Length @@ -150,6 +151,7 @@ class PartSphereGuiTools(GuiTools): obj.Placement.Base = obj.Placement.Base + v elif node_idx == 1: if v.Length > 0.0: - obj.Radius = v.Length # TODO: Perhaps better to project on the face? + obj.Radius = v.Length # TODO: Perhaps better to project on the face? + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_edit_sketcher_objects.py b/src/Mod/Draft/draftguitools/gui_edit_sketcher_objects.py index 620432e0f3..7b1ecea7da 100644 --- a/src/Mod/Draft/draftguitools/gui_edit_sketcher_objects.py +++ b/src/Mod/Draft/draftguitools/gui_edit_sketcher_objects.py @@ -26,8 +26,9 @@ # \brief Provides support functions to edit Sketch objects. __title__ = "FreeCAD Draft Edit Tool" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin, Carlo Pavan") +__author__ = ( + "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin, Carlo Pavan" +) __url__ = "https://www.freecad.org" ## \addtogroup draftguitools @@ -50,16 +51,22 @@ class SketcherSketchObjectGuiTools(GuiTools): 1 : endpoint """ import Part + editpoints = [] - if (obj.ConstraintCount == 0 - and obj.GeometryCount == 1 - and type(obj.Geometry[0]) == Part.LineSegment): - editpoints.append(obj.getPoint(0,1)) - editpoints.append(obj.getPoint(0,2)) + if ( + obj.ConstraintCount == 0 + and obj.GeometryCount == 1 + and type(obj.Geometry[0]) == Part.LineSegment + ): + editpoints.append(obj.getPoint(0, 1)) + editpoints.append(obj.getPoint(0, 2)) return editpoints else: - _wrn = translate("draft", "Sketch is too complex to edit: " - "it is suggested to use the default Sketcher editor") + _wrn = translate( + "draft", + "Sketch is too complex to edit: " + "it is suggested to use the default Sketcher editor", + ) App.Console.PrintWarning(_wrn + "\n") return None @@ -79,4 +86,5 @@ class SketcherSketchObjectGuiTools(GuiTools): obj.Geometry = [line] obj.recompute() + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_ellipses.py b/src/Mod/Draft/draftguitools/gui_ellipses.py index ded39d51ea..8a198eba6b 100644 --- a/src/Mod/Draft/draftguitools/gui_ellipses.py +++ b/src/Mod/Draft/draftguitools/gui_ellipses.py @@ -54,10 +54,12 @@ class Ellipse(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Ellipse', - 'Accel': "E, L", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Ellipse", "Ellipse"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Ellipse", "Creates an ellipse")} + return { + "Pixmap": "Draft_Ellipse", + "Accel": "E, L", + "MenuText": QT_TRANSLATE_NOOP("Draft_Ellipse", "Ellipse"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Ellipse", "Creates an ellipse"), + } def Activated(self): """Execute when the command is called.""" @@ -96,8 +98,8 @@ class Ellipse(gui_base_original.Creator): center = p1.add(halfdiag) p2 = p1.add(DraftVecUtils.project(diagonal, self.wp.v)) p4 = p1.add(DraftVecUtils.project(diagonal, self.wp.u)) - r1 = (p4.sub(p1).Length)/2 - r2 = (p2.sub(p1).Length)/2 + r1 = (p4.sub(p1).Length) / 2 + r2 = (p2.sub(p1).Length) / 2 try: # The command to run is built as a series of text strings # to be committed through the `draftutils.todo.ToDo` class. @@ -105,7 +107,7 @@ class Ellipse(gui_base_original.Creator): if r2 > r1: r1, r2 = r2, r1 m = App.Matrix() - m.rotateZ(math.pi/2) + m.rotateZ(math.pi / 2) rot1 = App.Rotation() rot1.Q = eval(rot) rot2 = App.Placement(m) @@ -114,37 +116,39 @@ class Ellipse(gui_base_original.Creator): Gui.addModule("Draft") if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Ellipse", "Ellipse")' - _cmd_list = ['ellipse = ' + _cmd, - 'ellipse.MajorRadius = ' + str(r1), - 'ellipse.MinorRadius = ' + str(r2), - 'pl = FreeCAD.Placement()', - 'pl.Rotation.Q= ' + rot, - 'pl.Base = ' + DraftVecUtils.toString(center), - 'ellipse.Placement = pl', - 'Draft.autogroup(ellipse)', - 'Draft.select(ellipse)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Ellipse"), - _cmd_list) + _cmd_list = [ + "ellipse = " + _cmd, + "ellipse.MajorRadius = " + str(r1), + "ellipse.MinorRadius = " + str(r2), + "pl = FreeCAD.Placement()", + "pl.Rotation.Q= " + rot, + "pl.Base = " + DraftVecUtils.toString(center), + "ellipse.Placement = pl", + "Draft.autogroup(ellipse)", + "Draft.select(ellipse)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Ellipse"), _cmd_list) else: # Insert a Draft ellipse - _cmd = 'Draft.make_ellipse' - _cmd += '(' - _cmd += str(r1) + ', ' + str(r2) + ', ' - _cmd += 'placement=pl, ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + DraftVecUtils.toString(center), - 'ellipse = ' + _cmd, - 'Draft.autogroup(ellipse)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Ellipse"), - _cmd_list) + _cmd = "Draft.make_ellipse" + _cmd += "(" + _cmd += str(r1) + ", " + str(r2) + ", " + _cmd += "placement=pl, " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + DraftVecUtils.toString(center), + "ellipse = " + _cmd, + "Draft.autogroup(ellipse)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Ellipse"), _cmd_list) except Exception: _err("Draft: Error: Unable to create object.") self.finish(cont=None) @@ -217,12 +221,14 @@ class Ellipse(gui_base_original.Creator): hints = [ Gui.InputHint(translate("draft", "%1 pick opposite point"), Gui.UserInput.MouseLeft) ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Ellipse', Ellipse()) +Gui.addCommand("Draft_Ellipse", Ellipse()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_facebinders.py b/src/Mod/Draft/draftguitools/gui_facebinders.py index 0b2f1f0e20..94a55b4fc4 100644 --- a/src/Mod/Draft/draftguitools/gui_facebinders.py +++ b/src/Mod/Draft/draftguitools/gui_facebinders.py @@ -55,10 +55,14 @@ class Facebinder(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Facebinder", - "Accel": "F,F", - "MenuText": QT_TRANSLATE_NOOP("Draft_Facebinder", "Facebinder"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Facebinder", "Creates a facebinder from the selected faces")} + return { + "Pixmap": "Draft_Facebinder", + "Accel": "F,F", + "MenuText": QT_TRANSLATE_NOOP("Draft_Facebinder", "Facebinder"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Facebinder", "Creates a facebinder from the selected faces" + ), + } def Activated(self): """Execute when the command is called.""" diff --git a/src/Mod/Draft/draftguitools/gui_fillets.py b/src/Mod/Draft/draftguitools/gui_fillets.py index 3624acbfcf..ed788ef3da 100644 --- a/src/Mod/Draft/draftguitools/gui_fillets.py +++ b/src/Mod/Draft/draftguitools/gui_fillets.py @@ -64,10 +64,14 @@ class Fillet(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Fillet", - "Accel": "F,I", - "MenuText": QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Fillet", "Creates a fillet between 2 selected edges")} + return { + "Pixmap": "Draft_Fillet", + "Accel": "F,I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Fillet", "Fillet"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Fillet", "Creates a fillet between 2 selected edges" + ), + } def Activated(self, name="Fillet"): """Execute when the command is called.""" @@ -87,23 +91,21 @@ class Fillet(gui_base_original.Creator): self.ui.radiusValue.setToolTip(tooltip) self.ui.radius = params.get_param("FilletRadius") self.ui.setRadiusValue(self.ui.radius, "Length") - self.ui.check_delete = self.ui._checkbox("isdelete", - self.ui.layout, - checked=self.delete) - self.ui.check_delete.setText(translate("Draft", - "Delete original objects")) + self.ui.check_delete = self.ui._checkbox( + "isdelete", self.ui.layout, checked=self.delete + ) + self.ui.check_delete.setText(translate("Draft", "Delete original objects")) self.ui.check_delete.show() - self.ui.check_chamfer = self.ui._checkbox("ischamfer", - self.ui.layout, - checked=self.chamfer) - self.ui.check_chamfer.setText(translate("Draft", - "Create chamfer")) + self.ui.check_chamfer = self.ui._checkbox( + "ischamfer", self.ui.layout, checked=self.chamfer + ) + self.ui.check_chamfer.setText(translate("Draft", "Create chamfer")) self.ui.check_chamfer.show() - if hasattr(self.ui.check_delete, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.ui.check_delete, "checkStateChanged"): # Qt version >= 6.7.0 self.ui.check_delete.checkStateChanged.connect(self.set_delete) self.ui.check_chamfer.checkStateChanged.connect(self.set_chamfer) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.ui.check_delete.stateChanged.connect(self.set_delete) self.ui.check_chamfer.stateChanged.connect(self.set_chamfer) @@ -163,15 +165,17 @@ class Fillet(gui_base_original.Creator): if delete: cmd += ", delete=True" cmd += ")" - cmd_list = ["sels = FreeCADGui.Selection.getSelectionEx('', 0)", - "fillet = " + cmd, - "Draft.autogroup(fillet)", - "FreeCAD.ActiveDocument.recompute()"] + cmd_list = [ + "sels = FreeCADGui.Selection.getSelectionEx('', 0)", + "fillet = " + cmd, + "Draft.autogroup(fillet)", + "FreeCAD.ActiveDocument.recompute()", + ] self.commit(translate("draft", "Create Fillet"), cmd_list) self.finish() -Gui.addCommand('Draft_Fillet', Fillet()) +Gui.addCommand("Draft_Fillet", Fillet()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_grid.py b/src/Mod/Draft/draftguitools/gui_grid.py index f3459fcb83..9d6db4daf6 100644 --- a/src/Mod/Draft/draftguitools/gui_grid.py +++ b/src/Mod/Draft/draftguitools/gui_grid.py @@ -55,12 +55,15 @@ class ToggleGrid(gui_base.GuiCommandSimplest): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Grid", - "Accel": "G, R", - "MenuText": QT_TRANSLATE_NOOP("Draft_ToggleGrid", "Toggle Grid"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ToggleGrid", - "Toggles the visibility of the Draft grid"), - "CmdType": "ForEdit"} + return { + "Pixmap": "Draft_Grid", + "Accel": "G, R", + "MenuText": QT_TRANSLATE_NOOP("Draft_ToggleGrid", "Toggle Grid"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ToggleGrid", "Toggles the visibility of the Draft grid" + ), + "CmdType": "ForEdit", + } def IsActive(self): """Return True when this command should be available.""" @@ -90,6 +93,7 @@ class ToggleGrid(gui_base.GuiCommandSimplest): WorkingPlane.get_working_plane() grid.show_always = True + Gui.addCommand("Draft_ToggleGrid", ToggleGrid()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_groups.py b/src/Mod/Draft/draftguitools/gui_groups.py index 920f922de6..41f0035cd7 100644 --- a/src/Mod/Draft/draftguitools/gui_groups.py +++ b/src/Mod/Draft/draftguitools/gui_groups.py @@ -69,9 +69,14 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_AddToGroup", - "MenuText": QT_TRANSLATE_NOOP("Draft_AddToGroup", "Add to Group"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_AddToGroup", "Adds selected objects to a group, or removes them from any group")} + return { + "Pixmap": "Draft_AddToGroup", + "MenuText": QT_TRANSLATE_NOOP("Draft_AddToGroup", "Add to Group"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_AddToGroup", + "Adds selected objects to a group, or removes them from any group", + ), + } def Activated(self): """Execute when the command is called.""" @@ -83,19 +88,21 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection): self.ui = Gui.draftToolBar objs = [obj for obj in self.doc.Objects if groups.is_group(obj)] objs.sort(key=lambda obj: obj.Label) - self.objects = [None] \ - + [None] \ - + objs - self.labels = [translate("draft", "Ungroup")] \ - + ["---"] \ - + [obj.Label for obj in objs] \ - + ["---"] \ - + [translate("draft", "Add to New Group")] - self.icons = [self.ui.getIcon(":/icons/list-remove.svg")] \ - + [None] \ - + [obj.ViewObject.Icon for obj in objs] \ - + [None] \ - + [self.ui.getIcon(":/icons/list-add.svg")] + self.objects = [None] + [None] + objs + self.labels = ( + [translate("draft", "Ungroup")] + + ["---"] + + [obj.Label for obj in objs] + + ["---"] + + [translate("draft", "Add to New Group")] + ) + self.icons = ( + [self.ui.getIcon(":/icons/list-remove.svg")] + + [None] + + [obj.ViewObject.Icon for obj in objs] + + [None] + + [self.ui.getIcon(":/icons/list-add.svg")] + ) # It uses the `DraftToolBar` class defined in the `DraftGui` module and # globally initialized in the `Gui` namespace to pop up a menu. @@ -149,7 +156,7 @@ def moveToGroup(group): for obj in Gui.Selection.getSelection(): try: - #retrieve group's visibility + # retrieve group's visibility obj.ViewObject.Visibility = group.ViewObject.Visibility group.addObject(obj) @@ -165,9 +172,14 @@ class SelectGroup(gui_base.GuiCommandNeedsSelection): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_SelectGroup", - "MenuText": QT_TRANSLATE_NOOP("Draft_SelectGroup", "Select Group"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_SelectGroup", "Selects the contents of selected groups. For selected non-group objects, the contents of the group they are in are selected.")} + return { + "Pixmap": "Draft_SelectGroup", + "MenuText": QT_TRANSLATE_NOOP("Draft_SelectGroup", "Select Group"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_SelectGroup", + "Selects the contents of selected groups. For selected non-group objects, the contents of the group they are in are selected.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -194,7 +206,9 @@ class SelectGroup(gui_base.GuiCommandNeedsSelection): # Inform the user if there is no new selection: if not Gui.Selection.hasSelection(): - msg = translate("draft", "No new selection. Select non-empty groups or objects inside groups.") + msg = translate( + "draft", "No new selection. Select non-empty groups or objects inside groups." + ) App.Console.PrintMessage(msg + "\n") @@ -209,9 +223,13 @@ class SetAutoGroup(gui_base.GuiCommandSimplest): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_AutoGroup", - "MenuText": QT_TRANSLATE_NOOP("Draft_AutoGroup", "Auto-Group"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_AutoGroup", "Adds new Draft and BIM objects to the selected layer or group")} + return { + "Pixmap": "Draft_AutoGroup", + "MenuText": QT_TRANSLATE_NOOP("Draft_AutoGroup", "Auto-Group"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_AutoGroup", "Adds new Draft and BIM objects to the selected layer or group" + ), + } def Activated(self): """Execute when the command is called. @@ -230,9 +248,9 @@ class SetAutoGroup(gui_base.GuiCommandSimplest): self.ui = Gui.draftToolBar sel = Gui.Selection.getSelection() if len(sel) == 1: - if (utils.get_type(sel[0]) == "Layer" - or (params.get_param("AutogroupAddGroups") - and groups.is_group(sel[0]))): + if utils.get_type(sel[0]) == "Layer" or ( + params.get_param("AutogroupAddGroups") and groups.is_group(sel[0]) + ): self.ui.setAutoGroup(sel[0].Name) return @@ -245,30 +263,34 @@ class SetAutoGroup(gui_base.GuiCommandSimplest): grps = [] lyrs = [obj for obj in self.doc.Objects if utils.get_type(obj) == "Layer"] lyrs.sort(key=lambda obj: obj.Label) - self.names = [None] \ - + [None] \ - + [obj.Name for obj in grps] \ - + [None] \ - + [obj.Name for obj in lyrs] - self.labels = [translate("draft", "None")] \ - + ["---"] \ - + [obj.Label for obj in grps] \ - + ["---"] \ - + [obj.Label for obj in lyrs] \ - + ["---"] \ - + [translate("draft", "New Layer")] - self.icons = [self.ui.getIcon(":/icons/button_invalid.svg")] \ - + [None] \ - + [obj.ViewObject.Icon for obj in grps] \ - + [None] \ - + [obj.ViewObject.Icon for obj in lyrs] \ - + [None] \ - + [self.ui.getIcon(":/icons/Draft_NewLayer.svg")] + self.names = ( + [None] + [None] + [obj.Name for obj in grps] + [None] + [obj.Name for obj in lyrs] + ) + self.labels = ( + [translate("draft", "None")] + + ["---"] + + [obj.Label for obj in grps] + + ["---"] + + [obj.Label for obj in lyrs] + + ["---"] + + [translate("draft", "New Layer")] + ) + self.icons = ( + [self.ui.getIcon(":/icons/button_invalid.svg")] + + [None] + + [obj.ViewObject.Icon for obj in grps] + + [None] + + [obj.ViewObject.Icon for obj in lyrs] + + [None] + + [self.ui.getIcon(":/icons/Draft_NewLayer.svg")] + ) # With the created lists it uses the interface to pop up a menu with options. # Once the desired option is chosen it launches the `proceed` method. self.ui.sourceCmd = self - pos = self.ui.autoGroupButton.mapToGlobal(QtCore.QPoint(0, self.ui.autoGroupButton.geometry().height())) + pos = self.ui.autoGroupButton.mapToGlobal( + QtCore.QPoint(0, self.ui.autoGroupButton.geometry().height()) + ) self.ui.popupMenu(self.labels, self.icons, pos) def proceed(self, option): @@ -292,18 +314,24 @@ class SetAutoGroup(gui_base.GuiCommandSimplest): None, translate("draft", "New Layer"), translate("draft", "Layer name"), - text=translate("draft", "Layer", "Object label") + text=translate("draft", "Layer", "Object label"), ) if not ok: return if not txt: return self.doc.openTransaction(translate("draft", "New layer")) - lyr = make_layer.make_layer(name=txt, line_color=None, shape_color=None, - line_width=None, draw_style=None, transparency=None) + lyr = make_layer.make_layer( + name=txt, + line_color=None, + shape_color=None, + line_width=None, + draw_style=None, + transparency=None, + ) self.doc.commitTransaction() self.doc.recompute() - self.ui.setAutoGroup(lyr.Name) # this... + self.ui.setAutoGroup(lyr.Name) # this... # self.ui.autoGroupButton.setDown(False) # or this? return @@ -333,9 +361,14 @@ class AddToConstruction(gui_base.GuiCommandNeedsSelection): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_AddConstruction", - "MenuText": QT_TRANSLATE_NOOP("Draft_AddConstruction", "Add to Construction Group"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_AddConstruction", "Adds the selected objects to the construction group,\nand changes their appearance to the construction style.\nThe construction group is created if it does not exist.")} + return { + "Pixmap": "Draft_AddConstruction", + "MenuText": QT_TRANSLATE_NOOP("Draft_AddConstruction", "Add to Construction Group"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_AddConstruction", + "Adds the selected objects to the construction group,\nand changes their appearance to the construction style.\nThe construction group is created if it does not exist.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -387,9 +420,11 @@ class AddNamedGroup(gui_base.GuiCommandSimplest): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_AddNamedGroup", - "MenuText": QT_TRANSLATE_NOOP("Draft_AddNamedGroup", "New Named Group"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_AddNamedGroup", "Adds a group with a given name")} + return { + "Pixmap": "Draft_AddNamedGroup", + "MenuText": QT_TRANSLATE_NOOP("Draft_AddNamedGroup", "New Named Group"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_AddNamedGroup", "Adds a group with a given name"), + } def Activated(self): super().Activated() @@ -398,7 +433,7 @@ class AddNamedGroup(gui_base.GuiCommandSimplest): None, translate("draft", "New Group"), translate("draft", "Group name"), - text=translate("draft", "Group", "Object label") + text=translate("draft", "Group", "Object label"), ) if not ok: return diff --git a/src/Mod/Draft/draftguitools/gui_hatch.py b/src/Mod/Draft/draftguitools/gui_hatch.py index 4c476ad939..ee2daccaea 100644 --- a/src/Mod/Draft/draftguitools/gui_hatch.py +++ b/src/Mod/Draft/draftguitools/gui_hatch.py @@ -1,24 +1,24 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2021 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * * +# * Copyright (c) 2021 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** """This module contains FreeCAD commands for the Draft workbench""" @@ -33,33 +33,39 @@ from draftutils.translate import QT_TRANSLATE_NOOP, translate class Draft_Hatch(gui_base.GuiCommandNeedsSelection): - def GetResources(self): - return {"Pixmap": "Draft_Hatch", - "MenuText": QT_TRANSLATE_NOOP("Draft_Hatch", "Hatch"), - "Accel": "H, A", - "ToolTip": QT_TRANSLATE_NOOP("Draft_Hatch", "Creates hatches on the faces of a selected object")} + return { + "Pixmap": "Draft_Hatch", + "MenuText": QT_TRANSLATE_NOOP("Draft_Hatch", "Hatch"), + "Accel": "H, A", + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Hatch", "Creates hatches on the faces of a selected object" + ), + } def Activated(self): import FreeCADGui if FreeCADGui.Selection.getSelection(): - task = FreeCADGui.Control.showDialog(Draft_Hatch_TaskPanel(FreeCADGui.Selection.getSelection()[0])) + task = FreeCADGui.Control.showDialog( + Draft_Hatch_TaskPanel(FreeCADGui.Selection.getSelection()[0]) + ) task.setDocumentName(FreeCADGui.ActiveDocument.Document.Name) task.setAutoCloseOnDeletedDocument(True) else: - FreeCAD.Console.PrintError(translate("Draft", "Choose a base object before using this command") + "\n") + FreeCAD.Console.PrintError( + translate("Draft", "Choose a base object before using this command") + "\n" + ) class Draft_Hatch_TaskPanel: - - def __init__(self,baseobj): + def __init__(self, baseobj): import FreeCADGui - from PySide import QtCore,QtGui + from PySide import QtCore, QtGui import Draft_rc self.baseobj = baseobj @@ -84,25 +90,25 @@ class Draft_Hatch_TaskPanel: params.set_param("HatchPatternScale", self.form.Scale.value()) params.set_param("HatchPatternRotation", self.form.Rotation.value()) params.set_param("HatchPatternTranslate", self.form.Translate.isChecked()) - if hasattr(self.baseobj,"File") and hasattr(self.baseobj,"Pattern"): + if hasattr(self.baseobj, "File") and hasattr(self.baseobj, "Pattern"): # modify existing hatch object - o = "FreeCAD.ActiveDocument.getObject(\""+self.baseobj.Name+"\")" - FreeCADGui.doCommand(o+".File=\""+self.form.File.property("fileName")+"\"") - FreeCADGui.doCommand(o+".Pattern=\""+self.form.Pattern.currentText()+"\"") - FreeCADGui.doCommand(o+".Scale="+str(self.form.Scale.value())) - FreeCADGui.doCommand(o+".Rotation="+str(self.form.Rotation.value())) - FreeCADGui.doCommand(o+".Translate="+str(self.form.Translate.isChecked())) + o = 'FreeCAD.ActiveDocument.getObject("' + self.baseobj.Name + '")' + FreeCADGui.doCommand(o + '.File="' + self.form.File.property("fileName") + '"') + FreeCADGui.doCommand(o + '.Pattern="' + self.form.Pattern.currentText() + '"') + FreeCADGui.doCommand(o + ".Scale=" + str(self.form.Scale.value())) + FreeCADGui.doCommand(o + ".Rotation=" + str(self.form.Rotation.value())) + FreeCADGui.doCommand(o + ".Translate=" + str(self.form.Translate.isChecked())) else: # create new hatch object FreeCAD.ActiveDocument.openTransaction("Create Hatch") FreeCADGui.addModule("Draft") cmd = "Draft.make_hatch(" - cmd += "baseobject=FreeCAD.ActiveDocument.getObject(\""+self.baseobj.Name - cmd += "\"),filename=\""+self.form.File.property("fileName") - cmd += "\",pattern=\""+self.form.Pattern.currentText() - cmd += "\",scale="+str(self.form.Scale.value()) - cmd += ",rotation="+str(self.form.Rotation.value()) - cmd += ",translate="+str(self.form.Translate.isChecked())+")" + cmd += 'baseobject=FreeCAD.ActiveDocument.getObject("' + self.baseobj.Name + cmd += '"),filename="' + self.form.File.property("fileName") + cmd += '",pattern="' + self.form.Pattern.currentText() + cmd += '",scale=' + str(self.form.Scale.value()) + cmd += ",rotation=" + str(self.form.Rotation.value()) + cmd += ",translate=" + str(self.form.Translate.isChecked()) + ")" FreeCADGui.doCommand(cmd) FreeCAD.ActiveDocument.commitTransaction() FreeCADGui.doCommand("FreeCAD.ActiveDocument.recompute()") @@ -116,7 +122,7 @@ class Draft_Hatch_TaskPanel: FreeCADGui.ActiveDocument.resetEdit() FreeCAD.ActiveDocument.recompute() - def onFileChanged(self,filename): + def onFileChanged(self, filename): pat = self.form.Pattern.currentText() self.form.Pattern.clear() @@ -125,8 +131,7 @@ class Draft_Hatch_TaskPanel: if pat in patterns: self.form.Pattern.setCurrentText(pat) - def getPatterns(self,filename): - + def getPatterns(self, filename): """returns a list of pattern names found in a PAT file""" patterns = [] if os.path.exists(filename): @@ -136,6 +141,8 @@ class Draft_Hatch_TaskPanel: patterns.append(line.split(",")[0][1:]) return patterns + if FreeCAD.GuiUp: import FreeCADGui - FreeCADGui.addCommand("Draft_Hatch",Draft_Hatch()) + + FreeCADGui.addCommand("Draft_Hatch", Draft_Hatch()) diff --git a/src/Mod/Draft/draftguitools/gui_heal.py b/src/Mod/Draft/draftguitools/gui_heal.py index c4bc68a565..dedb112936 100644 --- a/src/Mod/Draft/draftguitools/gui_heal.py +++ b/src/Mod/Draft/draftguitools/gui_heal.py @@ -48,15 +48,20 @@ class Heal(gui_base.GuiCommandSimplest): """ def __init__(self): - super(Heal, self).__init__(name=translate("draft","Heal")) + super(Heal, self).__init__(name=translate("draft", "Heal")) def GetResources(self): """Set icon, menu and tooltip.""" _tip = () - return {'Pixmap': 'Draft_Heal', - 'MenuText': QT_TRANSLATE_NOOP("Draft_Heal", "Heal"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Heal", "Heals faulty Draft objects saved with an earlier version of FreeCAD.\nIf an object is selected it tries to heal only that object,\notherwise it tries to heal all objects in the active document.")} + return { + "Pixmap": "Draft_Heal", + "MenuText": QT_TRANSLATE_NOOP("Draft_Heal", "Heal"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Heal", + "Heals faulty Draft objects saved with an earlier version of FreeCAD.\nIf an object is selected it tries to heal only that object,\notherwise it tries to heal all objects in the active document.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -71,6 +76,6 @@ class Heal(gui_base.GuiCommandSimplest): self.doc.commitTransaction() -Gui.addCommand('Draft_Heal', Heal()) +Gui.addCommand("Draft_Heal", Heal()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_hyperlink.py b/src/Mod/Draft/draftguitools/gui_hyperlink.py index 7080449aa4..6f6ea46b25 100644 --- a/src/Mod/Draft/draftguitools/gui_hyperlink.py +++ b/src/Mod/Draft/draftguitools/gui_hyperlink.py @@ -38,14 +38,18 @@ if FreeCAD.GuiUp: import Draft_rc from PySide.QtCore import QUrl from PySide.QtGui import QDesktopServices -def QT_TRANSLATE_NOOP(ctx,txt): + + +def QT_TRANSLATE_NOOP(ctx, txt): return txt + + translate = FreeCAD.Qt.translate from PySide import QtWidgets __title__ = "FreeCAD Draft Workbench GUI Tools - Hyperlinks tools" -__author__ = ("") +__author__ = "" __url__ = "https://www.freecad.org" @@ -53,10 +57,12 @@ class Draft_Hyperlink: """The Draft_Hyperlink FreeCAD command definition.""" def GetResources(self): - d = {'Pixmap': '', - 'Accel': "", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Hyperlink", "Open Links"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Hyperlink", "Opens linked documents")} + d = { + "Pixmap": "", + "Accel": "", + "MenuText": QT_TRANSLATE_NOOP("Draft_Hyperlink", "Open Links"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Hyperlink", "Opens linked documents"), + } return d def Activated(self): @@ -66,17 +72,9 @@ class Draft_Hyperlink: if len(self.hyperlinks_list) > 1: m = QtWidgets.QMessageBox() m.setWindowTitle(translate("draft", "Opening Multiple Links")) - m.setText( - translate( - "draft", - "Multiple links found" - ) - ) + m.setText(translate("draft", "Multiple links found")) m.setInformativeText( - translate( - "draft", - "This may lead to the opening of various windows" - ) + translate("draft", "This may lead to the opening of various windows") ) m.setStandardButtons(m.Ok | m.Cancel) ret = m.exec_() @@ -92,7 +90,9 @@ class Draft_Hyperlink: if hasattr(o.Object, "Text"): for text in o.Object.Text: - hyperlinks = re.findall(r"((\w:[\\/]|%\w+%|\\\\\w+|/\w+|\w{3,5}://)[\w\\/: ]+\.[\S]+)", text) + hyperlinks = re.findall( + r"((\w:[\\/]|%\w+%|\\\\\w+|/\w+|\w{3,5}://)[\w\\/: ]+\.[\S]+)", text + ) for hyperlink in hyperlinks: self.hyperlinks_list.append(hyperlink[0]) @@ -116,8 +116,11 @@ class Draft_Hyperlink: _toolmsg(translate("draft", "Opening hyperlink") + " " + hyperlink) - QDesktopServices.openUrl(url) #ToDo: add management to open FCStd files in the current instance and to open web pages with the Web Workbench + QDesktopServices.openUrl( + url + ) # ToDo: add management to open FCStd files in the current instance and to open web pages with the Web Workbench -FreeCADGui.addCommand('Draft_Hyperlink', Draft_Hyperlink()) + +FreeCADGui.addCommand("Draft_Hyperlink", Draft_Hyperlink()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_join.py b/src/Mod/Draft/draftguitools/gui_join.py index dcb2886abe..d680668ed3 100644 --- a/src/Mod/Draft/draftguitools/gui_join.py +++ b/src/Mod/Draft/draftguitools/gui_join.py @@ -49,10 +49,15 @@ class Join(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Join", - "Accel": "J, O", - "MenuText": QT_TRANSLATE_NOOP("Draft_Join", "Join"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Join", "Joins the selected lines or polylines into a single object.\nThe lines must share a common point at the start or at the end.")} + return { + "Pixmap": "Draft_Join", + "Accel": "J, O", + "MenuText": QT_TRANSLATE_NOOP("Draft_Join", "Join"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Join", + "Joins the selected lines or polylines into a single object.\nThe lines must share a common point at the start or at the end.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -83,10 +88,8 @@ class Join(gui_base_original.Modifier): _cmd += "(" _cmd += "FreeCADGui.Selection.getSelection()" _cmd += ")" - _cmd_list = ['j = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Join Lines"), - _cmd_list) + _cmd_list = ["j = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Join Lines"), _cmd_list) else: _err(translate("draft", "Only Draft lines and wires can be joined")) self.finish() @@ -98,9 +101,9 @@ class Join(gui_base_original.Modifier): labels.append(obj.Label) labels = ", ".join(labels) - _toolmsg(translate("draft","Selection:") + " {}".format(labels)) + _toolmsg(translate("draft", "Selection:") + " {}".format(labels)) -Gui.addCommand('Draft_Join', Join()) +Gui.addCommand("Draft_Join", Join()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_labels.py b/src/Mod/Draft/draftguitools/gui_labels.py index da088f815b..36c23356f7 100644 --- a/src/Mod/Draft/draftguitools/gui_labels.py +++ b/src/Mod/Draft/draftguitools/gui_labels.py @@ -58,10 +58,15 @@ class Label(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Label', - 'Accel': "D, L", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Label", "Label"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Label", "Creates a label, optionally attached to a selected object or subelement")} + return { + "Pixmap": "Draft_Label", + "Accel": "D, L", + "MenuText": QT_TRANSLATE_NOOP("Draft_Label", "Label"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Label", + "Creates a label, optionally attached to a selected object or subelement", + ), + } def Activated(self): """Execute when the command is called.""" @@ -71,7 +76,7 @@ class Label(gui_base_original.Creator): self.sel = Gui.Selection.getSelectionEx() if self.sel: self.sel = self.sel[0] - self.ui.labelUi(title=translate("draft",self.featureName), callback=self.setmode) + self.ui.labelUi(title=translate("draft", self.featureName), callback=self.setmode) self.ui.xValue.setFocus() self.ui.xValue.selectAll() self.ghost = trackers.lineTracker() @@ -82,6 +87,7 @@ class Label(gui_base_original.Creator): def setmode(self, i): """Set the type of label, if it is associated to an object.""" from draftobjects.label import get_label_types + self.labeltype = get_label_types()[i] params.set_param("labeltype", self.labeltype) @@ -103,10 +109,10 @@ class Label(gui_base_original.Creator): n = self.wp.axis r = self.wp.get_placement().Rotation - if abs(DraftVecUtils.angle(v, h, n)) <= math.pi/4: + if abs(DraftVecUtils.angle(v, h, n)) <= math.pi / 4: direction = "Horizontal" dist = -dist - elif abs(DraftVecUtils.angle(v, h, n)) >= math.pi*3/4: + elif abs(DraftVecUtils.angle(v, h, n)) >= math.pi * 3 / 4: direction = "Horizontal" elif DraftVecUtils.angle(v, h, n) > 0: direction = "Vertical" @@ -146,11 +152,12 @@ class Label(gui_base_original.Creator): # Commit the creation instructions through the parent class, # the Creator class - _cmd_list = ['_label_ = ' + _cmd, - 'Draft.autogroup(_label_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Label"), - _cmd_list) + _cmd_list = [ + "_label_ = " + _cmd, + "Draft.autogroup(_label_)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Label"), _cmd_list) self.finish() def action(self, arg): @@ -182,8 +189,7 @@ class Label(gui_base_original.Creator): # first click self.node.append(self.point) self.ui.isRelative.show() - _toolmsg(translate("draft", - "Pick endpoint of leader line")) + _toolmsg(translate("draft", "Pick endpoint of leader line")) if self.planetrack: self.planetrack.set(self.point) elif len(self.node) == 1: @@ -228,6 +234,6 @@ class Label(gui_base_original.Creator): Draft_Label = Label -Gui.addCommand('Draft_Label', Label()) +Gui.addCommand("Draft_Label", Label()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_layers.py b/src/Mod/Draft/draftguitools/gui_layers.py index 67f9bc6010..bb6c7dcd7c 100644 --- a/src/Mod/Draft/draftguitools/gui_layers.py +++ b/src/Mod/Draft/draftguitools/gui_layers.py @@ -47,12 +47,12 @@ bool(Draft_rc.__name__) def getColorIcon(color): - "returns a QtGui.QIcon from a color 3-float tuple" - from PySide import QtCore,QtGui - c = QtGui.QColor(int(color[0]*255),int(color[1]*255),int(color[2]*255)) - im = QtGui.QImage(48,48,QtGui.QImage.Format_ARGB32) + from PySide import QtCore, QtGui + + c = QtGui.QColor(int(color[0] * 255), int(color[1] * 255), int(color[2] * 255)) + im = QtGui.QImage(48, 48, QtGui.QImage.Format_ARGB32) im.fill(c) px = QtGui.QPixmap.fromImage(im) return QtGui.QIcon(px) @@ -66,9 +66,14 @@ class Layer(gui_base.GuiCommandSimplest): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Layer", - "MenuText": QT_TRANSLATE_NOOP("Draft_Layer", "New Layer"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Layer", "Adds a layer to the document.\nObjects added to this layer can share the same visual properties.")} + return { + "Pixmap": "Draft_Layer", + "MenuText": QT_TRANSLATE_NOOP("Draft_Layer", "New Layer"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Layer", + "Adds a layer to the document.\nObjects added to this layer can share the same visual properties.", + ), + } def Activated(self): """Execute when the command is called. @@ -79,7 +84,9 @@ class Layer(gui_base.GuiCommandSimplest): self.doc.openTransaction(translate("draft", "Create layer")) Gui.addModule("Draft") - Gui.doCommand("layer = Draft.make_layer(name=None, line_color=None, shape_color=None, line_width=None, draw_style=None, transparency=None)") + Gui.doCommand( + "layer = Draft.make_layer(name=None, line_color=None, shape_color=None, line_width=None, draw_style=None, transparency=None)" + ) Gui.doCommand("FreeCAD.ActiveDocument.recompute()") self.doc.commitTransaction() @@ -92,9 +99,14 @@ class AddToLayer(gui_base.GuiCommandNeedsSelection): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_AddToLayer", - "MenuText": QT_TRANSLATE_NOOP("Draft_AddToLayer", "Add to Layer"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_AddToLayer", "Adds selected objects to a layer, or removes them from any layer")} + return { + "Pixmap": "Draft_AddToLayer", + "MenuText": QT_TRANSLATE_NOOP("Draft_AddToLayer", "Add to Layer"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_AddToLayer", + "Adds selected objects to a layer, or removes them from any layer", + ), + } def Activated(self): """Execute when the command is called.""" @@ -106,19 +118,21 @@ class AddToLayer(gui_base.GuiCommandNeedsSelection): self.ui = Gui.draftToolBar objs = [obj for obj in App.ActiveDocument.Objects if utils.get_type(obj) == "Layer"] objs.sort(key=lambda obj: obj.Label) - self.objects = [None] \ - + [None] \ - + objs - self.labels = [translate("draft", "Remove From Layer")] \ - + ["---"] \ - + [obj.Label for obj in objs] \ - + ["---"] \ - + [translate("draft", "Add to New Layer")] - self.icons = [self.ui.getIcon(":/icons/list-remove.svg")] \ - + [None] \ - + [obj.ViewObject.Icon for obj in objs] \ - + [None] \ - + [self.ui.getIcon(":/icons/list-add.svg")] + self.objects = [None] + [None] + objs + self.labels = ( + [translate("draft", "Remove From Layer")] + + ["---"] + + [obj.Label for obj in objs] + + ["---"] + + [translate("draft", "Add to New Layer")] + ) + self.icons = ( + [self.ui.getIcon(":/icons/list-remove.svg")] + + [None] + + [obj.ViewObject.Icon for obj in objs] + + [None] + + [self.ui.getIcon(":/icons/list-add.svg")] + ) self.ui.sourceCmd = self self.ui.popupMenu(self.labels, self.icons) @@ -143,19 +157,26 @@ class AddToLayer(gui_base.GuiCommandNeedsSelection): if option == self.labels[-1]: # "Add to new layer..." from PySide import QtWidgets + txt, ok = QtWidgets.QInputDialog.getText( None, translate("draft", "New Layer"), translate("draft", "Layer name"), - text=translate("draft", "Layer", "Object label") + text=translate("draft", "Layer", "Object label"), ) if not ok: return if not txt: return self.doc.openTransaction(translate("draft", "Add to new layer")) - lyr = make_layer.make_layer(name=txt, line_color=None, shape_color=None, - line_width=None, draw_style=None, transparency=None) + lyr = make_layer.make_layer( + name=txt, + line_color=None, + shape_color=None, + line_width=None, + draw_style=None, + transparency=None, + ) for obj in Gui.Selection.getSelection(): lyr.Proxy.addObject(lyr, obj) self.doc.commitTransaction() @@ -173,14 +194,15 @@ class AddToLayer(gui_base.GuiCommandNeedsSelection): class LayerManager: - """GuiCommand that displays a Layers manager dialog""" def GetResources(self): - return {"Pixmap" : "Draft_LayerManager", - "MenuText": QT_TRANSLATE_NOOP("Draft_LayerManager", "Manage Layers"), - "ToolTip" : QT_TRANSLATE_NOOP("Draft_LayerManager", "Allows to modify the layers")} + return { + "Pixmap": "Draft_LayerManager", + "MenuText": QT_TRANSLATE_NOOP("Draft_LayerManager", "Manage Layers"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_LayerManager", "Allows to modify the layers"), + } def IsActive(self): """Return True when this command should be available.""" @@ -209,11 +231,13 @@ class LayerManager: # restore window geometry from stored state w = params.get_param("LayersManagerWidth") h = params.get_param("LayersManagerHeight") - self.dialog.resize(w,h) + self.dialog.resize(w, h) # center the dialog over FreeCAD window mw = Gui.getMainWindow() - self.dialog.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center()) + self.dialog.move( + mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center() + ) # connect signals/slots self.dialog.buttonNew.clicked.connect(self.addItem) @@ -231,8 +255,10 @@ class LayerManager: self.dialog.tree.setUniformRowHeights(True) self.dialog.tree.setItemDelegate(Layers_Delegate()) self.dialog.tree.setItemsExpandable(False) - self.dialog.tree.setRootIsDecorated(False) # removes spacing in first column - self.dialog.tree.setSelectionMode(QtWidgets.QTreeView.ExtendedSelection) # allow one to select many + self.dialog.tree.setRootIsDecorated(False) # removes spacing in first column + self.dialog.tree.setSelectionMode( + QtWidgets.QTreeView.ExtendedSelection + ) # allow one to select many # fill the tree view self.update() @@ -241,7 +267,6 @@ class LayerManager: self.dialog.exec_() def accept(self): - "when OK button is pressed" doc = App.ActiveDocument @@ -267,8 +292,14 @@ class LayerManager: if not changed: doc.openTransaction(trans_name) changed = True - obj = make_layer.make_layer(name=None, line_color=None, shape_color=None, - line_width=None, draw_style=None, transparency=None) + obj = make_layer.make_layer( + name=None, + line_color=None, + shape_color=None, + line_width=None, + draw_style=None, + transparency=None, + ) vobj = obj.ViewObject # visibility @@ -346,7 +377,6 @@ class LayerManager: self.dialog.reject() def reject(self): - "when Cancel button is pressed or dialog is closed" # save dialog size @@ -356,32 +386,34 @@ class LayerManager: return True def update(self): - "rebuild the model from document contents" self.model.clear() # set header - self.model.setHorizontalHeaderLabels([translate("Draft","On"), - translate("Draft","Name"), - translate("Draft","Line Width"), - translate("Draft","Draw Style"), - translate("Draft","Line Color"), - translate("Draft","Face Color"), - translate("Draft","Transparency"), - translate("Draft","Line Print Color")]) + self.model.setHorizontalHeaderLabels( + [ + translate("Draft", "On"), + translate("Draft", "Name"), + translate("Draft", "Line Width"), + translate("Draft", "Draw Style"), + translate("Draft", "Line Color"), + translate("Draft", "Face Color"), + translate("Draft", "Transparency"), + translate("Draft", "Line Print Color"), + ] + ) self.dialog.tree.header().setDefaultSectionSize(72) - self.dialog.tree.setColumnWidth(0,32) # on/off column - self.dialog.tree.setColumnWidth(1,128) # name column + self.dialog.tree.setColumnWidth(0, 32) # on/off column + self.dialog.tree.setColumnWidth(1, 128) # name column # populate objs = [obj for obj in App.ActiveDocument.Objects if utils.get_type(obj) == "Layer"] - objs.sort(key=lambda o:o.Label) + objs.sort(key=lambda o: o.Label) for obj in objs: self.addItem(obj) - def addItem(self,obj=None): - + def addItem(self, obj=None): "adds a row to the model" from PySide import QtCore, QtGui @@ -397,22 +429,19 @@ class LayerManager: lineColorItem = QtGui.QStandardItem() lineColorItem.setData( utils.get_rgba_tuple(params.get_param_view("DefaultShapeLineColor"))[:3], - QtCore.Qt.UserRole + QtCore.Qt.UserRole, ) shapeColorItem = QtGui.QStandardItem() shapeColorItem.setData( - utils.get_rgba_tuple(params.get_param_view("DefaultShapeColor"))[:3], - QtCore.Qt.UserRole + utils.get_rgba_tuple(params.get_param_view("DefaultShapeColor"))[:3], QtCore.Qt.UserRole ) transparencyItem = QtGui.QStandardItem() transparencyItem.setData( - params.get_param_view("DefaultShapeTransparency"), - QtCore.Qt.DisplayRole + params.get_param_view("DefaultShapeTransparency"), QtCore.Qt.DisplayRole ) linePrintColorItem = QtGui.QStandardItem() linePrintColorItem.setData( - utils.get_rgba_tuple(params.get_param("DefaultPrintColor"))[:3], - QtCore.Qt.UserRole + utils.get_rgba_tuple(params.get_param("DefaultPrintColor"))[:3], QtCore.Qt.UserRole ) # populate with object data @@ -421,29 +450,32 @@ class LayerManager: onItem.setCheckState(QtCore.Qt.Checked if vobj.Visibility else QtCore.Qt.Unchecked) nameItem.setText(obj.Label) nameItem.setToolTip(obj.Name) - widthItem.setData(vobj.LineWidth,QtCore.Qt.DisplayRole) + widthItem.setData(vobj.LineWidth, QtCore.Qt.DisplayRole) styleItem.setText(vobj.DrawStyle) - lineColorItem.setData(vobj.LineColor[:3],QtCore.Qt.UserRole) - shapeColorItem.setData(vobj.ShapeColor[:3],QtCore.Qt.UserRole) - transparencyItem.setData(vobj.Transparency,QtCore.Qt.DisplayRole) - if hasattr(vobj,"LinePrintColor"): - linePrintColorItem.setData(vobj.LinePrintColor[:3],QtCore.Qt.UserRole) + lineColorItem.setData(vobj.LineColor[:3], QtCore.Qt.UserRole) + shapeColorItem.setData(vobj.ShapeColor[:3], QtCore.Qt.UserRole) + transparencyItem.setData(vobj.Transparency, QtCore.Qt.DisplayRole) + if hasattr(vobj, "LinePrintColor"): + linePrintColorItem.setData(vobj.LinePrintColor[:3], QtCore.Qt.UserRole) lineColorItem.setIcon(getColorIcon(lineColorItem.data(QtCore.Qt.UserRole))) shapeColorItem.setIcon(getColorIcon(shapeColorItem.data(QtCore.Qt.UserRole))) linePrintColorItem.setIcon(getColorIcon(linePrintColorItem.data(QtCore.Qt.UserRole))) # append row - self.model.appendRow([onItem, - nameItem, - widthItem, - styleItem, - lineColorItem, - shapeColorItem, - transparencyItem, - linePrintColorItem]) + self.model.appendRow( + [ + onItem, + nameItem, + widthItem, + styleItem, + lineColorItem, + shapeColorItem, + transparencyItem, + linePrintColorItem, + ] + ) def onDelete(self): - "delete selected rows" rows = [] @@ -465,7 +497,6 @@ class LayerManager: self.model.takeRow(row) def onToggle(self): - "toggle selected layers on/off" from PySide import QtCore @@ -482,7 +513,6 @@ class LayerManager: self.model.itemFromIndex(index).setCheckState(state) def onIsolate(self): - "isolates the selected layers (turns all the others off" from PySide import QtCore @@ -501,7 +531,6 @@ if App.GuiUp: from PySide import QtCore, QtGui, QtWidgets class Layers_Delegate(QtWidgets.QStyledItemDelegate): - "model delegate" def __init__(self, parent=None, *args): @@ -511,91 +540,97 @@ if App.GuiUp: # But we want to show the color dialog only the first time self.first = True - def createEditor(self,parent,option,index): + def createEditor(self, parent, option, index): - if index.column() == 0: # Layer on/off + if index.column() == 0: # Layer on/off editor = QtWidgets.QCheckBox(parent) - if index.column() == 1: # Layer name + if index.column() == 1: # Layer name editor = QtWidgets.QLineEdit(parent) - elif index.column() == 2: # Line width + elif index.column() == 2: # Line width editor = QtWidgets.QSpinBox(parent) editor.setMaximum(99) - elif index.column() == 3: # Line style + elif index.column() == 3: # Line style editor = QtWidgets.QComboBox(parent) editor.addItems(utils.DRAW_STYLES) - elif index.column() == 4: # Line color + elif index.column() == 4: # Line color editor = QtWidgets.QLineEdit(parent) self.first = True - elif index.column() == 5: # Shape color + elif index.column() == 5: # Shape color editor = QtWidgets.QLineEdit(parent) self.first = True - elif index.column() == 6: # Transparency + elif index.column() == 6: # Transparency editor = QtWidgets.QSpinBox(parent) editor.setMaximum(100) - elif index.column() == 7: # Line print color + elif index.column() == 7: # Line print color editor = QtWidgets.QLineEdit(parent) self.first = True return editor def setEditorData(self, editor, index): - if index.column() == 0: # Layer on/off + if index.column() == 0: # Layer on/off editor.setChecked(index.data()) - elif index.column() == 1: # Layer name + elif index.column() == 1: # Layer name editor.setText(index.data()) - elif index.column() == 2: # Line width + elif index.column() == 2: # Line width editor.setValue(index.data()) - elif index.column() == 3: # Line style + elif index.column() == 3: # Line style editor.setCurrentIndex(utils.DRAW_STYLES.index(index.data())) - elif index.column() == 4: # Line color + elif index.column() == 4: # Line color editor.setText(str(index.data(QtCore.Qt.UserRole))) if self.first: c = index.data(QtCore.Qt.UserRole) - color = QtWidgets.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255))) + color = QtWidgets.QColorDialog.getColor( + QtGui.QColor(int(c[0] * 255), int(c[1] * 255), int(c[2] * 255)) + ) editor.setText(str(color.getRgbF())) self.first = False - elif index.column() == 5: # Shape color + elif index.column() == 5: # Shape color editor.setText(str(index.data(QtCore.Qt.UserRole))) if self.first: c = index.data(QtCore.Qt.UserRole) - color = QtWidgets.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255))) + color = QtWidgets.QColorDialog.getColor( + QtGui.QColor(int(c[0] * 255), int(c[1] * 255), int(c[2] * 255)) + ) editor.setText(str(color.getRgbF())) self.first = False - elif index.column() == 6: # Transparency + elif index.column() == 6: # Transparency editor.setValue(index.data()) elif index.column() == 7: # Line print color editor.setText(str(index.data(QtCore.Qt.UserRole))) if self.first: c = index.data(QtCore.Qt.UserRole) - color = QtWidgets.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255))) + color = QtWidgets.QColorDialog.getColor( + QtGui.QColor(int(c[0] * 255), int(c[1] * 255), int(c[2] * 255)) + ) editor.setText(str(color.getRgbF())) self.first = False def setModelData(self, editor, model, index): - if index.column() == 0: # Layer on/off - model.setData(index,editor.isChecked()) - elif index.column() == 1: # Layer name - model.setData(index,editor.text()) - elif index.column() == 2: # Line width - model.setData(index,editor.value()) - elif index.column() == 3: # Line style - model.setData(index,utils.DRAW_STYLES[editor.currentIndex()]) - elif index.column() == 4: # Line color - model.setData(index,eval(editor.text()),QtCore.Qt.UserRole) + if index.column() == 0: # Layer on/off + model.setData(index, editor.isChecked()) + elif index.column() == 1: # Layer name + model.setData(index, editor.text()) + elif index.column() == 2: # Line width + model.setData(index, editor.value()) + elif index.column() == 3: # Line style + model.setData(index, utils.DRAW_STYLES[editor.currentIndex()]) + elif index.column() == 4: # Line color + model.setData(index, eval(editor.text()), QtCore.Qt.UserRole) model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text()))) - elif index.column() == 5: # Shape color - model.setData(index,eval(editor.text()),QtCore.Qt.UserRole) + elif index.column() == 5: # Shape color + model.setData(index, eval(editor.text()), QtCore.Qt.UserRole) model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text()))) - elif index.column() == 6: # Transparency - model.setData(index,editor.value()) - elif index.column() == 7: # Line prin color - model.setData(index,eval(editor.text()),QtCore.Qt.UserRole) + elif index.column() == 6: # Transparency + model.setData(index, editor.value()) + elif index.column() == 7: # Line prin color + model.setData(index, eval(editor.text()), QtCore.Qt.UserRole) model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text()))) -Gui.addCommand('Draft_Layer', Layer()) -Gui.addCommand('Draft_AddToLayer', AddToLayer()) -Gui.addCommand('Draft_LayerManager', LayerManager()) +Gui.addCommand("Draft_Layer", Layer()) +Gui.addCommand("Draft_AddToLayer", AddToLayer()) +Gui.addCommand("Draft_LayerManager", LayerManager()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_lines.py b/src/Mod/Draft/draftguitools/gui_lines.py index 199211154a..1c41e219a8 100644 --- a/src/Mod/Draft/draftguitools/gui_lines.py +++ b/src/Mod/Draft/draftguitools/gui_lines.py @@ -58,12 +58,16 @@ class Line(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Line', - 'Accel': "L,I", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Line", "Line"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Line", "Creates a 2-point line")} + return { + "Pixmap": "Draft_Line", + "Accel": "L,I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Line", "Line"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Line", "Creates a 2-point line"), + } - def Activated(self, name=QT_TRANSLATE_NOOP("draft", "Line"), icon="Draft_Line", task_title=None): + def Activated( + self, name=QT_TRANSLATE_NOOP("draft", "Line"), icon="Draft_Line", task_title=None + ): """Execute when the command is called.""" super().Activated(name) if task_title is None: @@ -153,48 +157,49 @@ class Line(gui_base_original.Creator): Gui.addModule("Draft") # The command to run is built as a series of text strings # to be committed through the `draftutils.todo.ToDo` class. - if (len(self.node) == 2 - and params.get_param("UsePartPrimitives")): + if len(self.node) == 2 and params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object p1 = self.node[0] p2 = self.node[-1] - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Line", "Line")' - _cmd_list = ['line = ' + _cmd, - 'line.X1 = ' + str(p1.x), - 'line.Y1 = ' + str(p1.y), - 'line.Z1 = ' + str(p1.z), - 'line.X2 = ' + str(p2.x), - 'line.Y2 = ' + str(p2.y), - 'line.Z2 = ' + str(p2.z), - 'Draft.autogroup(line)', - 'Draft.select(line)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Line"), - _cmd_list) + _cmd_list = [ + "line = " + _cmd, + "line.X1 = " + str(p1.x), + "line.Y1 = " + str(p1.y), + "line.Z1 = " + str(p1.z), + "line.X2 = " + str(p2.x), + "line.Y2 = " + str(p2.y), + "line.Z2 = " + str(p2.z), + "Draft.autogroup(line)", + "Draft.select(line)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Line"), _cmd_list) else: # Insert a Draft line rot, sup, pts, fil = self.getStrings() _base = DraftVecUtils.toString(self.node[0]) - _cmd = 'Draft.make_wire' - _cmd += '(' - _cmd += 'points, ' - _cmd += 'placement=pl, ' - _cmd += 'closed=' + str(closed) + ', ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + _base, - 'points = ' + pts, - 'line = ' + _cmd, - 'Draft.autogroup(line)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Wire"), - _cmd_list) + _cmd = "Draft.make_wire" + _cmd += "(" + _cmd += "points, " + _cmd += "placement=pl, " + _cmd += "closed=" + str(closed) + ", " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + _base, + "points = " + pts, + "line = " + _cmd, + "Draft.autogroup(line)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Wire"), _cmd_list) super().finish() if cont or (cont is None and self.ui and self.ui.continueMode): self.Activated() @@ -214,6 +219,7 @@ class Line(gui_base_original.Creator): def undolast(self): """Undoes last line segment.""" import Part + if len(self.node) > 1: self.node.pop() # last = self.node[-1] @@ -232,6 +238,7 @@ class Line(gui_base_original.Creator): def drawUpdate(self, point): """Draws new line segment.""" import Part + if self.planetrack and self.node: self.planetrack.set(self.node[-1]) if len(self.node) == 1: @@ -268,6 +275,7 @@ class Line(gui_base_original.Creator): """Orient the working plane.""" if len(self.node) > 1 and self.obj: import DraftGeomUtils + n = DraftGeomUtils.getNormal(self.obj.Shape) if not n: n = self.wp.axis @@ -303,20 +311,22 @@ class Line(gui_base_original.Creator): hints = [ Gui.InputHint( translate("draft", "%1 pick next point, snap to first point to close"), - Gui.UserInput.MouseLeft + Gui.UserInput.MouseLeft, ) ] else: hints = [ Gui.InputHint(translate("draft", "%1 pick next point"), Gui.UserInput.MouseLeft) ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Line', Line()) +Gui.addCommand("Draft_Line", Line()) class Wire(Line): @@ -333,10 +343,12 @@ class Wire(Line): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Wire', - 'Accel': "P, L", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Wire", "Polyline"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Wire", "Creates a polyline")} + return { + "Pixmap": "Draft_Wire", + "Accel": "P, L", + "MenuText": QT_TRANSLATE_NOOP("Draft_Wire", "Polyline"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Wire", "Creates a polyline"), + } def Activated(self): """Execute when the command is called.""" @@ -357,9 +369,7 @@ class Wire(Line): try: w = Part.Wire(Part.__sortEdges__(edges)) except Exception: - _err(translate("draft", - "Unable to create a wire " - "from the selected objects")) + _err(translate("draft", "Unable to create a wire " "from the selected objects")) else: # Points of the new fused Wire in string form # 'FreeCAD.Vector(x,y,z), FreeCAD.Vector(x1,y1,z1), ...' @@ -369,19 +379,18 @@ class Wire(Line): # List of commands to remove the old objects rems = list() for o in Gui.Selection.getSelection(): - rems.append('FreeCAD.ActiveDocument.' - 'removeObject("' + o.Name + '")') + rems.append("FreeCAD.ActiveDocument." 'removeObject("' + o.Name + '")') Gui.addModule("Draft") # The command to run is built as a series of text strings # to be committed through the `draftutils.todo.ToDo` class - _cmd = 'wire = Draft.make_wire(' - _cmd += '[' + pts + '], closed=' + str(w.isClosed()) - _cmd += ')' + _cmd = "wire = Draft.make_wire(" + _cmd += "[" + pts + "], closed=" + str(w.isClosed()) + _cmd += ")" _cmd_list = [_cmd] _cmd_list.extend(rems) - _cmd_list.append('Draft.autogroup(wire)') - _cmd_list.append('FreeCAD.ActiveDocument.recompute()') + _cmd_list.append("Draft.autogroup(wire)") + _cmd_list.append("FreeCAD.ActiveDocument.recompute()") _op_name = translate("draft", "Convert to Wire") todo.ToDo.delayCommit([(_op_name, _cmd_list)]) @@ -390,11 +399,11 @@ class Wire(Line): # If there was no selection or the selection was just one object # then we proceed with the normal line creation functions, # only this time we will be able to input more than two points - super().Activated(name="Polyline", - icon="Draft_Wire", - task_title=translate("draft", "Polyline")) + super().Activated( + name="Polyline", icon="Draft_Wire", task_title=translate("draft", "Polyline") + ) -Gui.addCommand('Draft_Wire', Wire()) +Gui.addCommand("Draft_Wire", Wire()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_lineslope.py b/src/Mod/Draft/draftguitools/gui_lineslope.py index 928a64500e..d440296def 100644 --- a/src/Mod/Draft/draftguitools/gui_lineslope.py +++ b/src/Mod/Draft/draftguitools/gui_lineslope.py @@ -62,9 +62,14 @@ class LineSlope(gui_base.GuiCommandNeedsSelection): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Slope", - "MenuText": QT_TRANSLATE_NOOP("Draft_Slope", "Set Slope"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Slope", "Sets the slope of the selected line by changing the value of the Z value of one of its points.\nIf a polyline is selected, it will apply the slope transformation to each of its segments.\n\nThe slope will always change the Z value, therefore this command only works well for\nstraight Draft lines that are drawn on the XY-plane.")} + return { + "Pixmap": "Draft_Slope", + "MenuText": QT_TRANSLATE_NOOP("Draft_Slope", "Set Slope"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Slope", + "Sets the slope of the selected line by changing the value of the Z value of one of its points.\nIf a polyline is selected, it will apply the slope transformation to each of its segments.\n\nThe slope will always change the Z value, therefore this command only works well for\nstraight Draft lines that are drawn on the XY-plane.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -92,11 +97,13 @@ class LineSlope(gui_base.GuiCommandNeedsSelection): self.spinbox.setMaximum(9999.99) self.spinbox.setSingleStep(0.01) - _tip = ("New slope of the selected lines.\n" - "This is the tangent of the horizontal angle:\n" - "0 = horizontal\n" - "1 = 45 deg up\n" - "-1 = 45deg down\n") + _tip = ( + "New slope of the selected lines.\n" + "This is the tangent of the horizontal angle:\n" + "0 = horizontal\n" + "1 = 45 deg up\n" + "-1 = 45deg down\n" + ) label.setToolTip(translate("Draft", _tip)) self.spinbox.setToolTip(translate("Draft", _tip)) layout.addWidget(self.spinbox) @@ -145,6 +152,6 @@ class LineSlope(gui_base.GuiCommandNeedsSelection): Draft_Slope = LineSlope -Gui.addCommand('Draft_Slope', LineSlope()) +Gui.addCommand("Draft_Slope", LineSlope()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_mirror.py b/src/Mod/Draft/draftguitools/gui_mirror.py index d2837fd254..600483dfc4 100644 --- a/src/Mod/Draft/draftguitools/gui_mirror.py +++ b/src/Mod/Draft/draftguitools/gui_mirror.py @@ -59,10 +59,14 @@ class Mirror(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Mirror', - 'Accel': "M, I", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Mirror", "Mirror"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Mirror", "Mirrors the selected objects along a line defined by 2 points")} + return { + "Pixmap": "Draft_Mirror", + "Accel": "M, I", + "MenuText": QT_TRANSLATE_NOOP("Draft_Mirror", "Mirror"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Mirror", "Mirrors the selected objects along a line defined by 2 points" + ), + } def Activated(self): """Execute when the command is called.""" @@ -72,9 +76,7 @@ class Mirror(gui_base_original.Modifier): if not Gui.Selection.getSelection(): self.ui.selectUi(on_close_call=self.finish) _msg(translate("draft", "Select an object to mirror")) - self.call = \ - self.view.addEventCallback("SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() @@ -101,23 +103,21 @@ class Mirror(gui_base_original.Modifier): def mirror(self, p1, p2, copy=False): """Mirror the real shapes.""" - sel = '[' + sel = "[" for o in self.sel: if len(sel) > 1: - sel += ', ' - sel += 'FreeCAD.ActiveDocument.' + o.Name - sel += ']' + sel += ", " + sel += "FreeCAD.ActiveDocument." + o.Name + sel += "]" Gui.addModule("Draft") - _cmd = 'Draft.mirror' - _cmd += '(' - _cmd += sel + ', ' - _cmd += DraftVecUtils.toString(p1) + ', ' + _cmd = "Draft.mirror" + _cmd += "(" + _cmd += sel + ", " + _cmd += DraftVecUtils.toString(p1) + ", " _cmd += DraftVecUtils.toString(p2) - _cmd += ')' - _cmd_list = ['m = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Mirror"), - _cmd_list) + _cmd += ")" + _cmd_list = ["m = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Mirror"), _cmd_list) def action(self, arg): """Handle the 3D scene events. @@ -147,7 +147,7 @@ class Mirror(gui_base_original.Modifier): if nor.Length > tol: nor.normalize() mtx = DraftGeomUtils.mirror_matrix(App.Matrix(), last, nor) - self.ghost.setMatrix(mtx) # Ignores the position of the matrix. + self.ghost.setMatrix(mtx) # Ignores the position of the matrix. self.ghost.move(App.Vector(mtx.col(3)[:3])) if self.extendedCopy: if not gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): @@ -157,19 +157,19 @@ class Mirror(gui_base_original.Modifier): if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): if self.point: self.ui.redraw() - if (self.node == []): + if self.node == []: self.node.append(self.point) self.ui.isRelative.show() if self.ghost: self.ghost.on() - _toolmsg(translate("draft", - "Pick end point of mirror line")) + _toolmsg(translate("draft", "Pick end point of mirror line")) if self.planetrack: self.planetrack.set(self.point) else: last = self.node[0] - if (self.ui.isCopy.isChecked() - or gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())): + if self.ui.isCopy.isChecked() or gui_tool_utils.hasMod( + arg, gui_tool_utils.get_mod_alt_key() + ): self.mirror(last, self.point, True) else: self.mirror(last, self.point) @@ -199,6 +199,6 @@ class Mirror(gui_base_original.Modifier): self.finish() -Gui.addCommand('Draft_Mirror', Mirror()) +Gui.addCommand("Draft_Mirror", Mirror()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_move.py b/src/Mod/Draft/draftguitools/gui_move.py index 8b0569a7d4..ce440b81e1 100644 --- a/src/Mod/Draft/draftguitools/gui_move.py +++ b/src/Mod/Draft/draftguitools/gui_move.py @@ -50,16 +50,21 @@ class Move(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Move", - "Accel": "M, V", - "MenuText": QT_TRANSLATE_NOOP("Draft_Move", "Move"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Move", "Moves the selected objects.\nIf the \"Copy\" option is active, it creates displaced copies.")} + return { + "Pixmap": "Draft_Move", + "Accel": "M, V", + "MenuText": QT_TRANSLATE_NOOP("Draft_Move", "Move"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Move", + 'Moves the selected objects.\nIf the "Copy" option is active, it creates displaced copies.', + ), + } def Activated(self): """Execute when the command is called.""" - super().Activated(name="Move", - is_subtool=isinstance(App.activeDraftCommand, - SubelementHighlight)) + super().Activated( + name="Move", is_subtool=isinstance(App.activeDraftCommand, SubelementHighlight) + ) if not self.ui: return self.ghosts = [] @@ -78,7 +83,7 @@ class Move(gui_base_original.Modifier): if self.call: self.view.removeEventCallback("SoEvent", self.call) self.selection = Gui.Selection.getSelectionEx("", 0) - Gui.doCommand("selection = FreeCADGui.Selection.getSelectionEx(\"\", 0)") + Gui.doCommand('selection = FreeCADGui.Selection.getSelectionEx("", 0)') self.ui.lineUi(title=translate("draft", self.featureName), icon="Draft_Move") self.ui.modUi() if self.copymode: @@ -119,9 +124,11 @@ class Move(gui_base_original.Modifier): self.finish() elif arg["Type"] == "SoLocation2Event": self.handle_mouse_move_event(arg) - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["State"] == "DOWN" - and arg["Button"] == "BUTTON1"): + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1" + ): self.handle_mouse_click_event(arg) def handle_mouse_move_event(self, arg): @@ -162,8 +169,10 @@ class Move(gui_base_original.Modifier): else: last = self.node[0] self.vector = self.point.sub(last) - self.move(self.ui.isCopy.isChecked() - or gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())) + self.move( + self.ui.isCopy.isChecked() + or gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) + ) if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): self.extendedCopy = True else: @@ -179,12 +188,15 @@ class Move(gui_base_original.Modifier): if not self.ghosts: _err(translate("draft", "No valid subelements selected")) else: - objs, places, _ = utils._modifiers_process_selection(self.selection, copy, add_movable_children=(not copy)) + objs, places, _ = utils._modifiers_process_selection( + self.selection, copy, add_movable_children=(not copy) + ) self.ghosts = [trackers.ghostTracker(objs, parent_places=places)] def get_subelement_ghosts(self, selection, copy): """Get ghost for the subelements (vertices, edges).""" import Part + ghosts = [] for sel in selection: for sub in sel.SubElementNames if sel.SubElementNames else [""]: @@ -228,6 +240,6 @@ class Move(gui_base_original.Modifier): self.finish(cont=None) -Gui.addCommand('Draft_Move', Move()) +Gui.addCommand("Draft_Move", Move()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_offset.py b/src/Mod/Draft/draftguitools/gui_offset.py index 50d9eae88d..614c06f018 100644 --- a/src/Mod/Draft/draftguitools/gui_offset.py +++ b/src/Mod/Draft/draftguitools/gui_offset.py @@ -58,10 +58,15 @@ class Offset(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Offset', - 'Accel': "O, S", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Offset", "Offset"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Offset", "Offsets the selected object.\nIt can also create an offset copy of the original object.")} + return { + "Pixmap": "Draft_Offset", + "Accel": "O, S", + "MenuText": QT_TRANSLATE_NOOP("Draft_Offset", "Offset"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Offset", + "Offsets the selected object.\nIt can also create an offset copy of the original object.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -74,12 +79,9 @@ class Offset(gui_base_original.Modifier): if not Gui.Selection.getSelection(): self.ui.selectUi(on_close_call=self.finish) _msg(translate("draft", "Select an object to offset")) - self.call = self.view.addEventCallback( - "SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) elif len(Gui.Selection.getSelection()) > 1: - _wrn(translate("draft", "Offset only works " - "on one object at a time")) + _wrn(translate("draft", "Offset only works " "on one object at a time")) else: self.proceed() @@ -119,8 +121,7 @@ class Offset(gui_base_original.Modifier): self.ghost = trackers.bsplineTracker(points=self.sel.Points) self.mode = "BSpline" elif utils.getType(self.sel) == "BezCurve": - _wrn(translate("draft", "Offset of Bézier curves " - "is currently not supported")) + _wrn(translate("draft", "Offset of Bézier curves " "is currently not supported")) self.finish() return else: @@ -165,29 +166,26 @@ class Offset(gui_base_original.Modifier): pass elif arg["Type"] == "SoLocation2Event": self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) - if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key()) - and self.constrainSeg): - dist = DraftGeomUtils.findPerpendicular(self.point, - self.shape, - self.constrainSeg[1]) + if ( + gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key()) + and self.constrainSeg + ): + dist = DraftGeomUtils.findPerpendicular( + self.point, self.shape, self.constrainSeg[1] + ) else: - dist = DraftGeomUtils.findPerpendicular(self.point, - self.shape.Edges) + dist = DraftGeomUtils.findPerpendicular(self.point, self.shape.Edges) if dist: self.ghost.on() if self.mode == "Wire": d = dist[0].negative() - v1 = DraftGeomUtils.getTangent(self.shape.Edges[0], - self.point) - v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]], - self.point) + v1 = DraftGeomUtils.getTangent(self.shape.Edges[0], self.point) + v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]], self.point) a = -DraftVecUtils.angle(v1, v2, self.wp.axis) self.dvec = DraftVecUtils.rotate(d, a, self.wp.axis) occmode = self.ui.occOffset.isChecked() params.set_param("Offset_OCC", occmode) - _wire = DraftGeomUtils.offsetWire(self.shape, - self.dvec, - occ=occmode) + _wire = DraftGeomUtils.offsetWire(self.shape, self.dvec, occ=occmode) self.ghost.update(_wire, forceclosed=occmode) elif self.mode == "BSpline": d = dist[0].negative() @@ -225,39 +223,37 @@ class Offset(gui_base_original.Modifier): copymode = False occmode = self.ui.occOffset.isChecked() params.set_param("Offset_OCC", occmode) - if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) - or self.ui.isCopy.isChecked()): + if ( + gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) + or self.ui.isCopy.isChecked() + ): copymode = True Gui.addModule("Draft") if self.npts: - _cmd = 'Draft.offset' - _cmd += '(' - _cmd += 'FreeCAD.ActiveDocument.' - _cmd += self.sel.Name + ', ' - _cmd += DraftVecUtils.toString(self.npts) + ', ' - _cmd += 'copy=' + str(copymode) - _cmd += ')' - _cmd_list = ['offst = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Offset"), - _cmd_list) + _cmd = "Draft.offset" + _cmd += "(" + _cmd += "FreeCAD.ActiveDocument." + _cmd += self.sel.Name + ", " + _cmd += DraftVecUtils.toString(self.npts) + ", " + _cmd += "copy=" + str(copymode) + _cmd += ")" + _cmd_list = ["offst = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Offset"), _cmd_list) elif self.dvec: if isinstance(self.dvec, float): delta = str(self.dvec) else: delta = DraftVecUtils.toString(self.dvec) - _cmd = 'Draft.offset' - _cmd += '(' - _cmd += 'FreeCAD.ActiveDocument.' - _cmd += self.sel.Name + ', ' - _cmd += delta + ', ' - _cmd += 'copy=' + str(copymode) + ', ' - _cmd += 'occ=' + str(occmode) - _cmd += ')' - _cmd_list = ['offst = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Offset"), - _cmd_list) + _cmd = "Draft.offset" + _cmd += "(" + _cmd += "FreeCAD.ActiveDocument." + _cmd += self.sel.Name + ", " + _cmd += delta + ", " + _cmd += "copy=" + str(copymode) + ", " + _cmd += "occ=" + str(occmode) + _cmd += ")" + _cmd_list = ["offst = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Offset"), _cmd_list) if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): self.extendedCopy = True else: @@ -298,7 +294,7 @@ class Offset(gui_base_original.Modifier): new_points = [] for old_point, new_point in zip(self.sel.Points, self.npts): diff_direction = new_point.sub(old_point).normalize() - new_points.append(old_point.add(diff_direction*rad)) + new_points.append(old_point.add(diff_direction * rad)) delta = DraftVecUtils.toString(new_points) else: self.dvec.normalize() @@ -311,24 +307,26 @@ class Offset(gui_base_original.Modifier): if self.ui.isCopy.isChecked(): copymode = True Gui.addModule("Draft") - _cmd = 'Draft.offset' - _cmd += '(' - _cmd += 'FreeCAD.ActiveDocument.' - _cmd += self.sel.Name + ', ' - _cmd += delta + ', ' - _cmd += 'copy=' + str(copymode) + ', ' - _cmd += 'occ=' + str(occmode) - _cmd += ')' - _cmd_list = ['offst = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Offset"), - _cmd_list) + _cmd = "Draft.offset" + _cmd += "(" + _cmd += "FreeCAD.ActiveDocument." + _cmd += self.sel.Name + ", " + _cmd += delta + ", " + _cmd += "copy=" + str(copymode) + ", " + _cmd += "occ=" + str(occmode) + _cmd += ")" + _cmd_list = ["offst = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Offset"), _cmd_list) self.finish() else: - _err(translate("Draft", - "Offset direction is not defined. Move the mouse on either side of the object first to indicate a direction.")) + _err( + translate( + "Draft", + "Offset direction is not defined. Move the mouse on either side of the object first to indicate a direction.", + ) + ) -Gui.addCommand('Draft_Offset', Offset()) +Gui.addCommand("Draft_Offset", Offset()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_orthoarray.py b/src/Mod/Draft/draftguitools/gui_orthoarray.py index b03c2c7209..b55e0c4487 100644 --- a/src/Mod/Draft/draftguitools/gui_orthoarray.py +++ b/src/Mod/Draft/draftguitools/gui_orthoarray.py @@ -51,9 +51,13 @@ class OrthoArray(gui_base.GuiCommandBase): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Array", - "MenuText": QT_TRANSLATE_NOOP("Draft_OrthoArray", "Array"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_OrthoArray", "Creates copies of the selected object in an orthogonal pattern")} + return { + "Pixmap": "Draft_Array", + "MenuText": QT_TRANSLATE_NOOP("Draft_OrthoArray", "Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_OrthoArray", "Creates copies of the selected object in an orthogonal pattern" + ), + } def Activated(self): """Execute when the command is called. @@ -67,8 +71,7 @@ class OrthoArray(gui_base.GuiCommandBase): self.mouse_event = coin.SoMouseButtonEvent.getClassTypeId() # self.callback_move = \ # self.view.addEventCallbackPivy(self.location, self.move) - self.callback_click = \ - self.view.addEventCallbackPivy(self.mouse_event, self.click) + self.callback_click = self.view.addEventCallbackPivy(self.mouse_event, self.click) self.ui = task_orthoarray.TaskPanelOrthoArray() # The calling class (this one) is saved in the object @@ -86,8 +89,10 @@ class OrthoArray(gui_base.GuiCommandBase): """ if event_cb: event = event_cb.getEvent() - if (event.getState() != coin.SoMouseButtonEvent.DOWN - or event.getButton() != coin.SoMouseButtonEvent.BUTTON1): + if ( + event.getState() != coin.SoMouseButtonEvent.DOWN + or event.getButton() != coin.SoMouseButtonEvent.BUTTON1 + ): return if self.ui and self.point: # The accept function of the interface @@ -113,6 +118,6 @@ class OrthoArray(gui_base.GuiCommandBase): self.finish() -Gui.addCommand('Draft_OrthoArray', OrthoArray()) +Gui.addCommand("Draft_OrthoArray", OrthoArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_patharray.py b/src/Mod/Draft/draftguitools/gui_patharray.py index 9cd6fece38..3f9189f125 100644 --- a/src/Mod/Draft/draftguitools/gui_patharray.py +++ b/src/Mod/Draft/draftguitools/gui_patharray.py @@ -69,9 +69,13 @@ class PathArray(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PathArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PathArray", "Path Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PathArray", "Creates copies of the selected object along a selected path")} + return { + "Pixmap": "Draft_PathArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PathArray", "Path Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PathArray", "Creates copies of the selected object along a selected path" + ), + } def Activated(self, name="Path array"): """Execute when the command is called.""" @@ -99,7 +103,12 @@ class PathArray(gui_base_original.Modifier): """Proceed with the command if one object was selected.""" sel = Gui.Selection.getSelectionEx() if len(sel) != 2: - _err(translate("draft","Select exactly 2 objects, the base object and the path object, before calling this command")) + _err( + translate( + "draft", + "Select exactly 2 objects, the base object and the path object, before calling this command", + ) + ) else: base_object = sel[0].Object path_object = sel[1].Object @@ -141,17 +150,19 @@ class PathArray(gui_base_original.Modifier): _cmd += "use_link=" + str(use_link) _cmd += ")" - _cmd_list = ["_obj_ = " + _cmd, - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] - self.commit(translate("draft","Create Path Array"), _cmd_list) + _cmd_list = [ + "_obj_ = " + _cmd, + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Path Array"), _cmd_list) # Commit the transaction and execute the commands # through the parent class self.finish() -Gui.addCommand('Draft_PathArray', PathArray()) +Gui.addCommand("Draft_PathArray", PathArray()) class PathLinkArray(PathArray): @@ -163,15 +174,20 @@ class PathLinkArray(PathArray): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PathLinkArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PathLinkArray", "Path Link Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PathLinkArray", "Creates linked copies of the selected object along a selected path")} + return { + "Pixmap": "Draft_PathLinkArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PathLinkArray", "Path Link Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PathLinkArray", + "Creates linked copies of the selected object along a selected path", + ), + } def Activated(self): """Execute when the command is called.""" super(PathLinkArray, self).Activated(name="Path link array") -Gui.addCommand('Draft_PathLinkArray', PathLinkArray()) +Gui.addCommand("Draft_PathLinkArray", PathLinkArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_pathtwistedarray.py b/src/Mod/Draft/draftguitools/gui_pathtwistedarray.py index e11dfd1b43..852f326c67 100644 --- a/src/Mod/Draft/draftguitools/gui_pathtwistedarray.py +++ b/src/Mod/Draft/draftguitools/gui_pathtwistedarray.py @@ -62,9 +62,14 @@ class PathTwistedArray(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PathTwistedArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PathTwistedArray", "Twisted Path Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PathTwistedArray", "Creates twisted copies of the selected object along a selected path")} + return { + "Pixmap": "Draft_PathTwistedArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PathTwistedArray", "Twisted Path Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PathTwistedArray", + "Creates twisted copies of the selected object along a selected path", + ), + } def Activated(self, name="Path twisted array"): """Execute when the command is called.""" @@ -76,7 +81,12 @@ class PathTwistedArray(gui_base_original.Modifier): """Proceed with the command if one object was selected.""" sel = Gui.Selection.getSelectionEx() if len(sel) != 2: - _err(translate("draft","Select exactly 2 objects, the base object and the path object, before calling this command")) + _err( + translate( + "draft", + "Select exactly 2 objects, the base object and the path object, before calling this command", + ) + ) else: base_object = sel[0].Object path_object = sel[1].Object @@ -95,17 +105,19 @@ class PathTwistedArray(gui_base_original.Modifier): _cmd += "use_link=" + str(use_link) _cmd += ")" - _cmd_list = ["_obj_ = " + _cmd, - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] - self.commit(translate("draft","Create Path Twisted Array"), _cmd_list) + _cmd_list = [ + "_obj_ = " + _cmd, + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Path Twisted Array"), _cmd_list) # Commit the transaction and execute the commands # through the parent class self.finish() -Gui.addCommand('Draft_PathTwistedArray', PathTwistedArray()) +Gui.addCommand("Draft_PathTwistedArray", PathTwistedArray()) class PathTwistedLinkArray(PathTwistedArray): @@ -117,16 +129,20 @@ class PathTwistedLinkArray(PathTwistedArray): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PathTwistedLinkArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PathTwistedLinkArray","Twisted Path Link Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PathTwistedLinkArray","Creates twisted linked copies of the selected object along a selected path")} + return { + "Pixmap": "Draft_PathTwistedLinkArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PathTwistedLinkArray", "Twisted Path Link Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PathTwistedLinkArray", + "Creates twisted linked copies of the selected object along a selected path", + ), + } def Activated(self): """Execute when the command is called.""" - super(PathTwistedLinkArray, - self).Activated(name="Path twisted link array") + super(PathTwistedLinkArray, self).Activated(name="Path twisted link array") -Gui.addCommand('Draft_PathTwistedLinkArray', PathTwistedLinkArray()) +Gui.addCommand("Draft_PathTwistedLinkArray", PathTwistedLinkArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_planeproxy.py b/src/Mod/Draft/draftguitools/gui_planeproxy.py index 2d2253ae72..56369a06c0 100644 --- a/src/Mod/Draft/draftguitools/gui_planeproxy.py +++ b/src/Mod/Draft/draftguitools/gui_planeproxy.py @@ -32,8 +32,7 @@ import FreeCADGui as Gui from draftutils import gui_utils __title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin") +__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin" __url__ = "https://www.freecad.org" @@ -42,9 +41,14 @@ class Draft_WorkingPlaneProxy: def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_PlaneProxy", - "MenuText": QT_TRANSLATE_NOOP("Draft_WorkingPlaneProxy", "Working Plane Proxy"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_WorkingPlaneProxy", "Creates a proxy object from the current working plane that allows to restore the camera position and visibility of objects")} + return { + "Pixmap": "Draft_PlaneProxy", + "MenuText": QT_TRANSLATE_NOOP("Draft_WorkingPlaneProxy", "Working Plane Proxy"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_WorkingPlaneProxy", + "Creates a proxy object from the current working plane that allows to restore the camera position and visibility of objects", + ), + } def IsActive(self): """Return True when this command should be available.""" @@ -61,6 +65,6 @@ class Draft_WorkingPlaneProxy: App.ActiveDocument.recompute() -Gui.addCommand('Draft_WorkingPlaneProxy', Draft_WorkingPlaneProxy()) +Gui.addCommand("Draft_WorkingPlaneProxy", Draft_WorkingPlaneProxy()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_pointarray.py b/src/Mod/Draft/draftguitools/gui_pointarray.py index f00bda7d3e..fcbaa041ab 100644 --- a/src/Mod/Draft/draftguitools/gui_pointarray.py +++ b/src/Mod/Draft/draftguitools/gui_pointarray.py @@ -63,9 +63,14 @@ class PointArray(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PointArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PointArray", "Point Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PointArray", "Creates copies of the selected object at the points of a point object")} + return { + "Pixmap": "Draft_PointArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PointArray", "Point Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PointArray", + "Creates copies of the selected object at the points of a point object", + ), + } def Activated(self, name="Point array"): """Execute when the command is called.""" @@ -92,32 +97,40 @@ class PointArray(gui_base_original.Modifier): """Proceed with the command if one object was selected.""" sel = Gui.Selection.getSelectionEx() if len(sel) != 2: - _err(translate("draft","Select exactly 2 objects, the base object and the point object, before calling this command")) + _err( + translate( + "draft", + "Select exactly 2 objects, the base object and the point object, before calling this command", + ) + ) else: base_object = sel[0].Object point_object = sel[1].Object extra = None - Gui.addModule('Draft') + Gui.addModule("Draft") _cmd = "Draft.make_point_array" _cmd += "(" _cmd += "App.ActiveDocument." + base_object.Name + ", " _cmd += "App.ActiveDocument." + point_object.Name + ", " _cmd += "extra=" + str(extra) + ", " - _cmd += 'use_link=' + str(self.use_link) + _cmd += "use_link=" + str(self.use_link) _cmd += ")" - _cmd_list = ["_obj_ = " + _cmd, - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] - self.commit(translate("draft","Create Point Array"), _cmd_list) + _cmd_list = [ + "_obj_ = " + _cmd, + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Point Array"), _cmd_list) # Commit the transaction and execute the commands # through the parent class self.finish() -Gui.addCommand('Draft_PointArray', PointArray()) +Gui.addCommand("Draft_PointArray", PointArray()) + class PointLinkArray(PointArray): """Gui Command for the PointLinkArray tool based on the PointArray tool.""" @@ -128,15 +141,20 @@ class PointLinkArray(PointArray): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_PointLinkArray', - 'MenuText': QT_TRANSLATE_NOOP("Draft_PointLinkArray", "Point Link Array"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_PointLinkArray", "Creates linked copies of the selected object at the points of a point object")} + return { + "Pixmap": "Draft_PointLinkArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PointLinkArray", "Point Link Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PointLinkArray", + "Creates linked copies of the selected object at the points of a point object", + ), + } def Activated(self): """Execute when the command is called.""" super(PointLinkArray, self).Activated(name="Point link array") -Gui.addCommand('Draft_PointLinkArray', PointLinkArray()) +Gui.addCommand("Draft_PointLinkArray", PointLinkArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_points.py b/src/Mod/Draft/draftguitools/gui_points.py index 1d6addcbd9..f5607213fd 100644 --- a/src/Mod/Draft/draftguitools/gui_points.py +++ b/src/Mod/Draft/draftguitools/gui_points.py @@ -59,9 +59,11 @@ class Point(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Point', - 'MenuText': QT_TRANSLATE_NOOP("Draft_Point", "Point"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Point", "Creates a point")} + return { + "Pixmap": "Draft_Point", + "MenuText": QT_TRANSLATE_NOOP("Draft_Point", "Point"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Point", "Creates a point"), + } def Activated(self): """Execute when the command is called.""" @@ -71,8 +73,12 @@ class Point(gui_base_original.Creator): self.ui.isRelative.hide() self.ui.continueCmd.show() # adding 2 callback functions - self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.click) - self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.move) + self.callbackClick = self.view.addEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), self.click + ) + self.callbackMove = self.view.addEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), self.move + ) def move(self, event_cb): """Execute as a callback when the pointer moves in the 3D view. @@ -108,34 +114,40 @@ class Point(gui_base_original.Creator): if not self.ui.mouse: return event = event_cb.getEvent() - if (event.getState() != coin.SoMouseButtonEvent.DOWN or - event.getButton() != event.BUTTON1): + if ( + event.getState() != coin.SoMouseButtonEvent.DOWN + or event.getButton() != event.BUTTON1 + ): return if self.point: Gui.addModule("Draft") if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Vertex", "Point")' - _cmd_list = ['point = ' + _cmd, - 'point.X = ' + str(self.point[0]), - 'point.Y = ' + str(self.point[1]), - 'point.Z = ' + str(self.point[2]), - 'Draft.autogroup(point)', - 'Draft.select(point)', - 'FreeCAD.ActiveDocument.recompute()'] + _cmd_list = [ + "point = " + _cmd, + "point.X = " + str(self.point[0]), + "point.Y = " + str(self.point[1]), + "point.Z = " + str(self.point[2]), + "Draft.autogroup(point)", + "Draft.select(point)", + "FreeCAD.ActiveDocument.recompute()", + ] self.commit(translate("draft", "Create Point"), _cmd_list) else: # Insert a Draft point - _cmd = 'Draft.make_point' - _cmd += '(' - _cmd += str(self.point[0]) + ', ' - _cmd += str(self.point[1]) + ', ' + _cmd = "Draft.make_point" + _cmd += "(" + _cmd += str(self.point[0]) + ", " + _cmd += str(self.point[1]) + ", " _cmd += str(self.point[2]) - _cmd += ')' - _cmd_list = ['point = ' + _cmd, - 'Draft.autogroup(point)', - 'FreeCAD.ActiveDocument.recompute()'] + _cmd += ")" + _cmd_list = [ + "point = " + _cmd, + "Draft.autogroup(point)", + "FreeCAD.ActiveDocument.recompute()", + ] self.commit(translate("draft", "Create Point"), _cmd_list) self.finish(cont=None) @@ -150,9 +162,13 @@ class Point(gui_base_original.Creator): """ try: if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + self.view.removeEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick + ) if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + self.view.removeEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), self.callbackMove + ) if self.callbackClick or self.callbackMove: # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: gui_utils.end_all_events() @@ -166,12 +182,14 @@ class Point(gui_base_original.Creator): self.Activated() def get_hints(self): - return [Gui.InputHint(translate("draft", "%1 pick point"), Gui.UserInput.MouseLeft)] \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + return ( + [Gui.InputHint(translate("draft", "%1 pick point"), Gui.UserInput.MouseLeft)] + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Point', Point()) +Gui.addCommand("Draft_Point", Point()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_polararray.py b/src/Mod/Draft/draftguitools/gui_polararray.py index 9a0248998b..4faf576636 100644 --- a/src/Mod/Draft/draftguitools/gui_polararray.py +++ b/src/Mod/Draft/draftguitools/gui_polararray.py @@ -51,9 +51,13 @@ class PolarArray(gui_base.GuiCommandBase): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_PolarArray", - "MenuText": QT_TRANSLATE_NOOP("Draft_PolarArray", "Polar Array"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_PolarArray", "Creates copies of the selected object in a polar pattern")} + return { + "Pixmap": "Draft_PolarArray", + "MenuText": QT_TRANSLATE_NOOP("Draft_PolarArray", "Polar Array"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_PolarArray", "Creates copies of the selected object in a polar pattern" + ), + } def Activated(self): """Execute when the command is called. @@ -65,10 +69,8 @@ class PolarArray(gui_base.GuiCommandBase): self.location = coin.SoLocation2Event.getClassTypeId() self.mouse_event = coin.SoMouseButtonEvent.getClassTypeId() - self.callback_move = \ - self.view.addEventCallbackPivy(self.location, self.move) - self.callback_click = \ - self.view.addEventCallbackPivy(self.mouse_event, self.click) + self.callback_move = self.view.addEventCallbackPivy(self.location, self.move) + self.callback_click = self.view.addEventCallbackPivy(self.mouse_event, self.click) self.ui = task_polararray.TaskPanelPolarArray() # The calling class (this one) is saved in the object @@ -99,8 +101,10 @@ class PolarArray(gui_base.GuiCommandBase): """ if event_cb: event = event_cb.getEvent() - if (event.getState() != coin.SoMouseButtonEvent.DOWN - or event.getButton() != coin.SoMouseButtonEvent.BUTTON1): + if ( + event.getState() != coin.SoMouseButtonEvent.DOWN + or event.getButton() != coin.SoMouseButtonEvent.BUTTON1 + ): return if self.ui and self.point: # The accept function of the interface @@ -128,6 +132,6 @@ class PolarArray(gui_base.GuiCommandBase): self.finish() -Gui.addCommand('Draft_PolarArray', PolarArray()) +Gui.addCommand("Draft_PolarArray", PolarArray()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_polygons.py b/src/Mod/Draft/draftguitools/gui_polygons.py index e437458712..ad19dd2955 100644 --- a/src/Mod/Draft/draftguitools/gui_polygons.py +++ b/src/Mod/Draft/draftguitools/gui_polygons.py @@ -52,10 +52,14 @@ class Polygon(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Polygon', - 'Accel': "P, G", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Polygon", "Polygon"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Polygon", "Creates a regular polygon (triangle, square, pentagon…)")} + return { + "Pixmap": "Draft_Polygon", + "Accel": "P, G", + "MenuText": QT_TRANSLATE_NOOP("Draft_Polygon", "Polygon"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Polygon", "Creates a regular polygon (triangle, square, pentagon…)" + ), + } def Activated(self, numVertices=None): """Execute when the command is called.""" @@ -107,6 +111,7 @@ class Polygon(gui_base_original.Creator): from the 3D view. """ import DraftGeomUtils + if self.ui.numFaces.value() != self.numVertices: self.polygonTrack.setNumVertices(self.ui.numFaces.value()) self.numVertices = self.ui.numFaces.value() @@ -121,8 +126,7 @@ class Polygon(gui_base_original.Creator): # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: - viewdelta = DraftVecUtils.project(self.point.sub(self.center), - self.wp.axis) + viewdelta = DraftVecUtils.project(self.point.sub(self.center), self.wp.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center @@ -136,60 +140,61 @@ class Polygon(gui_base_original.Creator): self.ui.switchUi(False) else: # choose radius if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], - self.tangents[1], - self.point) + cir = DraftGeomUtils.circleFrom2tan1pt( + self.tangents[0], self.tangents[1], self.point + ) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center elif self.tangents and self.tanpoints: - cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], - self.tanpoints[0], - self.point) + cir = DraftGeomUtils.circleFrom1tan2pt( + self.tangents[0], self.tanpoints[0], self.point + ) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): if not self.altdown: self.altdown = True - snapped = self.view.getObjectInfo((arg["Position"][0], - arg["Position"][1])) + snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(snapped["Object"]) + num = int(snapped["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], - self.tangents[1], - ed) + cir = DraftGeomUtils.circleFrom3tan( + self.tangents[0], self.tangents[1], ed + ) cl = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = cl.Center self.rad = cl.Radius else: - self.rad = self.center.add(DraftGeomUtils.findDistance(self.center,ed).sub(self.center)).Length + self.rad = self.center.add( + DraftGeomUtils.findDistance(self.center, ed).sub(self.center) + ).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: if self.altdown: self.altdown = False self.rad = DraftVecUtils.dist(self.point, self.center) - self.ui.setRadiusValue(self.rad, 'Length') + self.ui.setRadiusValue(self.rad, "Length") gui_tool_utils.redraw3DView() - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["State"] == "DOWN" - and arg["Button"] == "BUTTON1"): # mouse click + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1" + ): # mouse click if self.point: if self.step == 0: # choose center if (not self.node) and (not self.support): gui_tool_utils.getSupport(arg) - (self.point, - ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) + (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): - snapped = self.view.getObjectInfo((arg["Position"][0], - arg["Position"][1])) + snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge')) - 1 + ob = self.doc.getObject(snapped["Object"]) + num = int(snapped["Component"].lstrip("Edge")) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: @@ -221,39 +226,41 @@ class Polygon(gui_base_original.Creator): if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object Gui.addModule("Part") - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::RegularPolygon","RegularPolygon")' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + DraftVecUtils.toString(self.center), - 'pol = ' + _cmd, - 'pol.Polygon = ' + str(self.ui.numFaces.value()), - 'pol.Circumradius = ' + str(self.rad), - 'pol.Placement = pl', - 'Draft.autogroup(pol)', - 'Draft.select(pol)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Polygon (Part)"), - _cmd_list) + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + DraftVecUtils.toString(self.center), + "pol = " + _cmd, + "pol.Polygon = " + str(self.ui.numFaces.value()), + "pol.Circumradius = " + str(self.rad), + "pol.Placement = pl", + "Draft.autogroup(pol)", + "Draft.select(pol)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Polygon (Part)"), _cmd_list) else: # Insert a Draft polygon - _cmd = 'Draft.make_polygon' - _cmd += '(' - _cmd += str(self.ui.numFaces.value()) + ', ' - _cmd += 'radius=' + str(self.rad) + ', ' - _cmd += 'inscribed=True, ' - _cmd += 'placement=pl, ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + DraftVecUtils.toString(self.center), - 'pol = ' + _cmd, - 'Draft.autogroup(pol)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Polygon"), - _cmd_list) + _cmd = "Draft.make_polygon" + _cmd += "(" + _cmd += str(self.ui.numFaces.value()) + ", " + _cmd += "radius=" + str(self.rad) + ", " + _cmd += "inscribed=True, " + _cmd += "placement=pl, " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + DraftVecUtils.toString(self.center), + "pol = " + _cmd, + "Draft.autogroup(pol)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Polygon"), _cmd_list) self.finish(cont=None) def numericInput(self, numx, numy, numz): @@ -281,18 +288,14 @@ class Polygon(gui_base_original.Creator): self.rad = rad if len(self.tangents) == 2: - cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], - self.tangents[1], - rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: _c = DraftGeomUtils.findClosestCircle(self.center, cir) self.center = _c.Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0], - self.tanpoints[0], - rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0], self.tanpoints[0], rad) if self.center: _c = DraftGeomUtils.findClosestCircle(self.center, cir) self.center = _c.Center @@ -302,19 +305,17 @@ class Polygon(gui_base_original.Creator): def get_hints(self): if self.step == 0: - hints = [ - Gui.InputHint(translate("draft", "%1 pick center"), Gui.UserInput.MouseLeft) - ] + hints = [Gui.InputHint(translate("draft", "%1 pick center"), Gui.UserInput.MouseLeft)] else: - hints = [ - Gui.InputHint(translate("draft", "%1 pick radius"), Gui.UserInput.MouseLeft) - ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + hints = [Gui.InputHint(translate("draft", "%1 pick radius"), Gui.UserInput.MouseLeft)] + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Polygon', Polygon()) +Gui.addCommand("Draft_Polygon", Polygon()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_rectangles.py b/src/Mod/Draft/draftguitools/gui_rectangles.py index ecdaf15019..49d4058b14 100644 --- a/src/Mod/Draft/draftguitools/gui_rectangles.py +++ b/src/Mod/Draft/draftguitools/gui_rectangles.py @@ -49,10 +49,12 @@ class Rectangle(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Rectangle', - 'Accel': "R, E", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Rectangle", "Rectangle"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Rectangle", "Creates a 2-point rectangle")} + return { + "Pixmap": "Draft_Rectangle", + "Accel": "R, E", + "MenuText": QT_TRANSLATE_NOOP("Draft_Rectangle", "Rectangle"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Rectangle", "Creates a 2-point rectangle"), + } def Activated(self): """Execute when the command is called.""" @@ -109,37 +111,39 @@ class Rectangle(gui_base_original.Creator): Gui.addModule("Draft") if params.get_param("UsePartPrimitives"): # Insert a Part::Primitive object - _cmd = 'FreeCAD.ActiveDocument.' + _cmd = "FreeCAD.ActiveDocument." _cmd += 'addObject("Part::Plane", "Plane")' - _cmd_list = ['plane = ' + _cmd, - 'plane.Length = ' + str(length), - 'plane.Width = ' + str(height), - 'pl = FreeCAD.Placement()', - 'pl.Rotation.Q=' + rot, - 'pl.Base = ' + DraftVecUtils.toString(base), - 'plane.Placement = pl', - 'Draft.autogroup(plane)', - 'Draft.select(plane)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Plane"), - _cmd_list) + _cmd_list = [ + "plane = " + _cmd, + "plane.Length = " + str(length), + "plane.Width = " + str(height), + "pl = FreeCAD.Placement()", + "pl.Rotation.Q=" + rot, + "pl.Base = " + DraftVecUtils.toString(base), + "plane.Placement = pl", + "Draft.autogroup(plane)", + "Draft.select(plane)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Plane"), _cmd_list) else: - _cmd = 'Draft.make_rectangle' - _cmd += '(' - _cmd += 'length=' + str(length) + ', ' - _cmd += 'height=' + str(height) + ', ' - _cmd += 'placement=pl, ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + DraftVecUtils.toString(base), - 'rec = ' + _cmd, - 'Draft.autogroup(rec)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Rectangle"), - _cmd_list) + _cmd = "Draft.make_rectangle" + _cmd += "(" + _cmd += "length=" + str(length) + ", " + _cmd += "height=" + str(height) + ", " + _cmd += "placement=pl, " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + DraftVecUtils.toString(base), + "rec = " + _cmd, + "Draft.autogroup(rec)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Rectangle"), _cmd_list) except Exception: _err("Draft: error delaying commit") self.finish(cont=None) @@ -164,9 +168,11 @@ class Rectangle(gui_base_original.Creator): self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg, noTracker=True) self.rect.update(self.point) gui_tool_utils.redraw3DView() - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["State"] == "DOWN" - and arg["Button"] == "BUTTON1"): + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1" + ): if arg["Position"] == self.pos: self.finish(cont=None) @@ -213,12 +219,14 @@ class Rectangle(gui_base_original.Creator): hints = [ Gui.InputHint(translate("draft", "%1 pick opposite point"), Gui.UserInput.MouseLeft) ] - return hints \ - + gui_tool_utils._get_hint_xyz_constrain() \ - + gui_tool_utils._get_hint_mod_constrain() \ + return ( + hints + + gui_tool_utils._get_hint_xyz_constrain() + + gui_tool_utils._get_hint_mod_constrain() + gui_tool_utils._get_hint_mod_snap() + ) -Gui.addCommand('Draft_Rectangle', Rectangle()) +Gui.addCommand("Draft_Rectangle", Rectangle()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_rotate.py b/src/Mod/Draft/draftguitools/gui_rotate.py index 7651e8c08b..197f87ab84 100644 --- a/src/Mod/Draft/draftguitools/gui_rotate.py +++ b/src/Mod/Draft/draftguitools/gui_rotate.py @@ -52,10 +52,15 @@ class Rotate(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Rotate", - "Accel": "R, O", - "MenuText": QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Rotate", "Rotates the selected objects.\nIf the \"Copy\" option is active, it will create rotated copies.")} + return { + "Pixmap": "Draft_Rotate", + "Accel": "R, O", + "MenuText": QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Rotate", + 'Rotates the selected objects.\nIf the "Copy" option is active, it will create rotated copies.', + ), + } def Activated(self): """Execute when the command is called.""" @@ -79,7 +84,7 @@ class Rotate(gui_base_original.Modifier): if self.call: self.view.removeEventCallback("SoEvent", self.call) self.selection = Gui.Selection.getSelectionEx("", 0) - Gui.doCommand("selection = FreeCADGui.Selection.getSelectionEx(\"\", 0)") + Gui.doCommand('selection = FreeCADGui.Selection.getSelectionEx("", 0)') self.step = 0 self.center = None self.point = None @@ -106,9 +111,11 @@ class Rotate(gui_base_original.Modifier): pass elif arg["Type"] == "SoLocation2Event": self.handle_mouse_move_event(arg) - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["State"] == "DOWN" - and arg["Button"] == "BUTTON1"): + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1" + ): self.handle_mouse_click_event(arg) def _get_angle(self): @@ -134,11 +141,7 @@ class Rotate(gui_base_original.Modifier): # Project self.point on a plane that is parallel to the wp and that # passes through self.center. self.point = geometry.project_point_on_plane( - self.point, - self.center, - self.wp.axis, - direction=None, - force_projection=True + self.point, self.center, self.wp.axis, direction=None, force_projection=True ) if self.extendedCopy: if not gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): @@ -183,7 +186,9 @@ class Rotate(gui_base_original.Modifier): self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) self.ui.makeFace.hide() self.ui.labelRadius.setText(translate("draft", "Base angle")) - self.ui.radiusValue.setToolTip(translate("draft", "The base angle to start the rotation from")) + self.ui.radiusValue.setToolTip( + translate("draft", "The base angle to start the rotation from") + ) self.arctrack.setCenter(self.center) for ghost in self.ghosts: ghost.center(self.center) @@ -196,7 +201,12 @@ class Rotate(gui_base_original.Modifier): """Set the starting point of the rotation.""" self.firstangle = self._get_angle() self.ui.labelRadius.setText(translate("draft", "Rotation")) - self.ui.radiusValue.setToolTip(translate("draft", "The amount of rotation to perform.\nThe final angle will be the base angle plus this amount.")) + self.ui.radiusValue.setToolTip( + translate( + "draft", + "The amount of rotation to perform.\nThe final angle will be the base angle plus this amount.", + ) + ) self.arctrack.on() self.arctrack.setStartPoint(self.point) for ghost in self.ghosts: @@ -208,8 +218,10 @@ class Rotate(gui_base_original.Modifier): """Set the rotation angle.""" self.angle = self._get_angle() if self.angle != 0: - self.rotate(self.ui.isCopy.isChecked() - or gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())) + self.rotate( + self.ui.isCopy.isChecked() + or gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()) + ) if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): self.extendedCopy = True else: @@ -225,7 +237,9 @@ class Rotate(gui_base_original.Modifier): if not self.ghosts: _err(translate("draft", "No valid subelements selected")) else: - objs, places, _ = utils._modifiers_process_selection(self.selection, copy, add_movable_children=(not copy)) + objs, places, _ = utils._modifiers_process_selection( + self.selection, copy, add_movable_children=(not copy) + ) self.ghosts = [trackers.ghostTracker(objs, parent_places=places)] if self.center: for ghost in self.ghosts: @@ -234,6 +248,7 @@ class Rotate(gui_base_original.Modifier): def get_subelement_ghosts(self, selection, copy): """Get ghost for the subelements (vertices, edges).""" import Part + ghosts = [] for sel in selection: for sub in sel.SubElementNames if sel.SubElementNames else [""]: @@ -290,7 +305,9 @@ class Rotate(gui_base_original.Modifier): self.ui.radiusUi() self.ui.makeFace.hide() self.ui.labelRadius.setText(translate("draft", "Base angle")) - self.ui.radiusValue.setToolTip(translate("draft", "The base angle to start the rotation from")) + self.ui.radiusValue.setToolTip( + translate("draft", "The base angle to start the rotation from") + ) self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) self.step = 1 _toolmsg(translate("draft", "Pick base angle")) @@ -303,7 +320,12 @@ class Rotate(gui_base_original.Modifier): """ if self.step == 1: self.ui.labelRadius.setText(translate("draft", "Rotation")) - self.ui.radiusValue.setToolTip(translate("draft", "The amount of rotation to perform.\nThe final angle will be the base angle plus this amount.")) + self.ui.radiusValue.setToolTip( + translate( + "draft", + "The amount of rotation to perform.\nThe final angle will be the base angle plus this amount.", + ) + ) self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) self.firstangle = math.radians(rad) self.arctrack.setStartAngle(self.firstangle) @@ -318,6 +340,6 @@ class Rotate(gui_base_original.Modifier): self.finish(cont=None) -Gui.addCommand('Draft_Rotate', Rotate()) +Gui.addCommand("Draft_Rotate", Rotate()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_scale.py b/src/Mod/Draft/draftguitools/gui_scale.py index 0118343615..62fb932161 100644 --- a/src/Mod/Draft/draftguitools/gui_scale.py +++ b/src/Mod/Draft/draftguitools/gui_scale.py @@ -62,10 +62,14 @@ class Scale(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Scale", - "Accel": "S, C", - "MenuText": QT_TRANSLATE_NOOP("Draft_Scale", "Scale"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Scale", "Scales the selected objects from a base point")} + return { + "Pixmap": "Draft_Scale", + "Accel": "S, C", + "MenuText": QT_TRANSLATE_NOOP("Draft_Scale", "Scale"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Scale", "Scales the selected objects from a base point" + ), + } def Activated(self): """Execute when the command is called.""" @@ -88,9 +92,9 @@ class Scale(gui_base_original.Modifier): if self.call: self.view.removeEventCallback("SoEvent", self.call) self.selection = Gui.Selection.getSelectionEx("", 0) - Gui.doCommand("selection = FreeCADGui.Selection.getSelectionEx(\"\", 0)") + Gui.doCommand('selection = FreeCADGui.Selection.getSelectionEx("", 0)') self.refs = [] - self.ui.pointUi(title=translate("draft",self.featureName), icon="Draft_Scale") + self.ui.pointUi(title=translate("draft", self.featureName), icon="Draft_Scale") self.ui.isRelative.hide() self.ui.xValue.setFocus() self.ui.xValue.selectAll() @@ -116,12 +120,15 @@ class Scale(gui_base_original.Modifier): if not self.ghosts: _err(translate("draft", "No valid subelements selected")) else: - objs, places, _ = utils._modifiers_process_selection(self.selection, (copy or clone), scale=True) + objs, places, _ = utils._modifiers_process_selection( + self.selection, (copy or clone), scale=True + ) self.ghosts = [trackers.ghostTracker(objs, parent_places=places)] def get_subelement_ghosts(self, selection, copy): """Get ghost for the subelements (vertices, edges).""" import Part + ghosts = [] for sel in selection: for sub in sel.SubElementNames if sel.SubElementNames else [""]: @@ -135,7 +142,7 @@ class Scale(gui_base_original.Modifier): delta = App.Vector(x, y, z) # ScaleRelative option removed in v1.1 as it does not work properly: # if rel: - # delta = self.wp.get_local_coords(delta) + # delta = self.wp.get_local_coords(delta) for ghost in self.ghosts: ghost.scale(delta) # calculate a correction factor depending on the scaling center @@ -170,10 +177,12 @@ class Scale(gui_base_original.Modifier): self.finish() elif arg["Type"] == "SoLocation2Event": self.handle_mouse_move_event(arg) - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["State"] == "DOWN" - and arg["Button"] == "BUTTON1" - and self.point): + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1" + and self.point + ): self.handle_mouse_click_event() def handle_mouse_move_event(self, arg): @@ -204,7 +213,7 @@ class Scale(gui_base_original.Modifier): self.delta = App.Vector(sx, sy, sz) # ScaleRelative option removed in v1.1 as it does not work properly: # if self.task.relative.isChecked(): - # self.delta = self.wp.get_local_coords(self.delta) + # self.delta = self.wp.get_local_coords(self.delta) self.center = self.node[0] if self.task.isCopy.isChecked(): cmd_name = translate("draft", "Copy") @@ -255,7 +264,7 @@ class Scale(gui_base_original.Modifier): if hasattr(self, "task"): if self.task: self.task.lock.setChecked(True) - self.task.setValue(d2/d1) + self.task.setValue(d2 / d1) def finish(self, cont=False): """Terminate the operation.""" @@ -265,6 +274,6 @@ class Scale(gui_base_original.Modifier): super().finish() -Gui.addCommand('Draft_Scale', Scale()) +Gui.addCommand("Draft_Scale", Scale()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_selectplane.py b/src/Mod/Draft/draftguitools/gui_selectplane.py index 6b0288c127..75152caafb 100644 --- a/src/Mod/Draft/draftguitools/gui_selectplane.py +++ b/src/Mod/Draft/draftguitools/gui_selectplane.py @@ -44,8 +44,7 @@ from draftutils.todo import todo from draftutils.translate import translate __title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools" -__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " - "Dmitry Chigrin") +__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, " "Dmitry Chigrin" __url__ = "https://www.freecad.org" @@ -54,10 +53,15 @@ class Draft_SelectPlane: def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_SelectPlane", - "Accel": "W, P", - "MenuText": QT_TRANSLATE_NOOP("Draft_SelectPlane", "Working Plane"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_SelectPlane", "Defines the working plane from 3 vertices, 1 or more shapes, or an object")} + return { + "Pixmap": "Draft_SelectPlane", + "Accel": "W, P", + "MenuText": QT_TRANSLATE_NOOP("Draft_SelectPlane", "Working Plane"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_SelectPlane", + "Defines the working plane from 3 vertices, 1 or more shapes, or an object", + ), + } def IsActive(self): """Return True when this command should be available.""" @@ -126,9 +130,9 @@ class Draft_SelectPlane: form.buttonPrevious.clicked.connect(self.on_click_previous) form.buttonNext.clicked.connect(self.on_click_next) form.fieldOffset.textEdited.connect(self.on_set_offset) - if hasattr(form.checkCenter, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(form.checkCenter, "checkStateChanged"): # Qt version >= 6.7.0 form.checkCenter.checkStateChanged.connect(self.on_set_center) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 form.checkCenter.stateChanged.connect(self.on_set_center) form.fieldGridSpacing.textEdited.connect(self.on_set_grid_size) form.fieldGridMainLine.valueChanged.connect(self.on_set_main_line) @@ -150,9 +154,12 @@ class Draft_SelectPlane: # Execute the actual task panel delayed to catch possible active Draft command todo.delay(Gui.Control.showDialog, self.taskd) todo.delay(form.setFocus, None) - _toolmsg(translate( + _toolmsg( + translate( "draft", - "Select 3 vertices, one or more shapes or an object to define a working plane")) + "Select 3 vertices, one or more shapes or an object to define a working plane", + ) + ) self.call = self.view.addEventCallback("SoEvent", self.action) def finish(self): @@ -178,9 +185,11 @@ class Draft_SelectPlane: """Set the callbacks for the view.""" if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": self.reject() - if arg["Type"] == "SoMouseButtonEvent" \ - and (arg["State"] == "UP") \ - and (arg["Button"] == "BUTTON1"): + if ( + arg["Type"] == "SoMouseButtonEvent" + and (arg["State"] == "UP") + and (arg["Button"] == "BUTTON1") + ): self.check_selection() def check_selection(self): @@ -211,13 +220,14 @@ class Draft_SelectPlane: def on_click_move(self): sels = Gui.Selection.getSelectionEx("", 0) - if len(sels) == 1 \ - and len(sels[0].SubObjects) == 1 \ - and sels[0].SubObjects[0].ShapeType == "Vertex": - vert = Part.getShape(sels[0].Object, - sels[0].SubElementNames[0], - needSubElement=True, - retType=0) + if ( + len(sels) == 1 + and len(sels[0].SubObjects) == 1 + and sels[0].SubObjects[0].ShapeType == "Vertex" + ): + vert = Part.getShape( + sels[0].Object, sels[0].SubElementNames[0], needSubElement=True, retType=0 + ) self.wp.set_to_position(vert.Point) Gui.Selection.clearSelection() self.finish() @@ -287,6 +297,7 @@ class Draft_SelectPlane: color = utils.argb_to_rgba(self.taskd.form.buttonColor.property("color").rgba()) params.set_param("gridColor", color) -Gui.addCommand('Draft_SelectPlane', Draft_SelectPlane()) + +Gui.addCommand("Draft_SelectPlane", Draft_SelectPlane()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_setstyle.py b/src/Mod/Draft/draftguitools/gui_setstyle.py index 5699571350..5d6982966b 100644 --- a/src/Mod/Draft/draftguitools/gui_setstyle.py +++ b/src/Mod/Draft/draftguitools/gui_setstyle.py @@ -40,19 +40,21 @@ from FreeCAD import Units as U from draftutils import params from draftutils import utils -def QT_TRANSLATE_NOOP(ctx,txt): + +def QT_TRANSLATE_NOOP(ctx, txt): return txt + + translate = App.Qt.translate __title__ = "FreeCAD Draft Workbench GUI Tools - Styling tools" -__author__ = ("Yorik van Havre") +__author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" PRESETPATH = os.path.join(App.getUserAppDataDir(), "Draft", "StylePresets.json") class Draft_SetStyle: - """The Draft_SetStyle FreeCAD command definition.""" def GetResources(self): @@ -61,7 +63,9 @@ class Draft_SetStyle: "Pixmap": "Draft_Apply", "Accel": "S, S", "MenuText": QT_TRANSLATE_NOOP("Draft_SetStyle", "Set Style"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_SetStyle", "Sets the default style and can apply the style to objects") + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_SetStyle", "Sets the default style and can apply the style to objects" + ), } def Activated(self): @@ -70,50 +74,81 @@ class Draft_SetStyle: class Draft_SetStyle_TaskPanel: - """The task panel for the Draft_SetStyle command""" def __init__(self): self.form = Gui.PySideUic.loadUi(":/ui/TaskPanel_SetStyle.ui") - self.form.setWindowIcon(QtGui.QIcon.fromTheme("gtk-apply", QtGui.QIcon(":/icons/Draft_Apply.svg"))) + self.form.setWindowIcon( + QtGui.QIcon.fromTheme("gtk-apply", QtGui.QIcon(":/icons/Draft_Apply.svg")) + ) - self.form.saveButton.setIcon(QtGui.QIcon.fromTheme("gtk-save", QtGui.QIcon(":/icons/document-save.svg"))) - self.form.applyButton.setIcon(QtGui.QIcon.fromTheme("gtk-apply", QtGui.QIcon(":/icons/Draft_Apply.svg"))) + self.form.saveButton.setIcon( + QtGui.QIcon.fromTheme("gtk-save", QtGui.QIcon(":/icons/document-save.svg")) + ) + self.form.applyButton.setIcon( + QtGui.QIcon.fromTheme("gtk-apply", QtGui.QIcon(":/icons/Draft_Apply.svg")) + ) self.form.annotButton.setIcon(QtGui.QIcon(":/icons/Draft_Text.svg")) - self.form.ShapeColor.setProperty("color", self.getColor(params.get_param_view("DefaultShapeColor"))) - self.form.AmbientColor.setProperty("color", self.getColor(params.get_param_view("DefaultAmbientColor"))) - self.form.EmissiveColor.setProperty("color", self.getColor(params.get_param_view("DefaultEmissiveColor"))) - self.form.SpecularColor.setProperty("color", self.getColor(params.get_param_view("DefaultSpecularColor"))) + self.form.ShapeColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultShapeColor")) + ) + self.form.AmbientColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultAmbientColor")) + ) + self.form.EmissiveColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultEmissiveColor")) + ) + self.form.SpecularColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultSpecularColor")) + ) self.form.Transparency.setValue(params.get_param_view("DefaultShapeTransparency")) self.form.Shininess.setValue(params.get_param_view("DefaultShapeShininess")) - self.form.LineColor.setProperty("color", self.getColor(params.get_param_view("DefaultShapeLineColor"))) + self.form.LineColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultShapeLineColor")) + ) self.form.LineWidth.setValue(params.get_param_view("DefaultShapeLineWidth")) - self.form.PointColor.setProperty("color", self.getColor(params.get_param_view("DefaultShapeVertexColor"))) + self.form.PointColor.setProperty( + "color", self.getColor(params.get_param_view("DefaultShapeVertexColor")) + ) self.form.PointSize.setValue(params.get_param_view("DefaultShapePointSize")) self.form.DrawStyle.setCurrentIndex(params.get_param("DefaultDrawStyle")) self.form.DisplayMode.setCurrentIndex(params.get_param("DefaultDisplayMode")) - self.form.TextColor.setProperty("color", self.getColor(params.get_param("DefaultTextColor"))) + self.form.TextColor.setProperty( + "color", self.getColor(params.get_param("DefaultTextColor")) + ) self.form.TextFont.setCurrentFont(QtGui.QFont(params.get_param("textfont"))) self.form.TextSize.setText(U.Quantity(params.get_param("textheight"), U.Length).UserString) self.form.LineSpacing.setValue(params.get_param("LineSpacing")) self.form.ScaleMultiplier.setValue(params.get_param("DefaultAnnoScaleMultiplier")) - self.form.AnnoLineColor.setProperty("color", self.getColor(params.get_param("DefaultAnnoLineColor"))) + self.form.AnnoLineColor.setProperty( + "color", self.getColor(params.get_param("DefaultAnnoLineColor")) + ) self.form.AnnoLineWidth.setValue(params.get_param("DefaultAnnoLineWidth")) self.form.ArrowStyleStart.setCurrentIndex(params.get_param("dimsymbolstart")) - self.form.ArrowSizeStart.setText(U.Quantity(params.get_param("arrowsizestart"), U.Length).UserString) + self.form.ArrowSizeStart.setText( + U.Quantity(params.get_param("arrowsizestart"), U.Length).UserString + ) self.form.ArrowStyleEnd.setCurrentIndex(params.get_param("dimsymbolend")) - self.form.ArrowSizeEnd.setText(U.Quantity(params.get_param("arrowsizeend"), U.Length).UserString) + self.form.ArrowSizeEnd.setText( + U.Quantity(params.get_param("arrowsizeend"), U.Length).UserString + ) self.form.ShowUnit.setChecked(params.get_param("showUnit")) self.form.UnitOverride.setText(params.get_param("overrideUnit")) - self.form.DimOvershoot.setText(U.Quantity(params.get_param("dimovershoot"), U.Length).UserString) + self.form.DimOvershoot.setText( + U.Quantity(params.get_param("dimovershoot"), U.Length).UserString + ) self.form.ExtLines.setText(U.Quantity(params.get_param("extlines"), U.Length).UserString) - self.form.ExtOvershoot.setText(U.Quantity(params.get_param("extovershoot"), U.Length).UserString) - self.form.TextSpacing.setText(U.Quantity(params.get_param("dimspacing"), U.Length).UserString) + self.form.ExtOvershoot.setText( + U.Quantity(params.get_param("extovershoot"), U.Length).UserString + ) + self.form.TextSpacing.setText( + U.Quantity(params.get_param("dimspacing"), U.Length).UserString + ) self.form.saveButton.clicked.connect(self.onSaveStyle) self.form.applyButton.clicked.connect(self.onApplyStyle) @@ -143,38 +178,35 @@ class Draft_SetStyle_TaskPanel: def getValues(self): return { - "ShapeColor": utils.argb_to_rgba(self.form.ShapeColor.property("color").rgba()), - "AmbientColor": utils.argb_to_rgba(self.form.AmbientColor.property("color").rgba()), - "EmissiveColor": utils.argb_to_rgba(self.form.EmissiveColor.property("color").rgba()), - "SpecularColor": utils.argb_to_rgba(self.form.SpecularColor.property("color").rgba()), - "Transparency": self.form.Transparency.value(), - "Shininess": self.form.Shininess.value(), - - "LineColor": utils.argb_to_rgba(self.form.LineColor.property("color").rgba()), - "LineWidth": self.form.LineWidth.value(), - "PointColor": utils.argb_to_rgba(self.form.PointColor.property("color").rgba()), - "PointSize": self.form.PointSize.value(), - "DrawStyle": self.form.DrawStyle.currentIndex(), - "DisplayMode": self.form.DisplayMode.currentIndex(), - - "TextColor": utils.argb_to_rgba(self.form.TextColor.property("color").rgba()), - "TextFont": self.form.TextFont.currentFont().family(), - "TextSize": U.Quantity(self.form.TextSize.text()).Value, - "LineSpacing": self.form.LineSpacing.value(), + "ShapeColor": utils.argb_to_rgba(self.form.ShapeColor.property("color").rgba()), + "AmbientColor": utils.argb_to_rgba(self.form.AmbientColor.property("color").rgba()), + "EmissiveColor": utils.argb_to_rgba(self.form.EmissiveColor.property("color").rgba()), + "SpecularColor": utils.argb_to_rgba(self.form.SpecularColor.property("color").rgba()), + "Transparency": self.form.Transparency.value(), + "Shininess": self.form.Shininess.value(), + "LineColor": utils.argb_to_rgba(self.form.LineColor.property("color").rgba()), + "LineWidth": self.form.LineWidth.value(), + "PointColor": utils.argb_to_rgba(self.form.PointColor.property("color").rgba()), + "PointSize": self.form.PointSize.value(), + "DrawStyle": self.form.DrawStyle.currentIndex(), + "DisplayMode": self.form.DisplayMode.currentIndex(), + "TextColor": utils.argb_to_rgba(self.form.TextColor.property("color").rgba()), + "TextFont": self.form.TextFont.currentFont().family(), + "TextSize": U.Quantity(self.form.TextSize.text()).Value, + "LineSpacing": self.form.LineSpacing.value(), "ScaleMultiplier": self.form.ScaleMultiplier.value(), - - "AnnoLineColor": utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba()), - "AnnoLineWidth": self.form.AnnoLineWidth.value(), + "AnnoLineColor": utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba()), + "AnnoLineWidth": self.form.AnnoLineWidth.value(), "ArrowStyleStart": self.form.ArrowStyleStart.currentIndex(), - "ArrowSizeStart": U.Quantity(self.form.ArrowSizeStart.text()).Value, - "ArrowStyleEnd": self.form.ArrowStyleEnd.currentIndex(), - "ArrowSizeEnd": U.Quantity(self.form.ArrowSizeEnd.text()).Value, - "ShowUnit": self.form.ShowUnit.isChecked(), - "UnitOverride": self.form.UnitOverride.text(), - "DimOvershoot": U.Quantity(self.form.DimOvershoot.text()).Value, - "ExtLines": U.Quantity(self.form.ExtLines.text()).Value, - "ExtOvershoot": U.Quantity(self.form.ExtOvershoot.text()).Value, - "TextSpacing": U.Quantity(self.form.TextSpacing.text()).Value + "ArrowSizeStart": U.Quantity(self.form.ArrowSizeStart.text()).Value, + "ArrowStyleEnd": self.form.ArrowStyleEnd.currentIndex(), + "ArrowSizeEnd": U.Quantity(self.form.ArrowSizeEnd.text()).Value, + "ShowUnit": self.form.ShowUnit.isChecked(), + "UnitOverride": self.form.UnitOverride.text(), + "DimOvershoot": U.Quantity(self.form.DimOvershoot.text()).Value, + "ExtLines": U.Quantity(self.form.ExtLines.text()).Value, + "ExtOvershoot": U.Quantity(self.form.ExtOvershoot.text()).Value, + "TextSpacing": U.Quantity(self.form.TextSpacing.text()).Value, } def setValues(self, preset): @@ -196,40 +228,35 @@ class Draft_SetStyle_TaskPanel: # --------------------------------------------------------------------- self.form.ShapeColor.setProperty( - "color", - self.getColor(preset.get("ShapeColor", getDefView("DefaultShapeColor"))) + "color", self.getColor(preset.get("ShapeColor", getDefView("DefaultShapeColor"))) ) self.form.AmbientColor.setProperty( - "color", - self.getColor(preset.get("AmbientColor", getDefView("DefaultAmbientColor"))) + "color", self.getColor(preset.get("AmbientColor", getDefView("DefaultAmbientColor"))) ) self.form.EmissiveColor.setProperty( - "color", - self.getColor(preset.get("EmissiveColor", getDefView("DefaultEmissiveColor"))) + "color", self.getColor(preset.get("EmissiveColor", getDefView("DefaultEmissiveColor"))) ) self.form.SpecularColor.setProperty( - "color", - self.getColor(preset.get("SpecularColor", getDefView("DefaultSpecularColor"))) + "color", self.getColor(preset.get("SpecularColor", getDefView("DefaultSpecularColor"))) ) self.form.Transparency.setValue( preset.get("Transparency", getDefView("DefaultShapeTransparency")) ) - self.form.Shininess.setValue( - preset.get("Shininess", getDefView("DefaultShapeShininess")) - ) + self.form.Shininess.setValue(preset.get("Shininess", getDefView("DefaultShapeShininess"))) # --------------------------------------------------------------------- self.form.LineColor.setProperty( - "color", - self.getColor(preset.get("LineColor", getDefView("DefaultShapeLineColor"))) - ) - self.form.LineWidth.setValue( - preset.get("LineWidth", getDefView("DefaultShapeLineWidth")) + "color", self.getColor(preset.get("LineColor", getDefView("DefaultShapeLineColor"))) ) + self.form.LineWidth.setValue(preset.get("LineWidth", getDefView("DefaultShapeLineWidth"))) self.form.PointColor.setProperty( "color", - self.getColor(preset.get("PointColor", preset.get("LineColor", getDefView("DefaultShapeVertexColor")))) + self.getColor( + preset.get( + "PointColor", preset.get("LineColor", getDefView("DefaultShapeVertexColor")) + ) + ), ) self.form.PointSize.setValue( preset.get("PointSize", preset.get("LineWidth", getDefView("DefaultShapePointSize"))) @@ -244,18 +271,15 @@ class Draft_SetStyle_TaskPanel: # --------------------------------------------------------------------- self.form.TextColor.setProperty( - "color", - self.getColor(preset.get("TextColor", getDefDraft("DefaultTextColor"))) + "color", self.getColor(preset.get("TextColor", getDefDraft("DefaultTextColor"))) ) self.form.TextFont.setCurrentFont( QtGui.QFont(preset.get("TextFont", getDefDraft("textfont"))) ) self.form.TextSize.setText( - U.Quantity(preset.get("TextSize", getDefDraft("textheight")),U.Length).UserString - ) - self.form.LineSpacing.setValue( - preset.get("LineSpacing", getDefDraft("LineSpacing")) + U.Quantity(preset.get("TextSize", getDefDraft("textheight")), U.Length).UserString ) + self.form.LineSpacing.setValue(preset.get("LineSpacing", getDefDraft("LineSpacing"))) self.form.ScaleMultiplier.setValue( preset.get("ScaleMultiplier", getDefDraft("DefaultAnnoScaleMultiplier")) ) @@ -264,16 +288,24 @@ class Draft_SetStyle_TaskPanel: self.form.AnnoLineColor.setProperty( "color", - self.getColor(preset.get("AnnoLineColor", preset.get("LineColor", getDefDraft("DefaultAnnoLineColor")))) + self.getColor( + preset.get( + "AnnoLineColor", preset.get("LineColor", getDefDraft("DefaultAnnoLineColor")) + ) + ), ) self.form.AnnoLineWidth.setValue( - preset.get("AnnoLineWidth", preset.get("LineWidth", getDefDraft("DefaultAnnoLineWidth"))) + preset.get( + "AnnoLineWidth", preset.get("LineWidth", getDefDraft("DefaultAnnoLineWidth")) + ) ) self.form.ArrowStyleStart.setCurrentIndex( preset.get("ArrowStyleStart", getDefDraft("dimsymbolstart")) ) self.form.ArrowSizeStart.setText( - U.Quantity(preset.get("ArrowSizeStart", getDefDraft("arrowsizestart")), U.Length).UserString + U.Quantity( + preset.get("ArrowSizeStart", getDefDraft("arrowsizestart")), U.Length + ).UserString ) self.form.ArrowStyleEnd.setCurrentIndex( preset.get("ArrowStyleEnd", getDefDraft("dimsymbolend")) @@ -281,12 +313,8 @@ class Draft_SetStyle_TaskPanel: self.form.ArrowSizeEnd.setText( U.Quantity(preset.get("ArrowSizeEnd", getDefDraft("arrowsizeend")), U.Length).UserString ) - self.form.ShowUnit.setChecked( - preset.get("ShowUnit", getDefDraft("showUnit")) - ) - self.form.UnitOverride.setText( - preset.get("UnitOverride", getDefDraft("overrideUnit")) - ) + self.form.ShowUnit.setChecked(preset.get("ShowUnit", getDefDraft("showUnit"))) + self.form.UnitOverride.setText(preset.get("UnitOverride", getDefDraft("overrideUnit"))) self.form.DimOvershoot.setText( U.Quantity(preset.get("DimOvershoot", getDefDraft("dimovershoot")), U.Length).UserString ) @@ -306,27 +334,49 @@ class Draft_SetStyle_TaskPanel: def accept(self): - params.set_param_view("DefaultShapeColor", utils.argb_to_rgba(self.form.ShapeColor.property("color").rgba())) - params.set_param_view("DefaultAmbientColor", utils.argb_to_rgba(self.form.AmbientColor.property("color").rgba())) - params.set_param_view("DefaultEmissiveColor", utils.argb_to_rgba(self.form.EmissiveColor.property("color").rgba())) - params.set_param_view("DefaultSpecularColor", utils.argb_to_rgba(self.form.SpecularColor.property("color").rgba())) + params.set_param_view( + "DefaultShapeColor", utils.argb_to_rgba(self.form.ShapeColor.property("color").rgba()) + ) + params.set_param_view( + "DefaultAmbientColor", + utils.argb_to_rgba(self.form.AmbientColor.property("color").rgba()), + ) + params.set_param_view( + "DefaultEmissiveColor", + utils.argb_to_rgba(self.form.EmissiveColor.property("color").rgba()), + ) + params.set_param_view( + "DefaultSpecularColor", + utils.argb_to_rgba(self.form.SpecularColor.property("color").rgba()), + ) params.set_param_view("DefaultShapeTransparency", self.form.Transparency.value()) params.set_param_view("DefaultShapeShininess", self.form.Shininess.value()) - params.set_param_view("DefaultShapeLineColor", utils.argb_to_rgba(self.form.LineColor.property("color").rgba())) + params.set_param_view( + "DefaultShapeLineColor", + utils.argb_to_rgba(self.form.LineColor.property("color").rgba()), + ) params.set_param_view("DefaultShapeLineWidth", self.form.LineWidth.value()) - params.set_param_view("DefaultShapeVertexColor", utils.argb_to_rgba(self.form.PointColor.property("color").rgba())) + params.set_param_view( + "DefaultShapeVertexColor", + utils.argb_to_rgba(self.form.PointColor.property("color").rgba()), + ) params.set_param_view("DefaultShapePointSize", self.form.PointSize.value()) params.set_param("DefaultDrawStyle", self.form.DrawStyle.currentIndex()) params.set_param("DefaultDisplayMode", self.form.DisplayMode.currentIndex()) - params.set_param("DefaultTextColor", utils.argb_to_rgba(self.form.TextColor.property("color").rgba())) + params.set_param( + "DefaultTextColor", utils.argb_to_rgba(self.form.TextColor.property("color").rgba()) + ) params.set_param("textfont", self.form.TextFont.currentFont().family()) params.set_param("textheight", U.Quantity(self.form.TextSize.text()).Value) params.set_param("LineSpacing", self.form.LineSpacing.value()) params.set_param("DefaultAnnoScaleMultiplier", self.form.ScaleMultiplier.value()) - params.set_param("DefaultAnnoLineColor", utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba())) + params.set_param( + "DefaultAnnoLineColor", + utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba()), + ) params.set_param("DefaultAnnoLineWidth", self.form.AnnoLineWidth.value()) params.set_param("dimsymbolstart", self.form.ArrowStyleStart.currentIndex()) params.set_param("arrowsizestart", U.Quantity(self.form.ArrowSizeStart.text()).Value) @@ -350,8 +400,14 @@ class Draft_SetStyle_TaskPanel: if App.ActiveDocument is not None: # Command can be called without a document. objs = App.ActiveDocument.Objects - typs = ["Dimension", "LinearDimension", "AngularDimension", - "Text", "DraftText", "Label"] + typs = [ + "Dimension", + "LinearDimension", + "AngularDimension", + "Text", + "DraftText", + "Label", + ] for obj in objs: if utils.get_type(obj) in typs: self.apply_style_to_obj(obj) @@ -366,13 +422,15 @@ class Draft_SetStyle_TaskPanel: if "FontName" not in properties: # Shapes if "ShapeAppearance" in properties: material = App.Material() - material.DiffuseColor = self.form.ShapeColor.property("color").getRgbF()[:3] # Remove Alpha (which is 1 instead of 0). + material.DiffuseColor = self.form.ShapeColor.property("color").getRgbF()[ + :3 + ] # Remove Alpha (which is 1 instead of 0). material.AmbientColor = self.form.AmbientColor.property("color").getRgbF()[:3] material.EmissiveColor = self.form.EmissiveColor.property("color").getRgbF()[:3] material.SpecularColor = self.form.SpecularColor.property("color").getRgbF()[:3] material.Transparency = self.form.Transparency.value() / 100 material.Shininess = self.form.Shininess.value() / 100 - vobj.ShapeAppearance = (material, ) + vobj.ShapeAppearance = (material,) if "LineColor" in properties: vobj.LineColor = self.form.LineColor.property("color").getRgbF()[:3] if "LineWidth" in properties: @@ -423,7 +481,7 @@ class Draft_SetStyle_TaskPanel: if "TextSpacing" in properties: vobj.TextSpacing = U.Quantity(self.form.TextSpacing.text()).Value - def onLoadStyle(self,index): + def onLoadStyle(self, index): if index > 0: pdict = self.load() @@ -433,19 +491,21 @@ class Draft_SetStyle_TaskPanel: def onSaveStyle(self): - reply = QtWidgets.QInputDialog.getText(None, - translate("Draft", "Save style"), - translate("Draft", "Name of this new style")) + reply = QtWidgets.QInputDialog.getText( + None, translate("Draft", "Save style"), translate("Draft", "Name of this new style") + ) if reply[1]: name = reply[0] pdict = self.load() if pdict: if name in pdict: - reply = QtWidgets.QMessageBox.question(None, - translate("Draft", "Warning"), - translate("Draft", "Name exists. Overwrite?"), - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No) + reply = QtWidgets.QMessageBox.question( + None, + translate("Draft", "Warning"), + translate("Draft", "Name exists. Overwrite?"), + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, + QtWidgets.QMessageBox.No, + ) if reply == QtWidgets.QMessageBox.No: return preset = self.getValues() @@ -454,7 +514,6 @@ class Draft_SetStyle_TaskPanel: self.loadDefaults() def load(self): - """loads the presets json file, returns a dict""" pdict = {} @@ -474,8 +533,7 @@ class Draft_SetStyle_TaskPanel: return {} return pdict - def save(self,d): - + def save(self, d): """saves the given dict to the presets json file""" try: diff --git a/src/Mod/Draft/draftguitools/gui_shape2dview.py b/src/Mod/Draft/draftguitools/gui_shape2dview.py index d9269cb9a4..898a9f2bc3 100644 --- a/src/Mod/Draft/draftguitools/gui_shape2dview.py +++ b/src/Mod/Draft/draftguitools/gui_shape2dview.py @@ -55,9 +55,14 @@ class Shape2DView(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_2DShapeView', - 'MenuText': QT_TRANSLATE_NOOP("Draft_Shape2DView", "Shape 2D View"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Shape2DView", "Creates a 2D projection of the selected objects on the XY-plane.\nThe initial projection direction is the opposite of the current active view direction.")} + return { + "Pixmap": "Draft_2DShapeView", + "MenuText": QT_TRANSLATE_NOOP("Draft_Shape2DView", "Shape 2D View"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Shape2DView", + "Creates a 2D projection of the selected objects on the XY-plane.\nThe initial projection direction is the opposite of the current active view direction.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -112,11 +117,10 @@ class Shape2DView(gui_base_original.Modifier): n += 1 if commitlist: commitlist.append("FreeCAD.ActiveDocument.recompute()") - self.commit(translate("draft", "Create 2D View"), - commitlist) + self.commit(translate("draft", "Create 2D View"), commitlist) self.finish() -Gui.addCommand('Draft_Shape2DView', Shape2DView()) +Gui.addCommand("Draft_Shape2DView", Shape2DView()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_shapestrings.py b/src/Mod/Draft/draftguitools/gui_shapestrings.py index 2ea8b19c5b..7acd4df13d 100644 --- a/src/Mod/Draft/draftguitools/gui_shapestrings.py +++ b/src/Mod/Draft/draftguitools/gui_shapestrings.py @@ -56,9 +56,13 @@ class ShapeString(gui_base.GuiCommandBase): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_ShapeString", - "MenuText": QT_TRANSLATE_NOOP("Draft_ShapeString", "Shape From Text"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ShapeString", "Creates a shape from a text string and a specified font")} + return { + "Pixmap": "Draft_ShapeString", + "MenuText": QT_TRANSLATE_NOOP("Draft_ShapeString", "Shape From Text"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ShapeString", "Creates a shape from a text string and a specified font" + ), + } def Activated(self): """Execute when the command is called.""" @@ -84,6 +88,6 @@ class ShapeString(gui_base.GuiCommandBase): super().finish() -Gui.addCommand('Draft_ShapeString', ShapeString()) +Gui.addCommand("Draft_ShapeString", ShapeString()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py index 061db54d2c..c1ffd4d8ee 100644 --- a/src/Mod/Draft/draftguitools/gui_snapper.py +++ b/src/Mod/Draft/draftguitools/gui_snapper.py @@ -61,7 +61,8 @@ __title__ = "FreeCAD Draft Snap tools" __author__ = "Yorik van Havre" __url__ = "https://www.freecad.org" -UNSNAPPABLES = ('Image::ImagePlane',) +UNSNAPPABLES = ("Image::ImagePlane",) + class Snapper: """Classes to manage snapping in Draft and Arch. @@ -148,20 +149,22 @@ class Snapper: self.init_active_snaps() self.set_snap_style() - self.cursors = \ - coll.OrderedDict([('passive', ':/icons/Draft_Snap_Near.svg'), - ('extension', ':/icons/Draft_Snap_Extension.svg'), - ('parallel', ':/icons/Draft_Snap_Parallel.svg'), - ('grid', ':/icons/Draft_Snap_Grid.svg'), - ('endpoint', ':/icons/Draft_Snap_Endpoint.svg'), - ('midpoint', ':/icons/Draft_Snap_Midpoint.svg'), - ('perpendicular', ':/icons/Draft_Snap_Perpendicular.svg'), - ('angle', ':/icons/Draft_Snap_Angle.svg'), - ('center', ':/icons/Draft_Snap_Center.svg'), - ('ortho', ':/icons/Draft_Snap_Ortho.svg'), - ('intersection', ':/icons/Draft_Snap_Intersection.svg'), - ('special', ':/icons/Draft_Snap_Special.svg')]) - + self.cursors = coll.OrderedDict( + [ + ("passive", ":/icons/Draft_Snap_Near.svg"), + ("extension", ":/icons/Draft_Snap_Extension.svg"), + ("parallel", ":/icons/Draft_Snap_Parallel.svg"), + ("grid", ":/icons/Draft_Snap_Grid.svg"), + ("endpoint", ":/icons/Draft_Snap_Endpoint.svg"), + ("midpoint", ":/icons/Draft_Snap_Midpoint.svg"), + ("perpendicular", ":/icons/Draft_Snap_Perpendicular.svg"), + ("angle", ":/icons/Draft_Snap_Angle.svg"), + ("center", ":/icons/Draft_Snap_Center.svg"), + ("ortho", ":/icons/Draft_Snap_Ortho.svg"), + ("intersection", ":/icons/Draft_Snap_Intersection.svg"), + ("special", ":/icons/Draft_Snap_Special.svg"), + ] + ) def _get_wp(self): # update=False is required, without it WorkingPlane.get_working_plane() @@ -170,7 +173,6 @@ class Snapper: # See: https://github.com/FreeCAD/FreeCAD/issues/24013 return WorkingPlane.get_working_plane(update=False) - def init_active_snaps(self): """ set self.active_snaps according to user prefs @@ -183,36 +185,42 @@ class Snapper: self.active_snaps.append(self.snaps[i]) i += 1 - def set_snap_style(self): self.snapStyle = params.get_param("snapStyle") if self.snapStyle: - self.mk = coll.OrderedDict([("passive", "SQUARE_LINE"), - ("extension", "SQUARE_LINE"), - ("parallel", "SQUARE_LINE"), - ("grid", "SQUARE_FILLED"), - ("endpoint", "SQUARE_FILLED"), - ("midpoint", "SQUARE_FILLED"), - ("perpendicular", "SQUARE_FILLED"), - ("angle", "SQUARE_FILLED"), - ("center", "SQUARE_FILLED"), - ("ortho", "SQUARE_FILLED"), - ("intersection", "SQUARE_FILLED"), - ("special", "SQUARE_FILLED")]) + self.mk = coll.OrderedDict( + [ + ("passive", "SQUARE_LINE"), + ("extension", "SQUARE_LINE"), + ("parallel", "SQUARE_LINE"), + ("grid", "SQUARE_FILLED"), + ("endpoint", "SQUARE_FILLED"), + ("midpoint", "SQUARE_FILLED"), + ("perpendicular", "SQUARE_FILLED"), + ("angle", "SQUARE_FILLED"), + ("center", "SQUARE_FILLED"), + ("ortho", "SQUARE_FILLED"), + ("intersection", "SQUARE_FILLED"), + ("special", "SQUARE_FILLED"), + ] + ) else: - self.mk = coll.OrderedDict([("passive", "CIRCLE_LINE"), - ("extension", "CIRCLE_LINE"), - ("parallel", "CIRCLE_LINE"), - ("grid", "CIRCLE_LINE"), - ("endpoint", "CIRCLE_FILLED"), - ("midpoint", "DIAMOND_FILLED"), - ("perpendicular", "CIRCLE_FILLED"), - ("angle", "DIAMOND_FILLED"), - ("center", "CIRCLE_FILLED"), - ("ortho", "CIRCLE_FILLED"), - ("intersection", "CIRCLE_FILLED"), - ("special", "CIRCLE_FILLED")]) - + self.mk = coll.OrderedDict( + [ + ("passive", "CIRCLE_LINE"), + ("extension", "CIRCLE_LINE"), + ("parallel", "CIRCLE_LINE"), + ("grid", "CIRCLE_LINE"), + ("endpoint", "CIRCLE_FILLED"), + ("midpoint", "DIAMOND_FILLED"), + ("perpendicular", "CIRCLE_FILLED"), + ("angle", "DIAMOND_FILLED"), + ("center", "CIRCLE_FILLED"), + ("ortho", "CIRCLE_FILLED"), + ("intersection", "CIRCLE_FILLED"), + ("special", "CIRCLE_FILLED"), + ] + ) def cstr(self, lastpoint, constrain, point): """Return constraints if needed.""" @@ -225,10 +233,7 @@ class Snapper: self.radiusTracker.update(fpt) return fpt - - def snap(self, screenpos, - lastpoint=None, active=True, - constrain=False, noTracker=False): + def snap(self, screenpos, lastpoint=None, active=True, constrain=False, noTracker=False): """Return a snapped point from the given (x, y) screen position. snap(screenpos,lastpoint=None,active=True,constrain=False, @@ -270,8 +275,7 @@ class Snapper: self.setTrackers() # Get current snap radius - self.radius = self.getScreenDist(params.get_param("snapRange"), - screenpos) + self.radius = self.getScreenDist(params.get_param("snapRange"), screenpos) if self.radiusTracker: self.radiusTracker.update(self.radius) self.radiusTracker.off() @@ -280,7 +284,7 @@ class Snapper: if params.get_param("alwaysSnap"): active = True - self.setCursor('passive') + self.setCursor("passive") if self.tracker: self.tracker.off() if self.extLine2: @@ -305,8 +309,7 @@ class Snapper: eline = None if active: point, eline = self.snapToPolar(point, lastpoint) - point, eline = self.snapToExtensions(point, lastpoint, - constrain, eline) + point, eline = self.snapToExtensions(point, lastpoint, constrain, eline) # Check if we have an object under the cursor and try to # snap to it @@ -344,12 +347,10 @@ class Snapper: self.running = False return fp - def cycleSnapObject(self): """Increase the index of the snap object by one.""" self.snapObjectIndex = self.snapObjectIndex + 1 - def snapToObject(self, lastpoint, active, constrain, eline, point): """Snap to an object.""" @@ -365,9 +366,11 @@ class Snapper: parent = obj subname = self.snapInfo["Component"] - if not obj \ - or Draft.getType(obj) in UNSNAPPABLES \ - or not getattr(obj.ViewObject, "Selectable", True): + if ( + not obj + or Draft.getType(obj) in UNSNAPPABLES + or not getattr(obj.ViewObject, "Selectable", True) + ): return None snaps = [] @@ -382,11 +385,9 @@ class Snapper: # Special snapping for polygons: add the center snaps.extend(self.snapToPolygon(obj)) - elif (Draft.getType(obj) == "BuildingPart" - and self.isEnabled("Center")): + elif Draft.getType(obj) == "BuildingPart" and self.isEnabled("Center"): # snap to the base placement of empty BuildingParts - snaps.append([obj.Placement.Base, 'center', - self.toWP(obj.Placement.Base)]) + snaps.append([obj.Placement.Base, "center", self.toWP(obj.Placement.Base)]) if (not self.maxEdges) or (len(shape.Edges) <= self.maxEdges): if "Edge" in comp: @@ -442,12 +443,12 @@ class Snapper: elif Draft.getType(obj).startswith("Points::"): snaps.extend(self.snapToEndpoints(obj.Points, point)) - elif (Draft.getType(obj) in ("WorkingPlaneProxy", "BuildingPart") - and self.isEnabled("Center")): + elif Draft.getType(obj) in ("WorkingPlaneProxy", "BuildingPart") and self.isEnabled( + "Center" + ): # snap to the center of WPProxies or to the base # placement of no empty BuildingParts - snaps.append([obj.Placement.Base, 'center', - self.toWP(obj.Placement.Base)]) + snaps.append([obj.Placement.Base, "center", self.toWP(obj.Placement.Base)]) elif Draft.getType(obj) == "SectionPlane": # snap to corners of section planes @@ -521,14 +522,12 @@ class Snapper: self.spoint = fp return self.spoint - def toWP(self, point): """Project the given point on the working plane, if needed.""" if self.isEnabled("WorkingPlane"): return self._get_wp().project_point(point) return point - def getApparentPoint(self, x, y): """Return a 3D point, projected on the current working plane.""" view = Draft.get3DView() @@ -543,18 +542,18 @@ class Snapper: return self._get_wp().project_point(pt, dv) return pt - def snapToDim(self, obj): snaps = [] - if self.isEnabled("Endpoint") \ - and obj.ViewObject \ - and hasattr(obj.ViewObject.Proxy, "p2") \ - and hasattr(obj.ViewObject.Proxy, "p3"): - snaps.append([obj.ViewObject.Proxy.p2, 'endpoint', self.toWP(obj.ViewObject.Proxy.p2)]) - snaps.append([obj.ViewObject.Proxy.p3, 'endpoint', self.toWP(obj.ViewObject.Proxy.p3)]) + if ( + self.isEnabled("Endpoint") + and obj.ViewObject + and hasattr(obj.ViewObject.Proxy, "p2") + and hasattr(obj.ViewObject.Proxy, "p3") + ): + snaps.append([obj.ViewObject.Proxy.p2, "endpoint", self.toWP(obj.ViewObject.Proxy.p2)]) + snaps.append([obj.ViewObject.Proxy.p3, "endpoint", self.toWP(obj.ViewObject.Proxy.p3)]) return snaps - def snapToExtensions(self, point, last, constrain, eline): """Return a point snapped to extension or parallel line. @@ -603,8 +602,7 @@ class Snapper: return tsnap[2], eline for o in self.lastObj: - if (self.isEnabled('Extension') - or self.isEnabled('Parallel')): + if self.isEnabled("Extension") or self.isEnabled("Parallel"): ob = App.ActiveDocument.getObject(o) if not ob: continue @@ -612,7 +610,7 @@ class Snapper: continue edges = ob.Shape.Edges if Draft.getType(ob) == "Wall": - for so in [ob]+ob.Additions: + for so in [ob] + ob.Additions: if Draft.getType(so) == "Wall": if so.Base: edges.extend(so.Base.Shape.Edges) @@ -621,69 +619,81 @@ class Snapper: for e in edges: if DraftGeomUtils.geomType(e) != "Line": continue - np = self.getPerpendicular(e,point) + np = self.getPerpendicular(e, point) if (np.sub(point)).Length < self.radius: - if self.isEnabled('Extension'): - if DraftGeomUtils.isPtOnEdge(np,e): + if self.isEnabled("Extension"): + if DraftGeomUtils.isPtOnEdge(np, e): continue if np != e.Vertexes[0].Point: p0 = e.Vertexes[0].Point if self.tracker and not self.selectMode: self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['extension']) + self.tracker.setMarker(self.mk["extension"]) self.tracker.on() if self.extLine: self.extLine.p1(p0) self.extLine.p2(np) self.extLine.setColor() self.extLine.on() - self.setCursor('extension') - ne = Part.LineSegment(p0,np).toShape() + self.setCursor("extension") + ne = Part.LineSegment(p0, np).toShape() # storing extension line for intersection calculations later if len(self.lastExtensions) == 0: self.lastExtensions.append(ne) elif len(self.lastExtensions) == 1: - if not DraftGeomUtils.areColinear(ne,self.lastExtensions[0]): + if not DraftGeomUtils.areColinear( + ne, self.lastExtensions[0] + ): self.lastExtensions.append(self.lastExtensions[0]) self.lastExtensions[0] = ne else: - if (not DraftGeomUtils.areColinear(ne,self.lastExtensions[0])) and \ - (not DraftGeomUtils.areColinear(ne,self.lastExtensions[1])): + if ( + not DraftGeomUtils.areColinear( + ne, self.lastExtensions[0] + ) + ) and ( + not DraftGeomUtils.areColinear( + ne, self.lastExtensions[1] + ) + ): self.lastExtensions[1] = self.lastExtensions[0] self.lastExtensions[0] = ne - return np,ne - elif self.isEnabled('Parallel'): + return np, ne + elif self.isEnabled("Parallel"): if last: ve = DraftGeomUtils.vec(e) if not DraftVecUtils.isNull(ve): - de = Part.LineSegment(last,last.add(ve)).toShape() - np = self.getPerpendicular(de,point) + de = Part.LineSegment(last, last.add(ve)).toShape() + np = self.getPerpendicular(de, point) if (np.sub(point)).Length < self.radius: if self.tracker and not self.selectMode: self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) + self.tracker.setMarker(self.mk["parallel"]) self.tracker.on() - self.setCursor('parallel') - return np,de - return point,eline - + self.setCursor("parallel") + return np, de + return point, eline def snapToCrossExtensions(self, point): """Snap to the intersection of the last 2 extension lines.""" - if self.isEnabled('Extension'): + if self.isEnabled("Extension"): if len(self.lastExtensions) == 2: - np = DraftGeomUtils.findIntersection(self.lastExtensions[0], self.lastExtensions[1], True, True) + np = DraftGeomUtils.findIntersection( + self.lastExtensions[0], self.lastExtensions[1], True, True + ) if np: for p in np: dv = point.sub(p) if (self.radius == 0) or (dv.Length <= self.radius): if self.tracker and not self.selectMode: self.tracker.setCoords(p) - self.tracker.setMarker(self.mk['intersection']) + self.tracker.setMarker(self.mk["intersection"]) self.tracker.on() - self.setCursor('intersection') + self.setCursor("intersection") if self.extLine and self.extLine2: - if DraftVecUtils.equals(self.extLine.p1(), self.lastExtensions[0].Vertexes[0].Point): + if DraftVecUtils.equals( + self.extLine.p1(), self.lastExtensions[0].Vertexes[0].Point + ): p0 = self.lastExtensions[1].Vertexes[0].Point else: p0 = self.lastExtensions[0].Vertexes[0].Point @@ -695,10 +705,9 @@ class Snapper: return p return None - - def snapToPolar(self,point,last): + def snapToPolar(self, point, last): """Snap to polar lines from the given point.""" - if self.isEnabled('Ortho') and (not self.mask): + if self.isEnabled("Ortho") and (not self.mask): if last: vecs = [] wp = self._get_wp() @@ -719,17 +728,17 @@ class Snapper: except Part.OCCError: return point, None np = self.getPerpendicular(de, point) - if ((self.radius == 0) and (point.sub(last).getAngle(v) < 0.087)) \ - or ((np.sub(point)).Length < self.radius): + if ((self.radius == 0) and (point.sub(last).getAngle(v) < 0.087)) or ( + (np.sub(point)).Length < self.radius + ): if self.tracker and not self.selectMode: self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) + self.tracker.setMarker(self.mk["parallel"]) self.tracker.on() - self.setCursor('ortho') - return np,de + self.setCursor("ortho") + return np, de return point, None - def snapToGrid(self, point): """Return a grid snap point if available.""" if self.grid: @@ -741,13 +750,12 @@ class Snapper: if (self.radius == 0) or (dv.Length <= self.radius): if self.tracker and not self.selectMode: self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['grid']) + self.tracker.setMarker(self.mk["grid"]) self.tracker.on() - self.setCursor('grid') + self.setCursor("grid") return np return point - def snapToEndpoints(self, shape, point=None): """Return a list of endpoints snap locations.""" if self.isEnabled("Endpoint"): @@ -775,7 +783,6 @@ class Snapper: return snaps return [] - def snapToMidpoint(self, shape): """Return a list of midpoints snap locations.""" snaps = [] @@ -783,10 +790,9 @@ class Snapper: if isinstance(shape, Part.Edge): mp = DraftGeomUtils.findMidpoint(shape) if mp: - snaps.append([mp, 'midpoint', self.toWP(mp)]) + snaps.append([mp, "midpoint", self.toWP(mp)]) return snaps - def snapToNear(self, shape, point): """Return a list with a near snap location for an edge.""" if self.isEnabled("Near") and point: @@ -798,7 +804,6 @@ class Snapper: else: return [] - def snapToNearFace(self, shape, point): """Return a list with a near snap location for a face.""" if self.isEnabled("Near") and point: @@ -810,7 +815,6 @@ class Snapper: else: return [] - def snapToNearUnprojected(self, point): """Return a list with a near snap location that is not projected on the object.""" if self.isEnabled("Near") and point: @@ -818,7 +822,6 @@ class Snapper: else: return [] - def snapToPerpendicular(self, shape, last): """Return a list of perpendicular snap locations for an edge.""" if self.isEnabled("Perpendicular") and last: @@ -835,7 +838,6 @@ class Snapper: else: return [] - def snapToPerpendicularFace(self, shape, last): """Return a list of perpendicular snap locations for a face.""" if self.isEnabled("Perpendicular") and last: @@ -852,7 +854,6 @@ class Snapper: else: return [] - def snapToOrtho(self, shape, last, constrain): """Return a list of ortho snap locations.""" snaps = [] @@ -862,15 +863,16 @@ class Snapper: if last: if DraftGeomUtils.geomType(shape) == "Line": if self.constraintAxis: - tmpEdge = Part.LineSegment(last, last.add(self.constraintAxis)).toShape() + tmpEdge = Part.LineSegment( + last, last.add(self.constraintAxis) + ).toShape() # get the intersection points pt = DraftGeomUtils.findIntersection(tmpEdge, shape, True, True) if pt: for p in pt: - snaps.append([p, 'ortho', self.toWP(p)]) + snaps.append([p, "ortho", self.toWP(p)]) return snaps - def snapToExtOrtho(self, last, constrain, eline): """Return an ortho X extension snap location.""" if self.isEnabled("Extension") and self.isEnabled("Ortho"): @@ -880,19 +882,18 @@ class Snapper: # get the intersection points pt = DraftGeomUtils.findIntersection(tmpEdge1, tmpEdge2, True, True) if pt: - return [pt[0], 'ortho', pt[0]] + return [pt[0], "ortho", pt[0]] if eline: try: tmpEdge2 = Part.LineSegment(self.extLine.p1(), self.extLine.p2()).toShape() # get the intersection points pt = DraftGeomUtils.findIntersection(eline, tmpEdge2, True, True) if pt: - return [pt[0], 'ortho', pt[0]] + return [pt[0], "ortho", pt[0]] except Exception: return None return None - def snapToHold(self, point): """Return a snap location that is orthogonal to hold points. @@ -910,7 +911,7 @@ class Snapper: for p1, p2 in itertools.combinations(l, 2): p3 = p1.add((p2.sub(p1)).multiply(0.5)) if (p3.sub(point)).Length < self.radius: - return [p1, 'midpoint', p3] + return [p1, "midpoint", p3] # then try int points ipoints = [] l = list(self.holdPoints) @@ -925,22 +926,21 @@ class Snapper: ipoints.append([p1, i2[0]]) for p in ipoints: if (p[1].sub(point)).Length < self.radius: - return [p[0], 'ortho', p[1]] + return [p[0], "ortho", p[1]] # then try to stick to a line for p in self.holdPoints: d = DraftGeomUtils.findDistance(point, [p, p.add(u)]) if d: if d.Length < self.radius: fp = point.add(d) - return [p, 'extension', fp] + return [p, "extension", fp] d = DraftGeomUtils.findDistance(point, [p, p.add(v)]) if d: if d.Length < self.radius: fp = point.add(d) - return [p, 'extension', fp] + return [p, "extension", fp] return None - def snapToExtPerpendicular(self, last): """Return a perpendicular X extension snap location.""" if self.isEnabled("Extension") and self.isEnabled("Perpendicular"): @@ -948,10 +948,9 @@ class Snapper: if self.extLine.p1() != self.extLine.p2(): tmpEdge = Part.LineSegment(self.extLine.p1(), self.extLine.p2()).toShape() np = self.getPerpendicular(tmpEdge, last) - return [np, 'perpendicular', np] + return [np, "perpendicular", np] return None - def snapToElines(self, e1, e2): """Return a snap at the infinite intersection of the given edges.""" snaps = [] @@ -961,32 +960,26 @@ class Snapper: pts = DraftGeomUtils.findIntersection(e1, e2, True, True) if pts: for p in pts: - snaps.append([p, 'intersection', self.toWP(p)]) + snaps.append([p, "intersection", self.toWP(p)]) return snaps - def snapToAngles(self, shape): """Return a list of angle snap locations.""" snaps = [] if self.isEnabled("Angle"): place = App.Placement() place.Base = shape.Curve.Center - place.Rotation = App.Rotation(App.Vector(1, 0, 0), - App.Vector(0, 1, 0), - shape.Curve.Axis, - 'ZXY') + place.Rotation = App.Rotation( + App.Vector(1, 0, 0), App.Vector(0, 1, 0), shape.Curve.Axis, "ZXY" + ) rad = shape.Curve.Radius - for deg in (0, 30, 45, 60, - 90, 120, 135, 150, - 180, 210, 225, 240, - 270, 300, 315, 330): + for deg in (0, 30, 45, 60, 90, 120, 135, 150, 180, 210, 225, 240, 270, 300, 315, 330): ang = math.radians(deg) cur = App.Vector(math.sin(ang) * rad, math.cos(ang) * rad, 0) cur = place.multVec(cur) - snaps.append([cur, 'angle', self.toWP(cur)]) + snaps.append([cur, "angle", self.toWP(cur)]) return snaps - def snapToCenter(self, shape): """Return a list of center snap locations.""" snaps = [] @@ -996,34 +989,45 @@ class Snapper: if hasattr(shape.Curve, "Radius"): place = App.Placement() place.Base = cen - place.Rotation = App.Rotation(App.Vector(1, 0, 0), - App.Vector(0, 1, 0), - shape.Curve.Axis, - 'ZXY') + place.Rotation = App.Rotation( + App.Vector(1, 0, 0), App.Vector(0, 1, 0), shape.Curve.Axis, "ZXY" + ) rad = shape.Curve.Radius - for deg in (15, 37.5, 52.5, 75, - 105, 127.5, 142.5, 165, - 195, 217.5, 232.5, 255, - 285, 307.5, 322.5, 345): + for deg in ( + 15, + 37.5, + 52.5, + 75, + 105, + 127.5, + 142.5, + 165, + 195, + 217.5, + 232.5, + 255, + 285, + 307.5, + 322.5, + 345, + ): ang = math.radians(deg) cur = App.Vector(math.sin(ang) * rad, math.cos(ang) * rad, 0) cur = place.multVec(cur) - snaps.append([cur, 'center', cen_wp]) + snaps.append([cur, "center", cen_wp]) else: - snaps.append([cen, 'center', cen_wp]) + snaps.append([cen, "center", cen_wp]) return snaps - def snapToCenterFace(self, shape): """Return a face center snap location.""" snaps = [] if self.isEnabled("Center"): pos = shape.CenterOfMass c = self.toWP(pos) - snaps.append([pos, 'center', c]) + snaps.append([pos, "center", c]) return snaps - def snapToIntersection(self, shape): """Return a list of intersection snap locations.""" snaps = [] @@ -1043,17 +1047,21 @@ class Snapper: if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges): for edge in obj.Shape.Edges: try: - if self.isEnabled("WorkingPlane") \ - and hasattr(edge, "Curve") \ - and isinstance(edge.Curve,(Part.Line,Part.LineSegment)) \ - and hasattr(shape, "Curve") \ - and isinstance(shape.Curve,(Part.Line,Part.LineSegment)): + if ( + self.isEnabled("WorkingPlane") + and hasattr(edge, "Curve") + and isinstance(edge.Curve, (Part.Line, Part.LineSegment)) + and hasattr(shape, "Curve") + and isinstance(shape.Curve, (Part.Line, Part.LineSegment)) + ): # get apparent intersection (lines projected on WP) p1 = self.toWP(edge.Vertexes[0].Point) p2 = self.toWP(edge.Vertexes[-1].Point) p3 = self.toWP(shape.Vertexes[0].Point) p4 = self.toWP(shape.Vertexes[-1].Point) - pts = DraftGeomUtils.findIntersection(p1, p2, p3, p4, True, True) + pts = DraftGeomUtils.findIntersection( + p1, p2, p3, p4, True, True + ) else: pts = DraftGeomUtils.findIntersection(edge, shape) for pt in pts: @@ -1064,7 +1072,6 @@ class Snapper: # when trying to read their types return snaps - def snapToPolygon(self, obj): """Return a list of polygon center snap locations.""" snaps = [] @@ -1075,32 +1082,31 @@ class Snapper: p2 = edge.Vertexes[-1].Point v1 = p1.add((p2 - p1).scale(0.25, 0.25, 0.25)) v2 = p1.add((p2 - p1).scale(0.75, 0.75, 0.75)) - snaps.append([v1, 'center', self.toWP(c)]) - snaps.append([v2, 'center', self.toWP(c)]) + snaps.append([v1, "center", self.toWP(c)]) + snaps.append([v2, "center", self.toWP(c)]) return snaps - def snapToSpecials(self, obj, lastpoint=None, eline=None): """Return special snap locations, if any.""" snaps = [] if self.isEnabled("Special"): - if (Draft.getType(obj) == "Wall"): + if Draft.getType(obj) == "Wall": # special snapping for wall: snap to its base shape if it is linear if obj.Base: if not obj.Base.Shape.Solids: for v in obj.Base.Shape.Vertexes: - snaps.append([v.Point, 'special', self.toWP(v.Point)]) + snaps.append([v.Point, "special", self.toWP(v.Point)]) - elif (Draft.getType(obj) == "Structure"): + elif Draft.getType(obj) == "Structure": # special snapping for struct: only to its base point if obj.Base: if not obj.Base.Shape.Solids: for v in obj.Base.Shape.Vertexes: - snaps.append([v.Point, 'special', self.toWP(v.Point)]) + snaps.append([v.Point, "special", self.toWP(v.Point)]) else: b = obj.Placement.Base - snaps.append([b, 'special', self.toWP(b)]) + snaps.append([b, "special", self.toWP(b)]) if obj.ViewObject.ShowNodes: for edge in obj.Proxy.getNodeEdges(obj): snaps.extend(self.snapToEndpoints(edge)) @@ -1112,11 +1118,10 @@ class Snapper: elif hasattr(obj, "SnapPoints"): for p in obj.SnapPoints: p2 = obj.Placement.multVec(p) - snaps.append([p2, 'special', p2]) + snaps.append([p2, "special", p2]) return snaps - def getScreenDist(self, dist, cursor): """Return a distance in 3D space from a screen pixels distance.""" view = Draft.get3DView() @@ -1124,7 +1129,6 @@ class Snapper: p2 = view.getPoint((cursor[0] + dist, cursor[1])) return (p2.sub(p1)).Length - def getPerpendicular(self, edge, pt): """Return a point on an edge, perpendicular to the given point.""" dv = pt.sub(edge.Vertexes[0].Point) @@ -1132,7 +1136,6 @@ class Snapper: np = (edge.Vertexes[0].Point).add(nv) return np - def setArchDims(self, p1, p2): """Show arc dimensions between 2 points.""" if self.isEnabled("Dimensions"): @@ -1205,8 +1208,7 @@ class Snapper: else: self.cursorMode = mode self.cursorQt = self.get_cursor_with_tail( - ":/icons/Draft_Cursor.svg", - None if mode == "passive" else self.cursors[mode] + ":/icons/Draft_Cursor.svg", None if mode == "passive" else self.cursors[mode] ) for view in views: view.setCursor(self.cursorQt) @@ -1216,7 +1218,6 @@ class Snapper: if self.grid: self.grid.lowerTracker() - def off(self): """Finish snapping.""" if self.tracker: @@ -1255,7 +1256,6 @@ class Snapper: if toolbar: toolbar.hide() - def setSelectMode(self, mode): """Set the snapper into select mode (hides snapping temporarily).""" self.selectMode = mode @@ -1265,7 +1265,6 @@ class Snapper: if self.trackLine: self.trackLine.off() - def setAngle(self, delta=None): """Keep the current angle.""" if delta: @@ -1276,7 +1275,6 @@ class Snapper: if self.trackLine.Visible: self.mask = self.trackLine.p2().sub(self.trackLine.p1()) - def constrain(self, point, basepoint=None, axis=None): """Return a constrained point. @@ -1303,6 +1301,7 @@ class Snapper: if Gui.draftToolBar.globalMode: import WorkingPlane + wp = WorkingPlane.PlaneBase() # matches the global coordinate system else: wp = self._get_wp() @@ -1350,7 +1349,6 @@ class Snapper: return npoint - def unconstrain(self): """Unset the basepoint and the constrain line.""" self.basepoint = None @@ -1358,9 +1356,9 @@ class Snapper: if self.constrainLine: self.constrainLine.off() - - def getPoint(self, last=None, callback=None, movecallback=None, - extradlg=None, title=None, mode="point"): + def getPoint( + self, last=None, callback=None, movecallback=None, extradlg=None, title=None, mode="point" + ): """Get a 3D point from the screen. getPoint([last],[callback],[movecallback],[extradlg],[title]): @@ -1399,9 +1397,13 @@ class Snapper: # remove any previous leftover callbacks try: if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + self.view.removeEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick + ) if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + self.view.removeEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), self.callbackMove + ) if self.callbackClick or self.callbackMove: # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: gui_utils.end_all_events() @@ -1418,11 +1420,8 @@ class Snapper: mousepos = event.getPosition() ctrl = event.wasCtrlDown() shift = event.wasShiftDown() - self.pt = Gui.Snapper.snap(mousepos, lastpoint=last, - active=ctrl, constrain=shift) - self.ui.displayPoint(self.pt, last, - plane=self._get_wp(), - mask=Gui.Snapper.affinity) + self.pt = Gui.Snapper.snap(mousepos, lastpoint=last, active=ctrl, constrain=shift) + self.ui.displayPoint(self.pt, last, plane=self._get_wp(), mask=Gui.Snapper.affinity) if movecallback: movecallback(self.pt, self.snapInfo) @@ -1450,9 +1449,13 @@ class Snapper: def accept(): try: if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + self.view.removeEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick + ) if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + self.view.removeEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), self.callbackMove + ) if self.callbackClick or self.callbackMove: # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: gui_utils.end_all_events() @@ -1476,9 +1479,13 @@ class Snapper: def cancel(): try: if self.callbackClick: - self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick) + self.view.removeEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), self.callbackClick + ) if self.callbackMove: - self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.callbackMove) + self.view.removeEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), self.callbackMove + ) if self.callbackClick or self.callbackMove: # Next line fixes https://github.com/FreeCAD/FreeCAD/issues/10469: gui_utils.end_all_events() @@ -1504,13 +1511,17 @@ class Snapper: interface = self.ui.pointUi if callback: if title: - interface(title=title, cancel=cancel, getcoords=getcoords, - extra=extradlg, rel=bool(last)) + interface( + title=title, cancel=cancel, getcoords=getcoords, extra=extradlg, rel=bool(last) + ) else: - interface(cancel=cancel,getcoords=getcoords,extra=extradlg,rel=bool(last)) - self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click) - self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move) - + interface(cancel=cancel, getcoords=getcoords, extra=extradlg, rel=bool(last)) + self.callbackClick = self.view.addEventCallbackPivy( + coin.SoMouseButtonEvent.getClassTypeId(), click + ) + self.callbackMove = self.view.addEventCallbackPivy( + coin.SoLocation2Event.getClassTypeId(), move + ) def get_snap_toolbar(self): """Get the snap toolbar.""" @@ -1520,21 +1531,17 @@ class Snapper: if self.toolbar: return self.toolbar - def toggleGrid(self): """Toggle FreeCAD Draft Grid.""" Gui.runCommand("Draft_ToggleGrid") - def showradius(self): """Show the snap radius indicator.""" - self.radius = self.getScreenDist(params.get_param("snapRange"), - (400, 300)) + self.radius = self.getScreenDist(params.get_param("snapRange"), (400, 300)) if self.radiusTracker: self.radiusTracker.update(self.radius) self.radiusTracker.on() - def isEnabled(self, snap): """Returns true if the given snap is on""" if "Lock" in self.active_snaps and snap in self.active_snaps: @@ -1542,10 +1549,9 @@ class Snapper: else: return False - - def toggle_snap(self, snap, set_to = None): + def toggle_snap(self, snap, set_to=None): """Sets the given snap on/off according to the given parameter""" - if set_to: # set mode + if set_to: # set mode if set_to is True: if not snap in self.active_snaps: self.active_snaps.append(snap) @@ -1554,7 +1560,7 @@ class Snapper: if snap in self.active_snaps: self.active_snaps.remove(snap) status = False - else: # toggle mode, default + else: # toggle mode, default if not snap in self.active_snaps: self.active_snaps.append(snap) status = True @@ -1564,7 +1570,6 @@ class Snapper: self.save_snap_state() return status - def save_snap_state(self): """ Save snap state to user preferences to be restored in next session. @@ -1577,7 +1582,6 @@ class Snapper: snap_modes += "0" params.set_param("snapModes", snap_modes) - def show_hide_grids(self, show=True): """Show the grid in all 3D views where it was previously visible, or hide the grid in all 3D view. Used when switching to different workbenches. @@ -1588,7 +1592,9 @@ class Snapper: if (not show) and (not params.get_param("GridHideInOtherWorkbenches")): return mw = Gui.getMainWindow() - views = mw.getWindowsOfType(App.Base.TypeId.fromName("Gui::View3DInventor")) # All 3D views. + views = mw.getWindowsOfType( + App.Base.TypeId.fromName("Gui::View3DInventor") + ) # All 3D views. for view in views: if view in self.trackers[0]: i = self.trackers[0].index(view) @@ -1598,22 +1604,18 @@ class Snapper: else: grid.off() - def show(self): """Show the grid in all 3D views where it was previously visible.""" self.show_hide_grids(show=True) - def hide(self): """Hide the grid in all 3D views.""" self.show_hide_grids(show=False) - def setGrid(self): """Set the grid, if visible.""" self.setTrackers() - def setTrackers(self, update_grid=True): """Set the trackers.""" v = Draft.get3DView() @@ -1663,13 +1665,13 @@ class Snapper: if not update_grid: return - if self.grid.show_always \ - or (self.grid.show_during_command \ - and hasattr(App, "activeDraftCommand") \ - and App.activeDraftCommand): + if self.grid.show_always or ( + self.grid.show_during_command + and hasattr(App, "activeDraftCommand") + and App.activeDraftCommand + ): self.grid.set() - def addHoldPoint(self): """Add hold snap point to list of hold points.""" if self.spoint and self.spoint not in self.holdPoints: diff --git a/src/Mod/Draft/draftguitools/gui_snaps.py b/src/Mod/Draft/draftguitools/gui_snaps.py index 95999ac237..18c0c39bb6 100644 --- a/src/Mod/Draft/draftguitools/gui_snaps.py +++ b/src/Mod/Draft/draftguitools/gui_snaps.py @@ -40,7 +40,7 @@ from draftutils.messages import _log from draftutils.translate import translate -class Draft_Snap_Base(): +class Draft_Snap_Base: """Base Class inherited by all Draft Snap commands.""" def Activated(self, status=0): @@ -61,14 +61,19 @@ class Draft_Snap_Lock(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Lock tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Lock", - "Accel": "Shift+S", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Snap Lock"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Enables or disables snapping globally"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Lock", + "Accel": "Shift+S", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Snap Lock"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Lock", "Enables or disables snapping globally" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } - def IsActive(self): return True + def IsActive(self): + return True Gui.addCommand("Draft_Snap_Lock", Draft_Snap_Lock()) @@ -78,11 +83,13 @@ class Draft_Snap_Midpoint(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Midpoint tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Midpoint", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Midpoint", "Snap Midpoint"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Midpoint", "Snaps to the midpoint of edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Midpoint", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Midpoint", "Snap Midpoint"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Midpoint", "Snaps to the midpoint of edges"), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Midpoint", Draft_Snap_Midpoint()) @@ -92,11 +99,15 @@ class Draft_Snap_Perpendicular(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Perpendicular tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Perpendicular", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Perpendicular", "Snap Perpendicular"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Perpendicular", "Snaps to the perpendicular points on faces and edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Perpendicular", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Perpendicular", "Snap Perpendicular"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Perpendicular", "Snaps to the perpendicular points on faces and edges" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Perpendicular", Draft_Snap_Perpendicular()) @@ -106,11 +117,15 @@ class Draft_Snap_Grid(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Grid tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Grid", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Grid", "Snap Grid"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Grid", "Snaps to the intersections of grid lines"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Grid", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Grid", "Snap Grid"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Grid", "Snaps to the intersections of grid lines" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Grid", Draft_Snap_Grid()) @@ -120,11 +135,16 @@ class Draft_Snap_Intersection(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Intersection tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Intersection", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Intersection", "Snap Intersection"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Intersection", "Snaps to the intersection of 2 edges, and the intersection of a face and an edge"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Intersection", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Intersection", "Snap Intersection"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Intersection", + "Snaps to the intersection of 2 edges, and the intersection of a face and an edge", + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Intersection", Draft_Snap_Intersection()) @@ -134,11 +154,15 @@ class Draft_Snap_Parallel(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Parallel tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Parallel", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Parallel", "Snap Parallel"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Parallel", "Snaps to an imaginary line parallel to straight edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Parallel", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Parallel", "Snap Parallel"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Parallel", "Snaps to an imaginary line parallel to straight edges" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Parallel", Draft_Snap_Parallel()) @@ -148,11 +172,13 @@ class Draft_Snap_Endpoint(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Endpoint tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Endpoint", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Endpoint", "Snap Endpoint"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Endpoint", "Snaps to the endpoints of edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Endpoint", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Endpoint", "Snap Endpoint"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Endpoint", "Snaps to the endpoints of edges"), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Endpoint", Draft_Snap_Endpoint()) @@ -162,11 +188,16 @@ class Draft_Snap_Angle(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Angle tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Angle", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Angle", "Snap Angle"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Angle", "Snaps to the special cardinal points on circular edges, at multiples of 30° and 45°"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Angle", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Angle", "Snap Angle"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Angle", + "Snaps to the special cardinal points on circular edges, at multiples of 30° and 45°", + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Angle", Draft_Snap_Angle()) @@ -176,11 +207,16 @@ class Draft_Snap_Center(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Center tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Center", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Center", "Snap Center"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Center", "Snaps to the center point of faces and circular edges, and to the placement point of working plane proxies and building parts"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Center", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Center", "Snap Center"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Center", + "Snaps to the center point of faces and circular edges, and to the placement point of working plane proxies and building parts", + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Center", Draft_Snap_Center()) @@ -190,11 +226,16 @@ class Draft_Snap_Extension(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Extension tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Extension", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Extension", "Snap Extension"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Extension", "Snaps to an imaginary line that extends beyond the endpoints of straight edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Extension", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Extension", "Snap Extension"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Extension", + "Snaps to an imaginary line that extends beyond the endpoints of straight edges", + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Extension", Draft_Snap_Extension()) @@ -204,11 +245,15 @@ class Draft_Snap_Near(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Near tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Near", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Near", "Snap Near"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Near", "Snaps to the nearest point on faces and edges"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Near", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Near", "Snap Near"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Near", "Snaps to the nearest point on faces and edges" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Near", Draft_Snap_Near()) @@ -218,11 +263,16 @@ class Draft_Snap_Ortho(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Ortho tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Ortho", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Ortho", "Snap Ortho"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Ortho", "Snaps to imaginary lines that cross the previous point at multiples of 45°"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Ortho", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Ortho", "Snap Ortho"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Ortho", + "Snaps to imaginary lines that cross the previous point at multiples of 45°", + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Ortho", Draft_Snap_Ortho()) @@ -232,11 +282,15 @@ class Draft_Snap_Special(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Special tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Special", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Special", "Snap Special"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Special", "Snaps to special points defined by the object"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Special", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Special", "Snap Special"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Special", "Snaps to special points defined by the object" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Special", Draft_Snap_Special()) @@ -246,11 +300,15 @@ class Draft_Snap_Dimensions(Draft_Snap_Base): """GuiCommand for the Draft_Snap_Dimensions tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_Dimensions", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Dimensions", "Snap Dimensions"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_Dimensions", "Shows temporary X and Y dimensions"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_Dimensions", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_Dimensions", "Snap Dimensions"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_Dimensions", "Shows temporary X and Y dimensions" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_Dimensions", Draft_Snap_Dimensions()) @@ -260,11 +318,15 @@ class Draft_Snap_WorkingPlane(Draft_Snap_Base): """GuiCommand for the Draft_Snap_WorkingPlane tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap_WorkingPlane", - "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_WorkingPlane", "Snap Working Plane"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Snap_WorkingPlane", "Projects snap points onto the current working plane"), - "CmdType": "NoTransaction", - "Checkable": self.isChecked()} + return { + "Pixmap": "Draft_Snap_WorkingPlane", + "MenuText": QT_TRANSLATE_NOOP("Draft_Snap_WorkingPlane", "Snap Working Plane"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Snap_WorkingPlane", "Projects snap points onto the current working plane" + ), + "CmdType": "NoTransaction", + "Checkable": self.isChecked(), + } Gui.addCommand("Draft_Snap_WorkingPlane", Draft_Snap_WorkingPlane()) @@ -274,10 +336,14 @@ class ShowSnapBar(Draft_Snap_Base): """GuiCommand for the Draft_ShowSnapBar tool.""" def GetResources(self): - return {"Pixmap": "Draft_Snap", - "MenuText": QT_TRANSLATE_NOOP("Draft_ShowSnapBar", "Show Snap Toolbar"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ShowSnapBar", "Shows the snap toolbar if it is hidden"), - "CmdType": "NoTransaction"} + return { + "Pixmap": "Draft_Snap", + "MenuText": QT_TRANSLATE_NOOP("Draft_ShowSnapBar", "Show Snap Toolbar"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ShowSnapBar", "Shows the snap toolbar if it is hidden" + ), + "CmdType": "NoTransaction", + } def Activated(self): """Execute when the command is called.""" @@ -287,6 +353,6 @@ class ShowSnapBar(Draft_Snap_Base): toolbar.show() -Gui.addCommand('Draft_ShowSnapBar', ShowSnapBar()) +Gui.addCommand("Draft_ShowSnapBar", ShowSnapBar()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_splines.py b/src/Mod/Draft/draftguitools/gui_splines.py index 212e2dc37e..b4cf2ef3da 100644 --- a/src/Mod/Draft/draftguitools/gui_splines.py +++ b/src/Mod/Draft/draftguitools/gui_splines.py @@ -55,17 +55,21 @@ class BSpline(gui_lines.Line): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_BSpline', - 'Accel': "B, S", - 'MenuText': QT_TRANSLATE_NOOP("Draft_BSpline", "B-Spline"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_BSpline", "Creates a multiple-point B-spline")} + return { + "Pixmap": "Draft_BSpline", + "Accel": "B, S", + "MenuText": QT_TRANSLATE_NOOP("Draft_BSpline", "B-Spline"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_BSpline", "Creates a multiple-point B-spline"), + } def Activated(self): """Execute when the command is called. Activate the specific BSpline tracker. """ - super(BSpline, self).Activated(name="Bspline", icon="Draft_BSpline", task_title=translate("draft","B-Spline")) + super(BSpline, self).Activated( + name="Bspline", icon="Draft_BSpline", task_title=translate("draft", "B-Spline") + ) if self.doc: self.bsplinetrack = trackers.bsplineTracker() @@ -125,6 +129,7 @@ class BSpline(gui_lines.Line): def undolast(self): """Undo last line segment.""" import Part + if len(self.node) > 1: self.node.pop() self.bsplinetrack.update(self.node) @@ -136,6 +141,7 @@ class BSpline(gui_lines.Line): def drawUpdate(self, point): """Draw and update to the spline.""" import Part + if len(self.node) == 1: self.bsplinetrack.on() if self.planetrack: @@ -173,19 +179,20 @@ class BSpline(gui_lines.Line): rot, sup, pts, fil = self.getStrings() Gui.addModule("Draft") - _cmd = 'Draft.make_bspline' - _cmd += '(' - _cmd += 'points, ' - _cmd += 'closed=' + str(closed) + ', ' - _cmd += 'face=' + fil + ', ' - _cmd += 'support=' + sup - _cmd += ')' - _cmd_list = ['points = ' + pts, - 'spline = ' + _cmd, - 'Draft.autogroup(spline)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create B-Spline"), - _cmd_list) + _cmd = "Draft.make_bspline" + _cmd += "(" + _cmd += "points, " + _cmd += "closed=" + str(closed) + ", " + _cmd += "face=" + fil + ", " + _cmd += "support=" + sup + _cmd += ")" + _cmd_list = [ + "points = " + pts, + "spline = " + _cmd, + "Draft.autogroup(spline)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create B-Spline"), _cmd_list) except Exception: _err("Draft: error delaying commit") @@ -200,6 +207,6 @@ class BSpline(gui_lines.Line): self.Activated() -Gui.addCommand('Draft_BSpline', BSpline()) +Gui.addCommand("Draft_BSpline", BSpline()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_split.py b/src/Mod/Draft/draftguitools/gui_split.py index 6be1b5fc0a..e90c628d3d 100644 --- a/src/Mod/Draft/draftguitools/gui_split.py +++ b/src/Mod/Draft/draftguitools/gui_split.py @@ -46,10 +46,14 @@ class Split(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {"Pixmap": "Draft_Split", - "Accel": "S, P", - "MenuText": QT_TRANSLATE_NOOP("Draft_Split", "Split"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_Split", "Splits the selected line or polyline at a specified point")} + return { + "Pixmap": "Draft_Split", + "Accel": "S, P", + "MenuText": QT_TRANSLATE_NOOP("Draft_Split", "Split"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Split", "Splits the selected line or polyline at a specified point" + ), + } def Activated(self): """Execute when the command is called.""" @@ -77,9 +81,11 @@ class Split(gui_base_original.Modifier): elif arg["Type"] == "SoLocation2Event": gui_tool_utils.getPoint(self, arg) gui_tool_utils.redraw3DView() - elif (arg["Type"] == "SoMouseButtonEvent" - and arg["Button"] == "BUTTON1" - and arg["State"] == "DOWN"): + elif ( + arg["Type"] == "SoMouseButtonEvent" + and arg["Button"] == "BUTTON1" + and arg["State"] == "DOWN" + ): self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) if info is not None and "Edge" in info["Component"]: return self.proceed(info) @@ -95,7 +101,7 @@ class Split(gui_base_original.Modifier): cmd_list = [ "obj = FreeCAD.ActiveDocument." + wire, "new = Draft.split(obj, " + point + ", " + index + ")", - "FreeCAD.ActiveDocument.recompute()" + "FreeCAD.ActiveDocument.recompute()", ] self.commit(translate("draft", "Split Line"), cmd_list) @@ -107,6 +113,6 @@ class Split(gui_base_original.Modifier): super().finish() -Gui.addCommand('Draft_Split', Split()) +Gui.addCommand("Draft_Split", Split()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_stretch.py b/src/Mod/Draft/draftguitools/gui_stretch.py index 2c4e9b60d8..e566ff8d24 100644 --- a/src/Mod/Draft/draftguitools/gui_stretch.py +++ b/src/Mod/Draft/draftguitools/gui_stretch.py @@ -59,10 +59,12 @@ class Stretch(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Stretch', - 'Accel': "S, H", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Stretch", "Stretch"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Stretch", "Stretches the selected objects")} + return { + "Pixmap": "Draft_Stretch", + "Accel": "S, H", + "MenuText": QT_TRANSLATE_NOOP("Draft_Stretch", "Stretch"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Stretch", "Stretches the selected objects"), + } def Activated(self): """Execute when the command is called.""" @@ -73,9 +75,7 @@ class Stretch(gui_base_original.Modifier): if not Gui.Selection.getSelection(): self.ui.selectUi(on_close_call=self.finish) _msg(translate("draft", "Select an object to stretch")) - self.call = \ - self.view.addEventCallback("SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() @@ -104,7 +104,9 @@ class Stretch(gui_base_original.Modifier): elif hasattr(obj.Base, "Base"): if obj.Base.Base: if utils.getType(obj.Base.Base) in supported: - self.sel.append([obj.Base.Base, obj.Placement.multiply(obj.Base.Placement)]) + self.sel.append( + [obj.Base.Base, obj.Placement.multiply(obj.Base.Placement)] + ) elif utils.getType(obj) in ["Offset2D", "Array"]: base = None if hasattr(obj, "Source") and obj.Source: @@ -119,9 +121,9 @@ class Stretch(gui_base_original.Modifier): self.refpoint = None self.ui.pointUi(title=translate("draft", self.featureName), icon="Draft_Stretch") self.call = self.view.addEventCallback("SoEvent", self.action) - self.rectracker = trackers.rectangleTracker(dotted=True, - scolor=(0.0, 0.0, 1.0), - swidth=2) + self.rectracker = trackers.rectangleTracker( + dotted=True, scolor=(0.0, 0.0, 1.0), swidth=2 + ) self.nodetracker = [] self.displacement = None _toolmsg(translate("draft", "Pick first point of selection rectangle")) @@ -158,8 +160,7 @@ class Stretch(gui_base_original.Modifier): """Add point to defined selection rectangle.""" if self.step == 1: # first rctangle point - _toolmsg(translate("draft", "Pick the opposite point " - "of the selection rectangle")) + _toolmsg(translate("draft", "Pick the opposite point " "of the selection rectangle")) self.ui.setRelative(-1) self.rectracker.setorigin(point) self.rectracker.on() @@ -294,7 +295,9 @@ class Stretch(gui_base_original.Modifier): _cmd = _doc + ops[0].Name + ".Points=" + pts commitops.append(_cmd) elif tp in ["Sketch"]: - baseverts = [ops[0].Shape.Vertexes[i].Point for i in range(len(ops[1])) if ops[1][i]] + baseverts = [ + ops[0].Shape.Vertexes[i].Point for i in range(len(ops[1])) if ops[1][i] + ] for i in range(ops[0].GeometryCount): j = 0 while True: @@ -325,9 +328,7 @@ class Stretch(gui_base_original.Modifier): elif tp in ["Rectangle"]: p1 = App.Vector(0, 0, 0) p2 = App.Vector(ops[0].Length.Value, 0, 0) - p3 = App.Vector(ops[0].Length.Value, - ops[0].Height.Value, - 0) + p3 = App.Vector(ops[0].Length.Value, ops[0].Height.Value, 0) p4 = App.Vector(0, ops[0].Height.Value, 0) if ops[1] == [False, True, True, False]: optype = 1 @@ -486,6 +487,6 @@ class Stretch(gui_base_original.Modifier): self.finish() -Gui.addCommand('Draft_Stretch', Stretch()) +Gui.addCommand("Draft_Stretch", Stretch()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_styles.py b/src/Mod/Draft/draftguitools/gui_styles.py index 5661f80382..111a8e2030 100644 --- a/src/Mod/Draft/draftguitools/gui_styles.py +++ b/src/Mod/Draft/draftguitools/gui_styles.py @@ -37,6 +37,7 @@ from draftguitools import gui_base_original from draftutils.translate import translate from draftutils import groups + class ApplyStyle(gui_base_original.Modifier): """Gui Command for the ApplyStyle tool.""" @@ -45,7 +46,9 @@ class ApplyStyle(gui_base_original.Modifier): return { "Pixmap": "Draft_Apply", "MenuText": QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Apply Current Style"), - "ToolTip": QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Applies the current style to the selected objects and groups") + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ApplyStyle", "Applies the current style to the selected objects and groups" + ), } def IsActive(self): @@ -60,8 +63,10 @@ class ApplyStyle(gui_base_original.Modifier): Gui.addModule("Draft") cmd_list = [ "doc = FreeCAD.ActiveDocument", - "Draft.apply_current_style([" + ", ".join(["doc." + obj.Name for obj in objs]) + "])", - "doc.recompute()" + "Draft.apply_current_style([" + + ", ".join(["doc." + obj.Name for obj in objs]) + + "])", + "doc.recompute()", ] self.commit(translate("draft", "Change Style"), cmd_list) self.finish() diff --git a/src/Mod/Draft/draftguitools/gui_subelements.py b/src/Mod/Draft/draftguitools/gui_subelements.py index 94aa97d5ca..559ed1a77b 100644 --- a/src/Mod/Draft/draftguitools/gui_subelements.py +++ b/src/Mod/Draft/draftguitools/gui_subelements.py @@ -57,10 +57,15 @@ class SubelementHighlight(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_SubelementHighlight', - 'Accel': "H, S", - 'MenuText': QT_TRANSLATE_NOOP("Draft_SubelementHighlight","Highlight Subelements"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_SubelementHighlight","Highlights the subelements of the selected objects, to be able to move, rotate, and scale them")} + return { + "Pixmap": "Draft_SubelementHighlight", + "Accel": "H, S", + "MenuText": QT_TRANSLATE_NOOP("Draft_SubelementHighlight", "Highlight Subelements"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_SubelementHighlight", + "Highlights the subelements of the selected objects, to be able to move, rotate, and scale them", + ), + } def Activated(self): """Execute when the command is called.""" @@ -108,20 +113,23 @@ class SubelementHighlight(gui_base_original.Modifier): """Get the selection.""" if not Gui.Selection.getSelection() and self.ui: _msg(translate("draft", "Select an object to edit")) - self.call = self.view.addEventCallback("SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() def get_editable_objects_from_selection(self): """Get editable Draft objects for the selection.""" for obj in Gui.Selection.getSelection(): - if (obj.isDerivedFrom("Part::Part2DObject") - or utils.get_type(obj) in ["BezCurve", "BSpline", "Wire"]): + if obj.isDerivedFrom("Part::Part2DObject") or utils.get_type(obj) in [ + "BezCurve", + "BSpline", + "Wire", + ]: self.editable_objects.append(obj) - elif (hasattr(obj, "Base") - and (obj.Base.isDerivedFrom("Part::Part2DObject") - or utils.get_type(obj.Base) in ["BezCurve", "BSpline", "Wire"])): + elif hasattr(obj, "Base") and ( + obj.Base.isDerivedFrom("Part::Part2DObject") + or utils.get_type(obj.Base) in ["BezCurve", "BSpline", "Wire"] + ): self.editable_objects.append(obj.Base) def highlight_editable_objects(self): @@ -129,10 +137,11 @@ class SubelementHighlight(gui_base_original.Modifier): for obj in self.editable_objects: vobj = obj.ViewObject self.original_view_settings[obj.Name] = { - 'Visibility': vobj.Visibility, - 'PointSize': vobj.PointSize, - 'PointColor': vobj.PointColor, - 'LineColor': vobj.LineColor} + "Visibility": vobj.Visibility, + "PointSize": vobj.PointSize, + "PointColor": vobj.PointColor, + "LineColor": vobj.LineColor, + } vobj.Visibility = True vobj.PointSize = 10 vobj.PointColor = (1.0, 0.0, 0.0) @@ -157,6 +166,6 @@ class SubelementHighlight(gui_base_original.Modifier): pass -Gui.addCommand('Draft_SubelementHighlight', SubelementHighlight()) +Gui.addCommand("Draft_SubelementHighlight", SubelementHighlight()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_texts.py b/src/Mod/Draft/draftguitools/gui_texts.py index 104bea8bef..7696cbe8cf 100644 --- a/src/Mod/Draft/draftguitools/gui_texts.py +++ b/src/Mod/Draft/draftguitools/gui_texts.py @@ -55,16 +55,18 @@ class Text(gui_base_original.Creator): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Text', - 'Accel': "T, E", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Text", "Text"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Text", "Creates a multi-line annotation")} + return { + "Pixmap": "Draft_Text", + "Accel": "T, E", + "MenuText": QT_TRANSLATE_NOOP("Draft_Text", "Text"), + "ToolTip": QT_TRANSLATE_NOOP("Draft_Text", "Creates a multi-line annotation"), + } def Activated(self): """Execute when the command is called.""" super().Activated(name="Text") if self.ui: - self.text = '' + self.text = "" self.ui.sourceCmd = self self.ui.pointUi(title=translate("draft", self.featureName), icon="Draft_Text") self.ui.isRelative.hide() @@ -108,23 +110,24 @@ class Text(gui_base_original.Creator): list_as_text = ", ".join(t_list) - string = '[' + list_as_text + ']' + string = "[" + list_as_text + "]" Gui.addModule("Draft") - _cmd = 'Draft.make_text' - _cmd += '(' - _cmd += string + ', ' - _cmd += 'placement=pl, ' - _cmd += 'screen=None, height=None, line_spacing=None' - _cmd += ')' - _cmd_list = ['pl = FreeCAD.Placement()', - 'pl.Rotation.Q = ' + rot, - 'pl.Base = ' + base, - '_text_ = ' + _cmd, - 'Draft.autogroup(_text_)', - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Create Text"), - _cmd_list) + _cmd = "Draft.make_text" + _cmd += "(" + _cmd += string + ", " + _cmd += "placement=pl, " + _cmd += "screen=None, height=None, line_spacing=None" + _cmd += ")" + _cmd_list = [ + "pl = FreeCAD.Placement()", + "pl.Rotation.Q = " + rot, + "pl.Base = " + base, + "_text_ = " + _cmd, + "Draft.autogroup(_text_)", + "FreeCAD.ActiveDocument.recompute()", + ] + self.commit(translate("draft", "Create Text"), _cmd_list) self.finish(cont=None) def action(self, arg): @@ -143,8 +146,7 @@ class Text(gui_base_original.Creator): self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection if self.active: - (self.point, - ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) + (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1": @@ -167,6 +169,6 @@ class Text(gui_base_original.Creator): self.ui.textValue.setFocus() -Gui.addCommand('Draft_Text', Text()) +Gui.addCommand("Draft_Text", Text()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_togglemodes.py b/src/Mod/Draft/draftguitools/gui_togglemodes.py index edc0c283ae..957648f69f 100644 --- a/src/Mod/Draft/draftguitools/gui_togglemodes.py +++ b/src/Mod/Draft/draftguitools/gui_togglemodes.py @@ -70,7 +70,7 @@ class BaseMode(gui_base.GuiCommandSimplest): if hasattr(Gui, "draftToolBar"): _ui = Gui.draftToolBar else: - _msg(translate("draft","No active Draft toolbar")) + _msg(translate("draft", "No active Draft toolbar")) return if _ui is not None: @@ -89,16 +89,21 @@ class ToggleConstructionMode(BaseMode): """ def __init__(self): - super(ToggleConstructionMode, - self).__init__(name=translate("draft","Construction Mode")) + super(ToggleConstructionMode, self).__init__(name=translate("draft", "Construction Mode")) def GetResources(self): """Set icon, menu and tooltip.""" - d = {'Pixmap': 'Draft_Construction', - 'MenuText': QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode","Toggle Construction Mode"), - 'Accel': "C, M", - 'ToolTip': QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode","Toggles the construction mode")} + d = { + "Pixmap": "Draft_Construction", + "MenuText": QT_TRANSLATE_NOOP( + "Draft_ToggleConstructionMode", "Toggle Construction Mode" + ), + "Accel": "C, M", + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ToggleConstructionMode", "Toggles the construction mode" + ), + } return d def Activated(self): @@ -110,7 +115,7 @@ class ToggleConstructionMode(BaseMode): super(ToggleConstructionMode, self).Activated(mode="construction") -Gui.addCommand('Draft_ToggleConstructionMode', ToggleConstructionMode()) +Gui.addCommand("Draft_ToggleConstructionMode", ToggleConstructionMode()) class ToggleDisplayMode(gui_base.GuiCommandNeedsSelection): @@ -125,16 +130,20 @@ class ToggleDisplayMode(gui_base.GuiCommandNeedsSelection): """ def __init__(self): - super(ToggleDisplayMode, - self).__init__(name=translate("draft","Toggle Display Mode")) + super(ToggleDisplayMode, self).__init__(name=translate("draft", "Toggle Display Mode")) def GetResources(self): """Set icon, menu and tooltip.""" - d = {'Pixmap': 'Draft_SwitchMode', - 'Accel': "Shift+Space", - 'MenuText': QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode","Toggle Wireframe"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode","Switches the view style of the selected objects from Flat Lines to Wireframe and back")} + d = { + "Pixmap": "Draft_SwitchMode", + "Accel": "Shift+Space", + "MenuText": QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode", "Toggle Wireframe"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_ToggleDisplayMode", + "Switches the view style of the selected objects from Flat Lines to Wireframe and back", + ), + } return d def Activated(self): @@ -155,6 +164,6 @@ class ToggleDisplayMode(gui_base.GuiCommandNeedsSelection): obj.ViewObject.DisplayMode = "Flat Lines" -Gui.addCommand('Draft_ToggleDisplayMode', ToggleDisplayMode()) +Gui.addCommand("Draft_ToggleDisplayMode", ToggleDisplayMode()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_tool_utils.py b/src/Mod/Draft/draftguitools/gui_tool_utils.py index 4190bb4d37..b4e638fff0 100644 --- a/src/Mod/Draft/draftguitools/gui_tool_utils.py +++ b/src/Mod/Draft/draftguitools/gui_tool_utils.py @@ -68,6 +68,7 @@ _HINT_MOD_KEYS = [Gui.UserInput.KeyShift, Gui.UserInput.KeyControl, Gui.UserInpu # To allows for easy concatenation the _get_hint_* functions # always return a list (with a single item or an empty list). + def _get_hint_mod_constrain(): key = _HINT_MOD_KEYS[params.get_param("modconstrain")] return [Gui.InputHint(translate("draft", "%1 constrain"), key)] @@ -85,13 +86,17 @@ def _get_hint_xyz_constrain(): shortcut_x = params.get_param("inCommandShortcutRestrictX").upper() shortcut_y = params.get_param("inCommandShortcutRestrictY").upper() shortcut_z = params.get_param("inCommandShortcutRestrictZ").upper() - if pattern.fullmatch(shortcut_x) \ - and pattern.fullmatch(shortcut_y) \ - and pattern.fullmatch(shortcut_z): + if ( + pattern.fullmatch(shortcut_x) + and pattern.fullmatch(shortcut_y) + and pattern.fullmatch(shortcut_z) + ): key_x = getattr(Gui.UserInput, "Key" + shortcut_x) key_y = getattr(Gui.UserInput, "Key" + shortcut_y) key_z = getattr(Gui.UserInput, "Key" + shortcut_z) - return [Gui.InputHint(translate("draft", "%1/%2/%3 switch constraint"), key_x, key_y, key_z)] + return [ + Gui.InputHint(translate("draft", "%1/%2/%3 switch constraint"), key_x, key_y, key_z) + ] return [] @@ -267,11 +272,9 @@ def get_point(target, args, noTracker=False): point = None if hasattr(Gui, "Snapper"): - point = Gui.Snapper.snap(args["Position"], - lastpoint=last, - active=smod, - constrain=cmod, - noTracker=noTracker) + point = Gui.Snapper.snap( + args["Position"], lastpoint=last, active=smod, constrain=cmod, noTracker=noTracker + ) info = Gui.Snapper.snapInfo mask = Gui.Snapper.affinity if not point: @@ -310,9 +313,9 @@ def set_working_plane_to_object_under_cursor(mouseEvent): App::DocumentObject or None The parent object the face belongs to, if alignment occurred, or None. """ - objectUnderCursor = gui_utils.get_3d_view().getObjectInfo(( - mouseEvent["Position"][0], - mouseEvent["Position"][1])) + objectUnderCursor = gui_utils.get_3d_view().getObjectInfo( + (mouseEvent["Position"][0], mouseEvent["Position"][1]) + ) if not objectUnderCursor: return None @@ -323,6 +326,7 @@ def set_working_plane_to_object_under_cursor(mouseEvent): return None import Part + if "ParentObject" in objectUnderCursor: obj = objectUnderCursor["ParentObject"] sub = objectUnderCursor["SubName"] @@ -357,14 +361,16 @@ def set_working_plane_to_selected_object(): sels = Gui.Selection.getSelectionEx("", 0) - if len(sels) == 1 \ - and len(sels[0].SubObjects) == 1 \ - and sels[0].SubObjects[0].ShapeType == "Face": + if ( + len(sels) == 1 + and len(sels[0].SubObjects) == 1 + and sels[0].SubObjects[0].ShapeType == "Face" + ): import Part - shape = Part.getShape(sels[0].Object, - sels[0].SubElementNames[0], - needSubElement=True, - retType=0) + + shape = Part.getShape( + sels[0].Object, sels[0].SubElementNames[0], needSubElement=True, retType=0 + ) if wp.align_to_face(shape, _hist_add=False): wp.auto = True @@ -377,7 +383,7 @@ setWorkingPlaneToSelectedObject = set_working_plane_to_selected_object def get_support(mouseEvent=None): - """"Align the working plane to a preselected face or the face under the cursor. + """ "Align the working plane to a preselected face or the face under the cursor. The working plane is only aligned if it is `'auto'`. diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py index 67e93748ce..be440e4229 100644 --- a/src/Mod/Draft/draftguitools/gui_trackers.py +++ b/src/Mod/Draft/draftguitools/gui_trackers.py @@ -58,11 +58,11 @@ __url__ = "https://www.freecad.org" class Tracker: """A generic Draft Tracker, to be used by other specific trackers.""" - def __init__(self, dotted=False, scolor=None, swidth=None, - children=[], ontop=False, name=None): + def __init__(self, dotted=False, scolor=None, swidth=None, children=[], ontop=False, name=None): global Part, DraftGeomUtils import Part import DraftGeomUtils + self.ontop = ontop self.color = coin.SoBaseColor() drawstyle = coin.SoDrawStyle() @@ -71,7 +71,7 @@ class Tracker: if dotted: drawstyle.style = coin.SoDrawStyle.LINES drawstyle.lineWeight = 3 - drawstyle.linePattern = 0x0f0f # 0xaa + drawstyle.linePattern = 0x0F0F # 0xaa node = coin.SoSeparator() for c in [drawstyle, self.color] + children: node.addChild(c) @@ -92,8 +92,7 @@ class Tracker: self.switch = None def get_scene_graph(self): - """Returns the current scenegraph or None if this is not a 3D view - """ + """Returns the current scenegraph or None if this is not a 3D view""" v = Draft.get3DView() if v: return v.getSceneGraph() @@ -164,13 +163,17 @@ class Tracker: """Set the color.""" if color is not None: self.color.rgb = color - elif hasattr(FreeCAD, "activeDraftCommand") \ - and FreeCAD.activeDraftCommand is not None \ - and hasattr(FreeCAD.activeDraftCommand, "featureName") \ - and FreeCAD.activeDraftCommand.featureName in ("Dimension", "Label", "Text"): + elif ( + hasattr(FreeCAD, "activeDraftCommand") + and FreeCAD.activeDraftCommand is not None + and hasattr(FreeCAD.activeDraftCommand, "featureName") + and FreeCAD.activeDraftCommand.featureName in ("Dimension", "Label", "Text") + ): self.color.rgb = utils.get_rgba_tuple(params.get_param("DefaultAnnoLineColor"))[:3] else: - self.color.rgb = utils.get_rgba_tuple(params.get_param_view("DefaultShapeLineColor"))[:3] + self.color.rgb = utils.get_rgba_tuple(params.get_param_view("DefaultShapeLineColor"))[ + :3 + ] def _get_wp(self): return FreeCAD.DraftWorkingPlane @@ -181,7 +184,9 @@ class snapTracker(Tracker): def __init__(self): self.marker = coin.SoMarkerSet() # this is the marker symbol - self.marker.markerIndex = FreeCADGui.getMarkerIndex("CIRCLE_FILLED", params.get_param_view("MarkerSize")) + self.marker.markerIndex = FreeCADGui.getMarkerIndex( + "CIRCLE_FILLED", params.get_param_view("MarkerSize") + ) self.coords = coin.SoCoordinate3() # this is the coordinate self.coords.point.setValue((0, 0, 0)) node = coin.SoAnnotation() @@ -192,7 +197,9 @@ class snapTracker(Tracker): def setMarker(self, style): """Set the marker index.""" - self.marker.markerIndex = FreeCADGui.getMarkerIndex(style, params.get_param_view("MarkerSize")) + self.marker.markerIndex = FreeCADGui.getMarkerIndex( + style, params.get_param_view("MarkerSize") + ) def setColor(self, color=None): """Set the color.""" @@ -224,9 +231,7 @@ class lineTracker(Tracker): line.numVertices.setValue(2) self.coords = coin.SoCoordinate3() # this is the coordinate self.coords.point.setValues(0, 2, [[0, 0, 0], [1, 0, 0]]) - super().__init__(dotted, scolor, swidth, - [self.coords, line], - ontop, name="lineTracker") + super().__init__(dotted, scolor, swidth, [self.coords, line], ontop, name="lineTracker") def p1(self, point=None): """Set or get the first point of the line.""" @@ -273,13 +278,13 @@ class polygonTracker(Tracker): m1.diffuseColor.setValue([0.5, 0.5, 1.0]) f = coin.SoIndexedFaceSet() f.coordIndex.setValues([0, 1, 2, 3]) - super().__init__(dotted, scolor, swidth, - [self.coords, self.line, m1, f], - name="polygonTracker") + super().__init__( + dotted, scolor, swidth, [self.coords, self.line, m1, f], name="polygonTracker" + ) else: - super().__init__(dotted, scolor, swidth, - [self.coords, self.line], - name="polygonTracker") + super().__init__( + dotted, scolor, swidth, [self.coords, self.line], name="polygonTracker" + ) def setNumVertices(self, num): self.line.numVertices.setValue(num + 1) @@ -312,6 +317,7 @@ class polygonTracker(Tracker): radius = math.hypot(local_vec.x, local_vec.y) self._drawPolygon(self.origin, radius) + class rectangleTracker(Tracker): """A Rectangle tracker, used by the rectangle tool.""" @@ -333,13 +339,11 @@ class rectangleTracker(Tracker): m1.diffuseColor.setValue([0.5, 0.5, 1.0]) f = coin.SoIndexedFaceSet() f.coordIndex.setValues([0, 1, 2, 3]) - super().__init__(dotted, scolor, swidth, - [self.coords, line, m1, f], - name="rectangleTracker") + super().__init__( + dotted, scolor, swidth, [self.coords, line, m1, f], name="rectangleTracker" + ) else: - super().__init__(dotted, scolor, swidth, - [self.coords, line], - name="rectangleTracker") + super().__init__(dotted, scolor, swidth, [self.coords, line], name="rectangleTracker") wp = self._get_wp() self.u = wp.u self.v = wp.v @@ -399,8 +403,10 @@ class rectangleTracker(Tracker): p1 = Vector(self.coords.point.getValues()[0].getValue()) p2 = Vector(self.coords.point.getValues()[2].getValue()) diag = p2.sub(p1) - return ((DraftVecUtils.project(diag, self.u)).Length, - (DraftVecUtils.project(diag, self.v)).Length) + return ( + (DraftVecUtils.project(diag, self.u)).Length, + (DraftVecUtils.project(diag, self.v)).Length, + ) def getNormal(self): """Return the normal of the rectangle.""" @@ -435,8 +441,7 @@ class dimTracker(Tracker): [0, 0, 0], [0, 0, 0]]) # fmt: on - super().__init__(dotted, scolor, swidth, - [self.coords, line], name="dimTracker") + super().__init__(dotted, scolor, swidth, [self.coords, line], name="dimTracker") self.p1 = self.p2 = self.p3 = None def update(self, pts): @@ -455,6 +460,7 @@ class dimTracker(Tracker): def calc(self): """Calculate the new points from p1 and p2.""" import Part + if (self.p1 is not None) and (self.p2 is not None): # fmt: off points = [DraftVecUtils.tup(self.p1, True), @@ -494,8 +500,7 @@ class bsplineTracker(Tracker): self.trans = coin.SoTransform() self.sep = coin.SoSeparator() self.recompute() - super().__init__(dotted, scolor, swidth, - [self.trans, self.sep], name="bsplineTracker") + super().__init__(dotted, scolor, swidth, [self.trans, self.sep], name="bsplineTracker") def update(self, points): """Update the points and recompute.""" @@ -508,9 +513,11 @@ class bsplineTracker(Tracker): if self.bspline: self.sep.removeChild(self.bspline) self.bspline = None - c = Part.BSplineCurve() + c = Part.BSplineCurve() # DNC: allows one to close the curve by placing ends close to each other - if len(self.points) >= 3 and ( (self.points[0] - self.points[-1]).Length < Draft.tolerance() ): + if len(self.points) >= 3 and ( + (self.points[0] - self.points[-1]).Length < Draft.tolerance() + ): # YVH: Added a try to bypass some hazardous situations try: c.interpolate(self.points[:-1], True) @@ -554,7 +561,9 @@ class bsplineTracker(Tracker): self.bspline.removeChild(self.bspline.getChild(0)) self.sep.addChild(self.bspline) else: - FreeCAD.Console.PrintWarning("bsplineTracker.recompute() failed to read-in Inventor string\n") + FreeCAD.Console.PrintWarning( + "bsplineTracker.recompute() failed to read-in Inventor string\n" + ) class bezcurveTracker(Tracker): @@ -567,8 +576,7 @@ class bezcurveTracker(Tracker): self.trans = coin.SoTransform() self.sep = coin.SoSeparator() self.recompute() - super().__init__(dotted, scolor, swidth, - [self.trans, self.sep], name="bezcurveTracker") + super().__init__(dotted, scolor, swidth, [self.trans, self.sep], name="bezcurveTracker") def update(self, points, degree=None): """Update the points and recompute.""" @@ -586,10 +594,12 @@ class bezcurveTracker(Tracker): self.bezcurve = [] - if (len(self.points) >= 2): + if len(self.points) >= 2: if self.degree: poles = self.points[1:] - segpoleslst = [poles[x:x+self.degree] for x in range(0, len(poles), (self.degree or 1))] + segpoleslst = [ + poles[x : x + self.degree] for x in range(0, len(poles), (self.degree or 1)) + ] else: segpoleslst = [self.points] startpoint = self.points[0] @@ -601,16 +611,16 @@ class bezcurveTracker(Tracker): c = c.toShape() startpoint = segpoles[-1] buf = c.writeInventor(2, 0.01) - # fp=open("spline.iv", "w") - # fp.write(buf) - # fp.close() + # fp=open("spline.iv", "w") + # fp.write(buf) + # fp.close() try: ivin = coin.SoInput() ivin.setBuffer(buf) ivob = coin.SoDB.readAll(ivin) except Exception: # workaround for pivy SoInput.setBuffer() bug - buf = buf.replace("\n","") + buf = buf.replace("\n", "") pts = re.findall(r"point \\[(.*?)\\]", buf)[0] pts = pts.split(",") pc = [] @@ -632,15 +642,17 @@ class bezcurveTracker(Tracker): bezcurveseg.removeChild(bezcurveseg.getChild(0)) self.sep.addChild(bezcurveseg) else: - FreeCAD.Console.PrintWarning("bezcurveTracker.recompute() failed to read-in Inventor string\n") + FreeCAD.Console.PrintWarning( + "bezcurveTracker.recompute() failed to read-in Inventor string\n" + ) self.bezcurve.append(bezcurveseg) class arcTracker(Tracker): """An arc tracker.""" + # Note: used by the Arc command but also for angular dimensions. - def __init__(self, dotted=False, scolor=None, swidth=None, - start=0, end=math.pi*2): + def __init__(self, dotted=False, scolor=None, swidth=None, start=0, end=math.pi * 2): self.circle = None self.startangle = math.degrees(start) self.endangle = math.degrees(end) @@ -650,12 +662,12 @@ class arcTracker(Tracker): self.autoinvert = True self.normal = self._get_wp().axis self.recompute() - super().__init__(dotted, scolor, swidth, - [self.trans, self.sep], name="arcTracker") + super().__init__(dotted, scolor, swidth, [self.trans, self.sep], name="arcTracker") def getDeviation(self): """Return a deviation vector that represents the base of the circle.""" import Part + c = Part.makeCircle(1, Vector(0, 0, 0), self.normal) return c.Vertexes[0].Point @@ -689,7 +701,7 @@ class arcTracker(Tracker): def getAngles(self): """Return the start and end angles in degrees.""" - return(self.startangle, self.endangle) + return (self.startangle, self.endangle) def setStartPoint(self, pt): """Set the start angle from a point.""" @@ -708,6 +720,7 @@ class arcTracker(Tracker): def setBy3Points(self, p1, p2, p3): """Set the arc by three points.""" import Part + try: arc = Part.ArcOfCircle(p1, p2, p3) except Exception: @@ -723,15 +736,14 @@ class arcTracker(Tracker): def recompute(self): """Recompute the tracker.""" import Part + if self.circle: self.sep.removeChild(self.circle) self.circle = None if (self.endangle < self.startangle) or not self.autoinvert: - c = Part.makeCircle(1, Vector(0, 0, 0), - self.normal, self.endangle, self.startangle) + c = Part.makeCircle(1, Vector(0, 0, 0), self.normal, self.endangle, self.startangle) else: - c = Part.makeCircle(1, Vector(0, 0, 0), - self.normal, self.startangle, self.endangle) + c = Part.makeCircle(1, Vector(0, 0, 0), self.normal, self.startangle, self.endangle) buf = c.writeInventor(2, 0.01) try: ivin = coin.SoInput() @@ -761,7 +773,9 @@ class arcTracker(Tracker): self.circle.removeChild(self.circle.getChild(0)) self.sep.addChild(self.circle) else: - FreeCAD.Console.PrintWarning("arcTracker.recompute() failed to read-in Inventor string\n") + FreeCAD.Console.PrintWarning( + "arcTracker.recompute() failed to read-in Inventor string\n" + ) class ghostTracker(Tracker): @@ -770,7 +784,9 @@ class ghostTracker(Tracker): You can pass it an object or a list of objects, or a shape. """ - def __init__(self, sel, dotted=False, scolor=None, swidth=None, mirror=False, parent_places=None): + def __init__( + self, sel, dotted=False, scolor=None, swidth=None, mirror=False, parent_places=None + ): self.trans = coin.SoTransform() self.trans.translation.setValue([0, 0, 0]) self.children = [self.trans] @@ -783,13 +799,16 @@ class ghostTracker(Tracker): else: parent_place = None import Part + if not isinstance(obj, Part.Vertex): self.rootsep.addChild(self.getNode(obj, parent_place)) else: self.coords = coin.SoCoordinate3() self.coords.point.setValue((obj.X, obj.Y, obj.Z)) self.marker = coin.SoMarkerSet() # this is the marker symbol - self.marker.markerIndex = FreeCADGui.getMarkerIndex("SQUARE_FILLED", params.get_param_view("MarkerSize")) + self.marker.markerIndex = FreeCADGui.getMarkerIndex( + "SQUARE_FILLED", params.get_param_view("MarkerSize") + ) node = coin.SoAnnotation() selnode = coin.SoSeparator() selnode.addChild(self.coords) @@ -802,8 +821,7 @@ class ghostTracker(Tracker): else: self.flipped = False self.children.append(self.rootsep) - super().__init__(dotted, scolor, swidth, - children=self.children, name="ghostTracker") + super().__init__(dotted, scolor, swidth, children=self.children, name="ghostTracker") self.setColor(scolor) def setColor(self, color=None): @@ -840,6 +858,7 @@ class ghostTracker(Tracker): def getNode(self, obj, parent_place=None): """Return a coin node representing the given object.""" import Part + if isinstance(obj, Part.Shape): return self.getNodeLight(obj) else: @@ -886,7 +905,11 @@ class ghostTracker(Tracker): def getMatrix(self): """Get matrix of the active view.""" - r = FreeCADGui.ActiveDocument.ActiveView.getViewer().getSoRenderManager().getViewportRegion() + r = ( + FreeCADGui.ActiveDocument.ActiveView.getViewer() + .getSoRenderManager() + .getViewportRegion() + ) v = coin.SoGetMatrixAction(r) m = self.trans.getMatrix(v) if m: @@ -937,8 +960,8 @@ class ghostTracker(Tracker): if len(index) % 4 == 0: for i in range(0, len(index), 4): tmp = index[i] - index[i] = index[i+1] - index[i+1] = tmp + index[i] = index[i + 1] + index[i + 1] = tmp node.coordIndex.setValues(index) @@ -946,11 +969,14 @@ class ghostTracker(Tracker): class editTracker(Tracker): """A node edit tracker.""" - def __init__(self, pos=Vector(0, 0, 0), name=None, idx=0, objcol=None, - marker=None, inactive=False): + def __init__( + self, pos=Vector(0, 0, 0), name=None, idx=0, objcol=None, marker=None, inactive=False + ): self.marker = coin.SoMarkerSet() # this is the marker symbol if marker is None: - self.marker.markerIndex = FreeCADGui.getMarkerIndex("SQUARE_FILLED", params.get_param_view("MarkerSize")) + self.marker.markerIndex = FreeCADGui.getMarkerIndex( + "SQUARE_FILLED", params.get_param_view("MarkerSize") + ) else: self.marker.markerIndex = marker self.coords = coin.SoCoordinate3() # this is the coordinate @@ -970,8 +996,7 @@ class editTracker(Tracker): self.selnode.addChild(self.marker) node.addChild(self.selnode) ontop = not inactive - super().__init__(children=[node], - ontop=ontop, name="editTracker") + super().__init__(children=[node], ontop=ontop, name="editTracker") if objcol is None: self.setColor() else: @@ -1024,7 +1049,7 @@ class PlaneTracker(Tracker): # getting screen distance p1 = Draft.get3DView().getPoint((100, 100)) p2 = Draft.get3DView().getPoint((110, 100)) - bl = (p2.sub(p1)).Length * (params.get_param("snapRange")/2.0) + bl = (p2.sub(p1)).Length * (params.get_param("snapRange") / 2.0) pick = coin.SoPickStyle() pick.style.setValue(coin.SoPickStyle.UNPICKABLE) self.trans = coin.SoTransform() @@ -1083,13 +1108,12 @@ class wireTracker(Tracker): self.line = coin.SoLineSet() self.closed = DraftGeomUtils.isReallyClosed(wire) if self.closed: - self.line.numVertices.setValue(len(wire.Vertexes)+1) + self.line.numVertices.setValue(len(wire.Vertexes) + 1) else: self.line.numVertices.setValue(len(wire.Vertexes)) self.coords = coin.SoCoordinate3() self.update(wire) - super().__init__(children=[self.coords, self.line], - name="wireTracker") + super().__init__(children=[self.coords, self.line], name="wireTracker") def update(self, wire, forceclosed=False): """Update the tracker.""" @@ -1127,11 +1151,11 @@ class gridTracker(Tracker): # small squares self.mat1 = coin.SoMaterial() - self.mat1.transparency.setValue(0.8*(1-gtrans)) + self.mat1.transparency.setValue(0.8 * (1 - gtrans)) self.mat1.diffuseColor.setValue(col) self.font = coin.SoFont() self.coords1 = coin.SoCoordinate3() - self.lines1 = coin.SoLineSet() # small squares + self.lines1 = coin.SoLineSet() # small squares # texts texts = coin.SoSeparator() @@ -1154,14 +1178,14 @@ class gridTracker(Tracker): # big squares self.mat2 = coin.SoMaterial() - self.mat2.transparency.setValue(0.2*(1-gtrans)) + self.mat2.transparency.setValue(0.2 * (1 - gtrans)) self.mat2.diffuseColor.setValue(col) self.coords2 = coin.SoCoordinate3() - self.lines2 = coin.SoLineSet() # big squares + self.lines2 = coin.SoLineSet() # big squares # human figure mat_human = coin.SoMaterial() - mat_human.transparency.setValue(0.3*(1-gtrans)) + mat_human.transparency.setValue(0.3 * (1 - gtrans)) mat_human.diffuseColor.setValue(col) self.coords_human = coin.SoCoordinate3() self.human = coin.SoLineSet() @@ -1169,11 +1193,11 @@ class gridTracker(Tracker): # axes self.mat3 = coin.SoMaterial() self.mat3.transparency.setValue(gtrans) - self.mat3.diffuseColor.setValues([col,red,green,blue]) + self.mat3.diffuseColor.setValues([col, red, green, blue]) self.coords3 = coin.SoCoordinate3() - self.lines3 = coin.SoIndexedLineSet() # axes - self.lines3.coordIndex.setValues(0,5,[0,1,-1,2,3]) - self.lines3.materialIndex.setValues(0,2,[0,0]) + self.lines3 = coin.SoIndexedLineSet() # axes + self.lines3.coordIndex.setValues(0, 5, [0, 1, -1, 2, 3]) + self.lines3.materialIndex.setValues(0, 2, [0, 0]) mbind3 = coin.SoMaterialBinding() mbind3.value = coin.SoMaterialBinding.PER_PART_INDEXED @@ -1223,8 +1247,8 @@ class gridTracker(Tracker): return numlines = self.numlines // self.mainlines // 2 * 2 * self.mainlines bound = (numlines // 2) * self.space - border = (numlines//2 + self.mainlines/2) * self.space - cursor = self.mainlines//4 * self.space + border = (numlines // 2 + self.mainlines / 2) * self.space + cursor = self.mainlines // 4 * self.space pts = [] mpts = [] apts = [] @@ -1239,73 +1263,83 @@ class gridTracker(Tracker): else: mpts.extend([[-bound, curr, z], [bound, curr, z]]) mpts.extend([[curr, -bound, z], [curr, bound, z]]) - cpts.extend([[-border,curr,z], [-border+cursor,curr,z]]) - cpts.extend([[border-cursor,curr,z], [border,curr,z]]) - cpts.extend([[curr,-border,z], [curr,-border+cursor,z]]) - cpts.extend([[curr,border-cursor,z], [curr,border,z]]) + cpts.extend([[-border, curr, z], [-border + cursor, curr, z]]) + cpts.extend([[border - cursor, curr, z], [border, curr, z]]) + cpts.extend([[curr, -border, z], [curr, -border + cursor, z]]) + cpts.extend([[curr, border - cursor, z], [curr, border, z]]) else: pts.extend([[-bound, curr, z], [bound, curr, z]]) pts.extend([[curr, -bound, z], [curr, bound, z]]) if pts != self.pts: idx = [] midx = [] - #aidx = [] + # aidx = [] cidx = [] for p in range(0, len(pts), 2): idx.append(2) for mp in range(0, len(mpts), 2): midx.append(2) - #for ap in range(0, len(apts), 2): + # for ap in range(0, len(apts), 2): # aidx.append(2) - for cp in range(0, len(cpts),2): + for cp in range(0, len(cpts), 2): cidx.append(2) if params.get_param("gridBorder"): # extra border - border = (numlines//2 + self.mainlines/2) * self.space - mpts.extend([[-border, -border, z], [border, -border, z], [border, border, z], [-border, border, z], [-border, -border, z]]) + border = (numlines // 2 + self.mainlines / 2) * self.space + mpts.extend( + [ + [-border, -border, z], + [border, -border, z], + [border, border, z], + [-border, border, z], + [-border, -border, z], + ] + ) midx.append(5) # cursors mpts.extend(cpts) midx.extend(cidx) # texts - self.font.size = self.space*(self.mainlines//4) or 1 + self.font.size = self.space * (self.mainlines // 4) or 1 self.font.name = params.get_param("textfont") - txt = FreeCAD.Units.Quantity(self.space*self.mainlines,FreeCAD.Units.Length).UserString + txt = FreeCAD.Units.Quantity( + self.space * self.mainlines, FreeCAD.Units.Length + ).UserString self.text1.string = txt self.text2.string = txt - self.textpos1.translation.setValue((-bound+self.space,-border+self.space,z)) - self.textpos2.translation.setValue((-bound-self.space,-bound+self.space,z)) + self.textpos1.translation.setValue((-bound + self.space, -border + self.space, z)) + self.textpos2.translation.setValue((-bound - self.space, -bound + self.space, z)) else: self.text1.string = " " self.text2.string = " " self.lines1.numVertices.deleteValues(0) self.lines2.numVertices.deleteValues(0) - #self.lines3.numVertices.deleteValues(0) + # self.lines3.numVertices.deleteValues(0) self.coords1.point.setValues(pts) self.lines1.numVertices.setValues(idx) self.coords2.point.setValues(mpts) self.lines2.numVertices.setValues(midx) self.coords3.point.setValues(apts) - #self.lines3.numVertices.setValues(aidx) + # self.lines3.numVertices.setValues(aidx) self.pts = pts # update the grid colors col, red, green, blue, gtrans = self.getGridColors() self.mat1.diffuseColor.setValue(col) self.mat2.diffuseColor.setValue(col) - self.mat3.diffuseColor.setValues([col,red,green,blue]) + self.mat3.diffuseColor.setValues([col, red, green, blue]) def getGridColors(self): """Returns grid colors stored in the preferences""" - gtrans = params.get_param("gridTransparency")/100.0 + gtrans = params.get_param("gridTransparency") / 100.0 col = utils.get_rgba_tuple(params.get_param("gridColor"))[:3] if params.get_param("coloredGridAxes"): vp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View") - red = vp.GetUnsigned("AxisXColor",0xCC333300) - green = vp.GetUnsigned("AxisYColor",0x33CC3300) - blue = vp.GetUnsigned("AxisZColor",0x3333CC00) + red = vp.GetUnsigned("AxisXColor", 0xCC333300) + green = vp.GetUnsigned("AxisYColor", 0x33CC3300) + blue = vp.GetUnsigned("AxisZColor", 0x3333CC00) red = utils.get_rgba_tuple(red)[:3] green = utils.get_rgba_tuple(green)[:3] blue = utils.get_rgba_tuple(blue)[:3] @@ -1321,38 +1355,88 @@ class gridTracker(Tracker): Based on "HumanFigure.brep" from the BIM Workbench. """ pts = [ - Vector (131.2, 0.0, 175.8), Vector (135.7, 0.0, 211.7), Vector (142.1, 0.0, 229.3), - Vector (154.0, 0.0, 276.3), Vector (163.6, 0.0, 333.4), Vector (173.8, 0.0, 411.5), - Vector (186.0, 0.0, 491.7), Vector (200.2, 0.0, 591.8), Vector (215.4, 0.0, 714.8), - Vector (224.1, 0.0, 650.0), Vector (234.1, 0.0, 575.8), Vector (251.9, 0.0, 425.5), - Vector (240.8, 0.0, 273.3), Vector (235.9, 0.0, 243.2), Vector (197.3, 0.0, 81.7), - Vector (188.8, 0.0, 37.6), Vector (195.1, 0.0, 0.0), Vector (278.8, 0.0, 0.0), - Vector (294.5, 0.0, 121.0), Vector (308.4, 0.0, 184.3), Vector (318.1, 0.0, 225.4), - Vector (322.0, 0.0, 235.2), Vector (340.1, 0.0, 283.5), Vector (349.0, 0.0, 341.4), - Vector (354.2, 0.0, 523.7), Vector (383.1, 0.0, 719.7), Vector (399.6, 0.0, 820.3), - Vector (381.2, 0.0, 1029.6), Vector (385.6, 0.0, 1164.0), Vector (390.1, 0.0, 1184.6), - Vector (398.3, 0.0, 1201.9), Vector (430.2, 0.0, 1273.1), Vector (438.2, 0.0, 1321.2), - Vector (441.3, 0.0, 1368.2), Vector (428.1, 0.0, 1405.3), Vector (395.0, 0.0, 1424.3), - Vector (365.5, 0.0, 1446.6), Vector (349.8, 0.0, 1460.2), Vector (345.6, 0.0, 1476.7), - Vector (337.9, 0.0, 1570.3), Vector (332.8, 0.0, 1624.7), Vector (322.2, 0.0, 1666.9), - Vector (216.2, 0.0, 1680.2), Vector (163.5, 0.0, 1559.1), Vector (179.8, 0.0, 1475.5), - Vector (195.6, 0.0, 1459.9), Vector (193.1, 0.0, 1447.8), Vector (171.0, 0.0, 1429.4), - Vector (132.3, 0.0, 1399.8), Vector (96.8, 0.0, 1374.7), Vector (74.0, 0.0, 1275.1), - Vector (46.2, 0.0, 1095.6), Vector (38.0, 0.0, 1041.5), Vector (25.2, 0.0, 958.5), - Vector (15.9, 0.0, 889.7), Vector (2.5, 0.0, 842.1), Vector (-5.8, 0.0, 785.4), - Vector (15.8, 0.0, 755.1), Vector (38.0, 0.0, 750.4), Vector (45.0, 0.0, 755.4), - Vector (53.1, 0.0, 736.1), Vector (76.4, 0.0, 572.2), Vector (83.6, 0.0, 512.0), - Vector (81.3, 0.0, 499.0), Vector (74.0, 0.0, 460.9), Vector (61.9, 0.0, 363.4), - Vector (53.4, 0.0, 269.3), Vector (44.5, 0.0, 179.7), Vector (25.6, 0.0, 121.6), - Vector (0.6, 0.0, 76.5), Vector (-23.7, 0.0, 54.5), Vector (-43.8, 0.0, 33.5), - Vector (-25.6, 0.0, 0.0), Vector (117.9, 0.0, 0.0), Vector (131.2, 0.0, 175.8) + Vector(131.2, 0.0, 175.8), + Vector(135.7, 0.0, 211.7), + Vector(142.1, 0.0, 229.3), + Vector(154.0, 0.0, 276.3), + Vector(163.6, 0.0, 333.4), + Vector(173.8, 0.0, 411.5), + Vector(186.0, 0.0, 491.7), + Vector(200.2, 0.0, 591.8), + Vector(215.4, 0.0, 714.8), + Vector(224.1, 0.0, 650.0), + Vector(234.1, 0.0, 575.8), + Vector(251.9, 0.0, 425.5), + Vector(240.8, 0.0, 273.3), + Vector(235.9, 0.0, 243.2), + Vector(197.3, 0.0, 81.7), + Vector(188.8, 0.0, 37.6), + Vector(195.1, 0.0, 0.0), + Vector(278.8, 0.0, 0.0), + Vector(294.5, 0.0, 121.0), + Vector(308.4, 0.0, 184.3), + Vector(318.1, 0.0, 225.4), + Vector(322.0, 0.0, 235.2), + Vector(340.1, 0.0, 283.5), + Vector(349.0, 0.0, 341.4), + Vector(354.2, 0.0, 523.7), + Vector(383.1, 0.0, 719.7), + Vector(399.6, 0.0, 820.3), + Vector(381.2, 0.0, 1029.6), + Vector(385.6, 0.0, 1164.0), + Vector(390.1, 0.0, 1184.6), + Vector(398.3, 0.0, 1201.9), + Vector(430.2, 0.0, 1273.1), + Vector(438.2, 0.0, 1321.2), + Vector(441.3, 0.0, 1368.2), + Vector(428.1, 0.0, 1405.3), + Vector(395.0, 0.0, 1424.3), + Vector(365.5, 0.0, 1446.6), + Vector(349.8, 0.0, 1460.2), + Vector(345.6, 0.0, 1476.7), + Vector(337.9, 0.0, 1570.3), + Vector(332.8, 0.0, 1624.7), + Vector(322.2, 0.0, 1666.9), + Vector(216.2, 0.0, 1680.2), + Vector(163.5, 0.0, 1559.1), + Vector(179.8, 0.0, 1475.5), + Vector(195.6, 0.0, 1459.9), + Vector(193.1, 0.0, 1447.8), + Vector(171.0, 0.0, 1429.4), + Vector(132.3, 0.0, 1399.8), + Vector(96.8, 0.0, 1374.7), + Vector(74.0, 0.0, 1275.1), + Vector(46.2, 0.0, 1095.6), + Vector(38.0, 0.0, 1041.5), + Vector(25.2, 0.0, 958.5), + Vector(15.9, 0.0, 889.7), + Vector(2.5, 0.0, 842.1), + Vector(-5.8, 0.0, 785.4), + Vector(15.8, 0.0, 755.1), + Vector(38.0, 0.0, 750.4), + Vector(45.0, 0.0, 755.4), + Vector(53.1, 0.0, 736.1), + Vector(76.4, 0.0, 572.2), + Vector(83.6, 0.0, 512.0), + Vector(81.3, 0.0, 499.0), + Vector(74.0, 0.0, 460.9), + Vector(61.9, 0.0, 363.4), + Vector(53.4, 0.0, 269.3), + Vector(44.5, 0.0, 179.7), + Vector(25.6, 0.0, 121.6), + Vector(0.6, 0.0, 76.5), + Vector(-23.7, 0.0, 54.5), + Vector(-43.8, 0.0, 33.5), + Vector(-25.6, 0.0, 0.0), + Vector(117.9, 0.0, 0.0), + Vector(131.2, 0.0, 175.8), ] if loc: pts = [p.add(loc) for p in pts] return pts def displayHumanFigure(self, wp): - """ Display the human figure at the grid corner. + """Display the human figure at the grid corner. The silhouette is displayed only if: - preference BaseApp/Preferences/Mod/Draft/gridBorder is True; - preference BaseApp/Preferences/Mod/Draft/gridShowHuman is True; @@ -1362,10 +1446,12 @@ class gridTracker(Tracker): bound = (numlines // 2) * self.space pts = [] pidx = [] - if params.get_param("gridBorder") \ - and params.get_param("gridShowHuman") \ - and wp.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001: - loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) + if ( + params.get_param("gridBorder") + and params.get_param("gridShowHuman") + and wp.axis.getAngle(FreeCAD.Vector(0, 0, 1)) < 0.001 + ): + loc = FreeCAD.Vector(-bound + self.space / 2, -bound + self.space / 2, 0) hpts = self.get_human_figure(loc) pts.extend([tuple(p) for p in hpts]) pidx.append(len(hpts)) @@ -1375,21 +1461,21 @@ class gridTracker(Tracker): def setAxesColor(self, wp): """set axes color""" - cols = [0,0] + cols = [0, 0] if params.get_param("coloredGridAxes"): - if round(wp.u.getAngle(FreeCAD.Vector(1,0,0)),2) in (0,3.14): + if round(wp.u.getAngle(FreeCAD.Vector(1, 0, 0)), 2) in (0, 3.14): cols[0] = 1 - elif round(wp.u.getAngle(FreeCAD.Vector(0,1,0)),2) in (0,3.14): + elif round(wp.u.getAngle(FreeCAD.Vector(0, 1, 0)), 2) in (0, 3.14): cols[0] = 2 - elif round(wp.u.getAngle(FreeCAD.Vector(0,0,1)),2) in (0,3.14): + elif round(wp.u.getAngle(FreeCAD.Vector(0, 0, 1)), 2) in (0, 3.14): cols[0] = 3 - if round(wp.v.getAngle(FreeCAD.Vector(1,0,0)),2) in (0,3.14): + if round(wp.v.getAngle(FreeCAD.Vector(1, 0, 0)), 2) in (0, 3.14): cols[1] = 1 - elif round(wp.v.getAngle(FreeCAD.Vector(0,1,0)),2) in (0,3.14): + elif round(wp.v.getAngle(FreeCAD.Vector(0, 1, 0)), 2) in (0, 3.14): cols[1] = 2 - elif round(wp.v.getAngle(FreeCAD.Vector(0,0,1)),2) in (0,3.14): + elif round(wp.v.getAngle(FreeCAD.Vector(0, 0, 1)), 2) in (0, 3.14): cols[1] = 3 - self.lines3.materialIndex.setValues(0,2,cols) + self.lines3.materialIndex.setValues(0, 2, cols) def setSize(self, size): """Set size of the lines and update.""" @@ -1466,15 +1552,14 @@ class boxTracker(Tracker): self.baseline = line self.update() if shaded: - super().__init__(children=[self.trans, m, self.cube], - name="boxTracker") + super().__init__(children=[self.trans, m, self.cube], name="boxTracker") else: - super().__init__(children=[self.trans, w, self.cube], - name="boxTracker") + super().__init__(children=[self.trans, w, self.cube], name="boxTracker") def update(self, line=None, normal=None): """Update the tracker.""" import DraftGeomUtils + if not normal: normal = self._get_wp().axis if line: @@ -1491,14 +1576,13 @@ class boxTracker(Tracker): return self.cube.width.setValue(lvec.Length) bp = bp.add(lvec.multiply(0.5)) - bp = bp.add(DraftVecUtils.scaleTo(normal, self.cube.depth.getValue()/2.0)) + bp = bp.add(DraftVecUtils.scaleTo(normal, self.cube.depth.getValue() / 2.0)) self.pos(bp) tol = 1e-6 if lvec.Length > tol and normal.Length > tol: lvec.normalize() normal.normalize() - if not lvec.isEqual(normal, tol) \ - and not lvec.isEqual(normal.negative(), tol): + if not lvec.isEqual(normal, tol) and not lvec.isEqual(normal.negative(), tol): rot = FreeCAD.Rotation(lvec, FreeCAD.Vector(), normal, "XZY") self.trans.rotation.setValue(rot.Q) @@ -1545,8 +1629,7 @@ class radiusTracker(Tracker): self.sphere = coin.SoSphere() self.sphere.radius.setValue(radius) self.baseline = None - super().__init__(children=[self.trans, m, self.sphere], - name="radiusTracker") + super().__init__(children=[self.trans, m, self.sphere], name="radiusTracker") def update(self, arg1, arg2=None): """Update the tracker.""" @@ -1566,6 +1649,7 @@ class archDimTracker(Tracker): def __init__(self, p1=FreeCAD.Vector(0, 0, 0), p2=FreeCAD.Vector(1, 0, 0), mode=1): import SketcherGui + self.transform = coin.SoMatrixTransform() self.dimnode = coin.SoType.fromName("SoDatumLabel").createInstance() p1node = coin.SbVec3f([p1.x, p1.y, p1.z]) @@ -1610,27 +1694,28 @@ class archDimTracker(Tracker): # set the offset sign to prevent the dim line from intersecting the curve near the cursor sign_dx = math.copysign(1, (p2.sub(p1)).x) sign_dy = math.copysign(1, (p2.sub(p1)).y) - sign = sign_dx*sign_dy + sign = sign_dx * sign_dy if self.mode == 2: self.Distance = abs((p2.sub(p1)).x) - self.param1.setValue(sign*self.offset) + self.param1.setValue(sign * self.offset) elif self.mode == 3: self.Distance = abs((p2.sub(p1)).y) - self.param1.setValue(-1*sign*self.offset) + self.param1.setValue(-1 * sign * self.offset) else: self.Distance = (p2.sub(p1)).Length text = FreeCAD.Units.Quantity(self.Distance, FreeCAD.Units.Length).UserString self.matrix.setValue(*plane.get_placement().Matrix.transposed().A) - self.string.setValue(text.encode('utf8')) + self.string.setValue(text.encode("utf8")) # change the text position to external depending on the distance and scale values volume = self.camera.getViewVolume() - scale = self.view.getSize()[1]/volume.getHeight() - if scale*self.Distance > self.size_pixel*len(text): + scale = self.view.getSize()[1] / volume.getHeight() + if scale * self.Distance > self.size_pixel * len(text): self.param2.setValue(0) else: - self.param2.setValue(1/2*self.Distance + 3/5*self.size_pixel*len(text)/scale) - + self.param2.setValue( + 1 / 2 * self.Distance + 3 / 5 * self.size_pixel * len(text) / scale + ) def setMode(self, mode=1): """Set the mode. @@ -1666,4 +1751,5 @@ class archDimTracker(Tracker): else: return Vector(self.pnts.getValues()[-1].getValue()) + ## @} diff --git a/src/Mod/Draft/draftguitools/gui_trimex.py b/src/Mod/Draft/draftguitools/gui_trimex.py index bacea52ad4..2b67eb63e0 100644 --- a/src/Mod/Draft/draftguitools/gui_trimex.py +++ b/src/Mod/Draft/draftguitools/gui_trimex.py @@ -71,11 +71,14 @@ class Trimex(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Trimex', - 'Accel': "T, R", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Trimex", "Trimex"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Trimex", - "Trims or extends the selected object, or extrudes single faces")} + return { + "Pixmap": "Draft_Trimex", + "Accel": "T, R", + "MenuText": QT_TRANSLATE_NOOP("Draft_Trimex", "Trimex"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Trimex", "Trims or extends the selected object, or extrudes single faces" + ), + } def Activated(self): """Execute when the command is called.""" @@ -90,9 +93,7 @@ class Trimex(gui_base_original.Modifier): if not Gui.Selection.getSelection(): self.ui.selectUi(on_close_call=self.finish) _msg(translate("draft", "Select objects to trim or extend")) - self.call = \ - self.view.addEventCallback("SoEvent", - gui_tool_utils.selectObject) + self.call = self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) else: self.proceed() @@ -106,7 +107,7 @@ class Trimex(gui_base_original.Modifier): self.finish() return self.obj = sel[0] - self.ui.trimUi(title=translate("draft",self.featureName)) + self.ui.trimUi(title=translate("draft", self.featureName)) self.linetrack = trackers.lineTracker() import DraftGeomUtils @@ -148,7 +149,7 @@ class Trimex(gui_base_original.Modifier): else: self.edges = self.obj.Shape.Edges for e in self.edges: - if isinstance(e.Curve,(Part.BSplineCurve, Part.BezierCurve)): + if isinstance(e.Curve, (Part.BSplineCurve, Part.BezierCurve)): self.obj = None self.finish() _err(translate("draft", "Trimex does not support this object type")) @@ -162,11 +163,9 @@ class Trimex(gui_base_original.Modifier): sw = self.width for e in self.edges: if DraftGeomUtils.geomType(e) == "Line": - self.ghost.append(trackers.lineTracker(scolor=sc, - swidth=sw)) + self.ghost.append(trackers.lineTracker(scolor=sc, swidth=sw)) else: - self.ghost.append(trackers.arcTracker(scolor=sc, - swidth=sw)) + self.ghost.append(trackers.arcTracker(scolor=sc, swidth=sw)) if not self.ghost: self.obj = None self.finish() @@ -210,25 +209,21 @@ class Trimex(gui_base_original.Modifier): if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_snap_key()): self.snapped = None else: - self.snapped = self.view.getObjectInfo((arg["Position"][0], - arg["Position"][1])) + self.snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if self.extrudeMode: dist, ang = (self.extrude(self.shift), None) else: # If the geomType of the edge is "Line" ang will be None, # else dist will be None. - dist, ang = self.redraw(self.point, self.snapped, - self.shift, self.alt) + dist, ang = self.redraw(self.point, self.snapped, self.shift, self.alt) if dist: self.ui.labelRadius.setText(translate("draft", "Distance")) - self.ui.radiusValue.setToolTip(translate("draft", - "Offset distance")) + self.ui.radiusValue.setToolTip(translate("draft", "Offset distance")) self.ui.setRadiusValue(dist, unit="Length") elif ang: self.ui.labelRadius.setText(translate("draft", "Angle")) - self.ui.radiusValue.setToolTip(translate("draft", - "Offset angle")) + self.ui.radiusValue.setToolTip(translate("draft", "Offset angle")) self.ui.setRadiusValue(ang, unit="Angle") else: # both dist and ang are None, this indicates an impossible @@ -246,8 +241,7 @@ class Trimex(gui_base_original.Modifier): if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_snap_key()): self.snapped = None else: - self.snapped = self.view.getObjectInfo((cursor[0], - cursor[1])) + self.snapped = self.view.getObjectInfo((cursor[0], cursor[1])) self.trimObject() self.finish() @@ -263,7 +257,7 @@ class Trimex(gui_base_original.Modifier): else: delta = dvec if self.force and delta.Length: - ratio = self.force/delta.Length + ratio = self.force / delta.Length delta.multiply(ratio) if real: return delta @@ -273,7 +267,7 @@ class Trimex(gui_base_original.Modifier): self.ghost[1].p2(self.newpoint + dvec) # Update the vertex lineTrackers: for i in range(2, len(self.ghost)): - base = self.obj.Shape.Vertexes[i-2].Point + base = self.obj.Shape.Vertexes[i - 2].Point self.ghost[i].p1(base) self.ghost[i].p2(base + delta) return delta.Length @@ -299,7 +293,7 @@ class Trimex(gui_base_original.Modifier): npoint = self.activePoint else: npoint = DraftGeomUtils.findClosest(point, vlist) - if npoint > len(self.edges)/2: + if npoint > len(self.edges) / 2: reverse = True if alt: reverse = not reverse @@ -308,7 +302,7 @@ class Trimex(gui_base_original.Modifier): # sorting out directions if reverse and (npoint > 0): npoint = npoint - 1 - if (npoint > len(self.edges) - 1): + if npoint > len(self.edges) - 1: edge = self.edges[-1] ghost = self.ghost[-1] else: @@ -382,8 +376,7 @@ class Trimex(gui_base_original.Modifier): if real: if self.force: angle = math.radians(self.force) - newray = DraftVecUtils.rotate(App.Vector(rad, 0, 0), - -angle) + newray = DraftVecUtils.rotate(App.Vector(rad, 0, 0), -angle) self.newpoint = App.Vector.add(center, newray) chord = self.newpoint.sub(v2) perp = chord.cross(App.Vector(0, 0, 1)) @@ -429,15 +422,14 @@ class Trimex(gui_base_original.Modifier): if self.extrudeMode: delta = self.extrude(self.shift, real=True) - #print("delta", delta) + # print("delta", delta) self.doc.openTransaction("Extrude") Gui.addModule("Draft") obj = Draft.extrude(self.obj, delta, solid=True) self.doc.commitTransaction() self.obj = obj else: - edges = self.redraw(self.point, self.snapped, - self.shift, self.alt, real=True) + edges = self.redraw(self.point, self.snapped, self.shift, self.alt, real=True) newshape = Part.Wire(edges) self.doc.openTransaction("Trim/extend") if utils.getType(self.obj) in ["Wire", "BSpline"]: @@ -459,21 +451,21 @@ class Trimex(gui_base_original.Modifier): if self.placement: np = invpl.multVec(np) p.append(np) - if ((p[0].x == self.obj.X1) - and (p[0].y == self.obj.Y1) - and (p[0].z == self.obj.Z1)): + if (p[0].x == self.obj.X1) and (p[0].y == self.obj.Y1) and (p[0].z == self.obj.Z1): self.obj.X2 = p[-1].x self.obj.Y2 = p[-1].y self.obj.Z2 = p[-1].z - elif ((p[-1].x == self.obj.X1) - and (p[-1].y == self.obj.Y1) - and (p[-1].z == self.obj.Z1)): + elif ( + (p[-1].x == self.obj.X1) + and (p[-1].y == self.obj.Y1) + and (p[-1].z == self.obj.Z1) + ): self.obj.X2 = p[0].x self.obj.Y2 = p[0].y self.obj.Z2 = p[0].z - elif ((p[0].x == self.obj.X2) - and (p[0].y == self.obj.Y2) - and (p[0].z == self.obj.Z2)): + elif ( + (p[0].x == self.obj.X2) and (p[0].y == self.obj.Y2) and (p[0].z == self.obj.Z2) + ): self.obj.X1 = p[-1].x self.obj.Y1 = p[-1].y self.obj.Z1 = p[-1].z @@ -504,14 +496,15 @@ class Trimex(gui_base_original.Modifier): wires = [] for obj in objectslist: if not utils.getType(obj) in ["Wire", "Circle"]: - _err(translate("draft", - "Unable to trim these objects, " - "only Draft wires and arcs are supported")) + _err( + translate( + "draft", + "Unable to trim these objects, " "only Draft wires and arcs are supported", + ) + ) return if len(obj.Shape.Wires) > 1: - _err(translate("draft", - "Unable to trim these objects, " - "too many wires")) + _err(translate("draft", "Unable to trim these objects, " "too many wires")) return if len(obj.Shape.Wires) == 1: wires.append(obj.Shape.Wires[0]) @@ -555,17 +548,17 @@ class Trimex(gui_base_original.Modifier): la = last2 if utils.getType(obj) == "Wire": if la: - pts = obj.Points[:ed + 1] + ints + pts = obj.Points[: ed + 1] + ints else: - pts = ints + obj.Points[ed + 1:] + pts = ints + obj.Points[ed + 1 :] obj.Points = pts else: vec = ints[0].sub(obj.Placement.Base) vec = obj.Placement.inverse().Rotation.multVec(vec) _x = App.Vector(1, 0, 0) - _ang = -DraftVecUtils.angle(vec, - obj.Placement.Rotation.multVec(_x), - obj.Shape.Edges[0].Curve.Axis) + _ang = -DraftVecUtils.angle( + vec, obj.Placement.Rotation.multVec(_x), obj.Shape.Edges[0].Curve.Axis + ) ang = math.degrees(_ang) if la: obj.LastAngle = ang @@ -602,6 +595,6 @@ class Trimex(gui_base_original.Modifier): self.finish() -Gui.addCommand('Draft_Trimex', Trimex()) +Gui.addCommand("Draft_Trimex", Trimex()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_upgrade.py b/src/Mod/Draft/draftguitools/gui_upgrade.py index e57d9308d2..6cff995c47 100644 --- a/src/Mod/Draft/draftguitools/gui_upgrade.py +++ b/src/Mod/Draft/draftguitools/gui_upgrade.py @@ -53,10 +53,15 @@ class Upgrade(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_Upgrade', - 'Accel': "U, P", - 'MenuText': QT_TRANSLATE_NOOP("Draft_Upgrade", "Upgrade"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_Upgrade", "Upgrades the selected objects into more complex shapes.\nThe result of the operation depends on the types of objects, which may be able to be upgraded several times in a row.\nFor example, it can join the selected objects into one, convert simple edges into parametric polylines,\nconvert closed edges into filled faces and parametric polygons, and merge faces into a single face.")} + return { + "Pixmap": "Draft_Upgrade", + "Accel": "U, P", + "MenuText": QT_TRANSLATE_NOOP("Draft_Upgrade", "Upgrade"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_Upgrade", + "Upgrades the selected objects into more complex shapes.\nThe result of the operation depends on the types of objects, which may be able to be upgraded several times in a row.\nFor example, it can join the selected objects into one, convert simple edges into parametric polylines,\nconvert closed edges into filled faces and parametric polygons, and merge faces into a single face.", + ), + } def Activated(self): """Execute when the command is called.""" @@ -76,18 +81,16 @@ class Upgrade(gui_base_original.Modifier): self.end_callbacks(self.call) if Gui.Selection.getSelection(): Gui.addModule("Draft") - _cmd = 'Draft.upgrade' - _cmd += '(' - _cmd += 'FreeCADGui.Selection.getSelection(), ' - _cmd += 'delete=True' - _cmd += ')' - _cmd_list = ['_objs_ = ' + _cmd, - 'FreeCAD.ActiveDocument.recompute()'] - self.commit(translate("draft", "Upgrade"), - _cmd_list) + _cmd = "Draft.upgrade" + _cmd += "(" + _cmd += "FreeCADGui.Selection.getSelection(), " + _cmd += "delete=True" + _cmd += ")" + _cmd_list = ["_objs_ = " + _cmd, "FreeCAD.ActiveDocument.recompute()"] + self.commit(translate("draft", "Upgrade"), _cmd_list) self.finish() -Gui.addCommand('Draft_Upgrade', Upgrade()) +Gui.addCommand("Draft_Upgrade", Upgrade()) ## @} diff --git a/src/Mod/Draft/draftguitools/gui_wire2spline.py b/src/Mod/Draft/draftguitools/gui_wire2spline.py index e6c1710711..340e58c3e3 100644 --- a/src/Mod/Draft/draftguitools/gui_wire2spline.py +++ b/src/Mod/Draft/draftguitools/gui_wire2spline.py @@ -60,9 +60,14 @@ class WireToBSpline(gui_base_original.Modifier): def GetResources(self): """Set icon, menu and tooltip.""" - return {'Pixmap': 'Draft_WireToBSpline', - 'MenuText': QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Convert Wire/B-Spline"), - 'ToolTip': QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Converts the selected polyline to a B-spline, or the selected B-spline to a polyline")} + return { + "Pixmap": "Draft_WireToBSpline", + "MenuText": QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Convert Wire/B-Spline"), + "ToolTip": QT_TRANSLATE_NOOP( + "Draft_WireToBSpline", + "Converts the selected polyline to a B-spline, or the selected B-spline to a polyline", + ), + } def Activated(self): """Execute when the command is called.""" @@ -76,7 +81,7 @@ class WireToBSpline(gui_base_original.Modifier): # in order to properly open a transaction and commit it. selection = Gui.Selection.getSelection() if selection: - if utils.getType(selection[0]) in ['Wire', 'BSpline']: + if utils.getType(selection[0]) in ["Wire", "BSpline"]: super(WireToBSpline, self).Activated(name="Convert polyline/B-spline") if self.doc: self.obj = Gui.Selection.getSelection() @@ -88,18 +93,20 @@ class WireToBSpline(gui_base_original.Modifier): self.Points = self.obj.Points self.closed = self.obj.Closed n = None - if utils.getType(self.obj) == 'Wire': - n = Draft.make_bspline(self.Points, - closed=self.closed, - placement=self.pl) - elif utils.getType(self.obj) == 'BSpline': + if utils.getType(self.obj) == "Wire": + n = Draft.make_bspline( + self.Points, closed=self.closed, placement=self.pl + ) + elif utils.getType(self.obj) == "BSpline": self.bs2wire = True - n = Draft.make_wire(self.Points, - closed=self.closed, - placement=self.pl, - face=None, - support=None, - bs2wire=self.bs2wire) + n = Draft.make_wire( + self.Points, + closed=self.closed, + placement=self.pl, + face=None, + support=None, + bs2wire=self.bs2wire, + ) if n: Draft.formatObject(n, self.obj) self.doc.recompute() @@ -107,6 +114,6 @@ class WireToBSpline(gui_base_original.Modifier): self.finish() -Gui.addCommand('Draft_WireToBSpline', WireToBSpline()) +Gui.addCommand("Draft_WireToBSpline", WireToBSpline()) ## @} diff --git a/src/Mod/Draft/draftmake/make_arc_3points.py b/src/Mod/Draft/draftmake/make_arc_3points.py index 30947900fe..311ed4a186 100644 --- a/src/Mod/Draft/draftmake/make_arc_3points.py +++ b/src/Mod/Draft/draftmake/make_arc_3points.py @@ -84,37 +84,35 @@ def make_arc_3points(points, placement=None, face=False, support=None, primitive try: utils.type_check([(points, (list, tuple))], name=_name) except TypeError: - _err(translate("draft","Points:") + " {}".format(points)) - _err(translate("draft","Wrong input: must be a list or tuple of 3 points exactly.")) + _err(translate("draft", "Points:") + " {}".format(points)) + _err(translate("draft", "Wrong input: must be a list or tuple of 3 points exactly.")) return None if len(points) != 3: - _err(translate("draft","Points:") + " {}".format(points)) - _err(translate("draft","Wrong input: must be list or tuple of 3 points exactly.")) + _err(translate("draft", "Points:") + " {}".format(points)) + _err(translate("draft", "Wrong input: must be list or tuple of 3 points exactly.")) return None p1, p2, p3 = points try: - utils.type_check([(p1, App.Vector), - (p2, App.Vector), - (p3, App.Vector)], name=_name) + utils.type_check([(p1, App.Vector), (p2, App.Vector), (p3, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: incorrect type of points.")) + _err(translate("draft", "Wrong input: incorrect type of points.")) return None if placement is not None: try: utils.type_check([(placement, App.Placement)], name=_name) except TypeError: - _err(translate("draft","Placement:") + " {}".format(placement)) - _err(translate("draft","Wrong input: incorrect type of placement.")) + _err(translate("draft", "Placement:") + " {}".format(placement)) + _err(translate("draft", "Wrong input: incorrect type of placement.")) return None try: edge = Part.Arc(p1, p2, p3).toShape() except Part.OCCError as error: - _err(translate("draft","Cannot generate shape:") + " " + "{}".format(error)) + _err(translate("draft", "Cannot generate shape:") + " " + "{}".format(error)) return None if primitive: @@ -124,4 +122,5 @@ def make_arc_3points(points, placement=None, face=False, support=None, primitive return make_circle.make_circle(edge, placement=placement, face=face, support=support) + ## @} diff --git a/src/Mod/Draft/draftmake/make_array.py b/src/Mod/Draft/draftmake/make_array.py index 5183616923..41c7cd4e15 100644 --- a/src/Mod/Draft/draftmake/make_array.py +++ b/src/Mod/Draft/draftmake/make_array.py @@ -43,10 +43,7 @@ if App.GuiUp: from draftviewproviders.view_draftlink import ViewProviderDraftLink -def make_array(base_object, - arg1, arg2, arg3, - arg4=None, arg5=None, arg6=None, - use_link=True): +def make_array(base_object, arg1, arg2, arg3, arg4=None, arg5=None, arg6=None, use_link=True): """Create a Draft Array of the given object. Rectangular array @@ -82,14 +79,13 @@ def make_array(base_object, """ found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None if use_link: # The Array class must be called in this special way # to make it a LinkArray - new_obj = doc.addObject("Part::FeaturePython", "Array", - Array(None), None, True) + new_obj = doc.addObject("Part::FeaturePython", "Array", Array(None), None, True) else: new_obj = doc.addObject("Part::FeaturePython", "Array") Array(new_obj) @@ -129,7 +125,9 @@ def make_array(base_object, ViewProviderDraftLink(new_obj.ViewObject) else: if new_obj.ArrayType == "circular": - new_obj.Proxy.execute(new_obj) # Updates Count which is required for correct DiffuseColor. + new_obj.Proxy.execute( + new_obj + ) # Updates Count which is required for correct DiffuseColor. ViewProviderDraftArray(new_obj.ViewObject) gui_utils.format_object(new_obj, new_obj.Base) new_obj.ViewObject.Proxy.resetColors(new_obj.ViewObject) @@ -139,17 +137,17 @@ def make_array(base_object, return new_obj -def makeArray(baseobject, - arg1, arg2, arg3, - arg4=None, arg5=None, arg6=None, - name="Array", use_link=False): +def makeArray( + baseobject, arg1, arg2, arg3, arg4=None, arg5=None, arg6=None, name="Array", use_link=False +): """Create an Array. DEPRECATED. Use 'make_array'.""" - _wrn("Do not use this function directly; instead, use " - "'make_ortho_array', 'make_polar_array', " - "or 'make_circular_array'.") + _wrn( + "Do not use this function directly; instead, use " + "'make_ortho_array', 'make_polar_array', " + "or 'make_circular_array'." + ) + + return make_array(baseobject, arg1, arg2, arg3, arg4, arg5, arg6, use_link) - return make_array(baseobject, - arg1, arg2, arg3, - arg4, arg5, arg6, use_link) ## @} diff --git a/src/Mod/Draft/draftmake/make_bezcurve.py b/src/Mod/Draft/draftmake/make_bezcurve.py index 9337104932..c4b5ee04f6 100644 --- a/src/Mod/Draft/draftmake/make_bezcurve.py +++ b/src/Mod/Draft/draftmake/make_bezcurve.py @@ -38,9 +38,7 @@ if App.GuiUp: from draftviewproviders.view_bezcurve import ViewProviderBezCurve -def make_bezcurve(pointslist, - closed=False, placement=None, face=None, support=None, - degree=None): +def make_bezcurve(pointslist, closed=False, placement=None, face=None, support=None, degree=None): """make_bezcurve(pointslist, [closed], [placement]) Creates a Bezier Curve object from the given list of vectors. @@ -72,15 +70,17 @@ def make_bezcurve(pointslist, if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - if not isinstance(pointslist,list): + if not isinstance(pointslist, list): nlist = [] for v in pointslist.Vertexes: nlist.append(v.Point) pointslist = nlist if placement: - utils.type_check([(placement,App.Placement)], "make_bezcurve") - if len(pointslist) == 2: fname = "Line" - else: fname = "BezCurve" + utils.type_check([(placement, App.Placement)], "make_bezcurve") + if len(pointslist) == 2: + fname = "Line" + else: + fname = "BezCurve" obj = App.ActiveDocument.addObject("Part::FeaturePython", fname) obj.addExtension("Part::AttachExtensionPython") BezCurve(obj) @@ -89,18 +89,19 @@ def make_bezcurve(pointslist, obj.Degree = degree else: import Part - obj.Degree = min((len(pointslist)-(1 * (not closed))), - Part.BezierCurve().MaxDegree) + + obj.Degree = min((len(pointslist) - (1 * (not closed))), Part.BezierCurve().MaxDegree) obj.Closed = closed obj.AttachmentSupport = support if face is not None: obj.MakeFace = face obj.Proxy.resetcontinuity(obj) - if placement: obj.Placement = placement + if placement: + obj.Placement = placement if App.GuiUp: ViewProviderBezCurve(obj.ViewObject) -# if not face: obj.ViewObject.DisplayMode = "Wireframe" -# obj.ViewObject.DisplayMode = "Wireframe" + # if not face: obj.ViewObject.DisplayMode = "Wireframe" + # obj.ViewObject.DisplayMode = "Wireframe" gui_utils.format_object(obj) gui_utils.select(obj) diff --git a/src/Mod/Draft/draftmake/make_bspline.py b/src/Mod/Draft/draftmake/make_bspline.py index 265eb417f5..593866b49b 100644 --- a/src/Mod/Draft/draftmake/make_bspline.py +++ b/src/Mod/Draft/draftmake/make_bspline.py @@ -67,16 +67,16 @@ def make_bspline(pointslist, closed=False, placement=None, face=None, support=No if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - if not isinstance(pointslist,list): + if not isinstance(pointslist, list): nlist = [] for v in pointslist.Vertexes: nlist.append(v.Point) pointslist = nlist if len(pointslist) < 2: _err = "Draft.make_bspline: not enough points" - App.Console.PrintError(translate("draft", _err)+"\n") + App.Console.PrintError(translate("draft", _err) + "\n") return - if (pointslist[0] == pointslist[-1]): + if pointslist[0] == pointslist[-1]: if len(pointslist) > 2: closed = True pointslist.pop() @@ -85,13 +85,15 @@ def make_bspline(pointslist, closed=False, placement=None, face=None, support=No else: # len == 2 and first == last GIGO _err = "Draft.make_bspline: Invalid pointslist" - App.Console.PrintError(translate("Draft", _err)+"\n") + App.Console.PrintError(translate("Draft", _err) + "\n") return # should have sensible parms from here on if placement: - utils.type_check([(placement,App.Placement)], "make_bspline") - if len(pointslist) == 2: fname = "Line" - else: fname = "BSpline" + utils.type_check([(placement, App.Placement)], "make_bspline") + if len(pointslist) == 2: + fname = "Line" + else: + fname = "BSpline" obj = App.ActiveDocument.addObject("Part::FeaturePython", fname) obj.addExtension("Part::AttachExtensionPython") BSpline(obj) @@ -100,7 +102,8 @@ def make_bspline(pointslist, closed=False, placement=None, face=None, support=No obj.AttachmentSupport = support if face is not None: obj.MakeFace = face - if placement: obj.Placement = placement + if placement: + obj.Placement = placement if App.GuiUp: ViewProviderBSpline(obj.ViewObject) gui_utils.format_object(obj) diff --git a/src/Mod/Draft/draftmake/make_circle.py b/src/Mod/Draft/draftmake/make_circle.py index 71f02e6e1c..817cc0868b 100644 --- a/src/Mod/Draft/draftmake/make_circle.py +++ b/src/Mod/Draft/draftmake/make_circle.py @@ -54,7 +54,7 @@ def _get_normal(axis, ref_rot): local_comp_vec = App.Vector(1, 0, 0) comp_vec = ref_rot.multVec(local_comp_vec) axis = App.Vector(axis) # create independent copy - if axis.getAngle(comp_vec) > math.pi/2: + if axis.getAngle(comp_vec) > math.pi / 2: axis = axis.negative() return axis @@ -104,10 +104,9 @@ def make_circle(radius, placement=None, face=None, startangle=None, endangle=Non return if placement: - utils.type_check([(placement,App.Placement)], "make_circle") + utils.type_check([(placement, App.Placement)], "make_circle") - if (isinstance(radius, Part.Edge) and len(radius.Vertexes) > 1) \ - or startangle != endangle: + if (isinstance(radius, Part.Edge) and len(radius.Vertexes) > 1) or startangle != endangle: name = "Arc" else: name = "Circle" diff --git a/src/Mod/Draft/draftmake/make_circulararray.py b/src/Mod/Draft/draftmake/make_circulararray.py index 0e105c6c2f..bba512b29b 100644 --- a/src/Mod/Draft/draftmake/make_circulararray.py +++ b/src/Mod/Draft/draftmake/make_circulararray.py @@ -35,11 +35,16 @@ from draftutils.messages import _err from draftutils.translate import translate -def make_circular_array(base_object, - r_distance=100, tan_distance=50, - number=3, symmetry=1, - axis=App.Vector(0, 0, 1), center=App.Vector(0, 0, 0), - use_link=True): +def make_circular_array( + base_object, + r_distance=100, + tan_distance=50, + number=3, + symmetry=1, + axis=App.Vector(0, 0, 1), + center=App.Vector(0, 0, 0), + use_link=True, +): """Create a circular array from the given object. Parameters @@ -122,38 +127,46 @@ def make_circular_array(base_object, found, base_object = utils.find_object(base_object, doc=App.activeDocument()) if not found: - _err(translate("draft","Wrong input: base_object not in document.")) + _err(translate("draft", "Wrong input: base_object not in document.")) return None try: - utils.type_check([(r_distance, (int, float, App.Units.Quantity)), - (tan_distance, (int, float, App.Units.Quantity))], - name=_name) + utils.type_check( + [ + (r_distance, (int, float, App.Units.Quantity)), + (tan_distance, (int, float, App.Units.Quantity)), + ], + name=_name, + ) except TypeError: - _err(translate("draft","Wrong input: must be a number or quantity.")) + _err(translate("draft", "Wrong input: must be a number or quantity.")) return None try: - utils.type_check([(number, int), - (symmetry, int)], name=_name) + utils.type_check([(number, int), (symmetry, int)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be an integer number.")) + _err(translate("draft", "Wrong input: must be an integer number.")) return None try: - utils.type_check([(axis, App.Vector), - (center, App.Vector)], name=_name) + utils.type_check([(axis, App.Vector), (center, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None use_link = bool(use_link) - new_obj = make_array.make_array(base_object, - arg1=r_distance, arg2=tan_distance, - arg3=axis, arg4=center, - arg5=number, arg6=symmetry, - use_link=use_link) + new_obj = make_array.make_array( + base_object, + arg1=r_distance, + arg2=tan_distance, + arg3=axis, + arg4=center, + arg5=number, + arg6=symmetry, + use_link=use_link, + ) return new_obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_clone.py b/src/Mod/Draft/draftmake/make_clone.py index 2c5bf5c9eb..dabb1fdadb 100644 --- a/src/Mod/Draft/draftmake/make_clone.py +++ b/src/Mod/Draft/draftmake/make_clone.py @@ -64,19 +64,23 @@ def make_clone(obj, delta=None, forcedraft=False): if prefix: prefix = prefix.strip() + " " - if not isinstance(obj,list): + if not isinstance(obj, list): obj = [obj] - if len(obj) == 1 \ - and obj[0].isDerivedFrom("Part::Part2DObject") \ - and utils.get_type(obj[0]) not in ["BezCurve", "BSpline", "Wire"]: + if ( + len(obj) == 1 + and obj[0].isDerivedFrom("Part::Part2DObject") + and utils.get_type(obj[0]) not in ["BezCurve", "BSpline", "Wire"] + ): # "BezCurve", "BSpline" and "Wire" objects created with < v1.1 # are "Part::Part2DObject" objects but they need not be 2D. cl = App.ActiveDocument.addObject("Part::Part2DObjectPython", "Clone2D") cl.Label = prefix + obj[0].Label + " (2D)" - elif len(obj) == 1 \ - and (hasattr(obj[0], "CloneOf") or utils.get_type(obj[0]) == "BuildingPart") \ - and not forcedraft: + elif ( + len(obj) == 1 + and (hasattr(obj[0], "CloneOf") or utils.get_type(obj[0]) == "BuildingPart") + and not forcedraft + ): # arch objects can be clones try: import Arch @@ -87,13 +91,13 @@ def make_clone(obj, delta=None, forcedraft=False): if utils.get_type(obj[0]) == "BuildingPart": cl = Arch.makeComponent() else: - try: # new-style make function + try: # new-style make function cl = getattr(Arch, "make_" + obj[0].Proxy.Type.lower())() except Exception: - try: # old-style make function + try: # old-style make function cl = getattr(Arch, "make" + obj[0].Proxy.Type)() except Exception: - pass # not a standard Arch object... Fall back to Draft mode + pass # not a standard Arch object... Fall back to Draft mode if cl: base = utils.get_clone_base(obj[0]) cl.Label = prefix + base.Label @@ -119,9 +123,9 @@ def make_clone(obj, delta=None, forcedraft=False): cl.Objects = obj if delta: cl.Placement.move(delta) - elif (len(obj) == 1) and hasattr(obj[0],"Placement"): + elif (len(obj) == 1) and hasattr(obj[0], "Placement"): cl.Placement = obj[0].Placement - if hasattr(cl,"LongName") and hasattr(obj[0],"LongName"): + if hasattr(cl, "LongName") and hasattr(obj[0], "LongName"): cl.LongName = obj[0].LongName if App.GuiUp: ViewProviderClone(cl.ViewObject) diff --git a/src/Mod/Draft/draftmake/make_copy.py b/src/Mod/Draft/draftmake/make_copy.py index 5e45926bd7..20a3af2aea 100644 --- a/src/Mod/Draft/draftmake/make_copy.py +++ b/src/Mod/Draft/draftmake/make_copy.py @@ -58,7 +58,7 @@ def make_copy(obj, force=None, reparent=False, simple_copy=False): newobj = None - if simple_copy and hasattr(obj, 'Shape'): + if simple_copy and hasattr(obj, "Shape"): # this was the old implementation that is actually not used by default _name = utils.get_real_name(obj.Name) newobj = App.ActiveDocument.addObject("Part::Feature", _name) @@ -91,4 +91,5 @@ def make_copy(obj, force=None, reparent=False, simple_copy=False): return newobj + ## @} diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index 05f29d1d3d..005e768649 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -48,9 +48,10 @@ from draftutils.translate import translate from draftobjects.dimension import LinearDimension, AngularDimension if App.GuiUp: - from draftviewproviders.view_dimension \ - import (ViewProviderLinearDimension, - ViewProviderAngularDimension) + from draftviewproviders.view_dimension import ( + ViewProviderLinearDimension, + ViewProviderAngularDimension, + ) def _get_flip_text_lin(p1, p2, wp, normal): @@ -65,15 +66,15 @@ def _get_flip_text_lin(p1, p2, wp, normal): return False if math.isclose(abs(ang), math.pi, abs_tol=tol): return True - if math.isclose(ang, math.pi/2, abs_tol=tol): + if math.isclose(ang, math.pi / 2, abs_tol=tol): return False - if math.isclose(ang, -math.pi/2, abs_tol=tol): + if math.isclose(ang, -math.pi / 2, abs_tol=tol): return True # 90-180 (in that quadrant + 1st point closest to the origin): - if math.pi/2 < ang < math.pi: + if math.pi / 2 < ang < math.pi: return True # 180-270: - if -math.pi < ang < -math.pi/2: + if -math.pi < ang < -math.pi / 2: return True # 0-90 and 270-360: return False @@ -84,6 +85,7 @@ def _get_flip_text_ang(cen, sta, end, normal): if not params.get_param("DimAutoFlipText"): return False import Part + circle = Part.makeCircle(1, cen, normal, sta, end) mid = edges.findMidpoint(circle) wp = WorkingPlane.get_working_plane(update=False) @@ -135,7 +137,7 @@ def make_dimension(p1, p2, p3=None, p4=None): if App.GuiUp: # invert the normal if we are viewing it from the back vnorm = gui_utils.get3DView().getViewDirection() - if vnorm.getAngle(normal) < math.pi/2: + if vnorm.getAngle(normal) < math.pi / 2: normal = normal.negative() new_obj.Normal = normal @@ -217,8 +219,8 @@ def make_dimension(p1, p2, p3=None, p4=None): def makeDimension(p1, p2, p3=None, p4=None): """Create a dimension. DEPRECATED. Use 'make_dimension'.""" - _wrn(translate("draft","This function is deprecated. Do not use this function directly.")) - _wrn(translate("draft","Use one of 'make_linear_dimension', or 'make_linear_dimension_obj'.")) + _wrn(translate("draft", "This function is deprecated. Do not use this function directly.")) + _wrn(translate("draft", "Use one of 'make_linear_dimension', or 'make_linear_dimension_obj'.")) return make_dimension(p1, p2, p3, p4) @@ -258,26 +260,26 @@ def make_linear_dimension(p1, p2, dim_line=None): found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None try: utils.type_check([(p1, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None try: utils.type_check([(p2, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if dim_line: try: utils.type_check([(dim_line, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None else: diff = p2.sub(p1) @@ -347,61 +349,70 @@ def make_linear_dimension_obj(edge_object, i1=1, i2=2, dim_line=None): found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None if isinstance(edge_object, (list, tuple)): - _err(translate("draft","Wrong input: edge_object must not be a list or tuple.")) + _err(translate("draft", "Wrong input: edge_object must not be a list or tuple.")) return None found, edge_object = utils.find_object(edge_object, doc) if not found: - _err(translate("draft","Wrong input: edge_object not in document.")) + _err(translate("draft", "Wrong input: edge_object not in document.")) return None if not hasattr(edge_object, "Shape"): - _err(translate("draft","Wrong input: object doesn't have a 'Shape' to measure.")) + _err(translate("draft", "Wrong input: object doesn't have a 'Shape' to measure.")) return None - if (not hasattr(edge_object.Shape, "Vertexes") - or len(edge_object.Shape.Vertexes) < 1): - _err(translate("draft","Wrong input: object does not have at least 1 element in 'Vertexes' to use for measuring.")) + if not hasattr(edge_object.Shape, "Vertexes") or len(edge_object.Shape.Vertexes) < 1: + _err( + translate( + "draft", + "Wrong input: object does not have at least 1 element in 'Vertexes' to use for measuring.", + ) + ) return None try: utils.type_check([(i1, int)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be an integer.")) + _err(translate("draft", "Wrong input: must be an integer.")) return None if i1 < 1: i1 = 1 - _wrn(translate("draft","i1: values below 1 are not allowed; will be set to 1.")) + _wrn(translate("draft", "i1: values below 1 are not allowed; will be set to 1.")) vx1 = edge_object.getSubObject("Vertex" + str(i1)) if not vx1: - _err(translate("draft","Wrong input: vertex not in object.")) + _err(translate("draft", "Wrong input: vertex not in object.")) return None try: utils.type_check([(i2, int)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if i2 < 1: i2 = len(edge_object.Shape.Vertexes) - _wrn(translate("draft","i2: values below 1 are not allowed; will be set to the last vertex in the object.")) + _wrn( + translate( + "draft", + "i2: values below 1 are not allowed; will be set to the last vertex in the object.", + ) + ) vx2 = edge_object.getSubObject("Vertex" + str(i2)) if not vx2: - _err(translate("draft","Wrong input: vertex not in object.")) + _err(translate("draft", "Wrong input: vertex not in object.")) return None if dim_line: try: utils.type_check([(dim_line, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None else: diff = vx2.Point.sub(vx1.Point) @@ -419,8 +430,7 @@ def make_linear_dimension_obj(edge_object, i1=1, i2=2, dim_line=None): return new_obj -def make_radial_dimension_obj(edge_object, index=1, mode="radius", - dim_line=None): +def make_radial_dimension_obj(edge_object, index=1, mode="radius", dim_line=None): """Create a radial or diameter dimension from an arc object. Parameters @@ -467,56 +477,60 @@ def make_radial_dimension_obj(edge_object, index=1, mode="radius", found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None found, edge_object = utils.find_object(edge_object, doc) if not found: - _err(translate("draft","Wrong input: edge_object not in document.")) + _err(translate("draft", "Wrong input: edge_object not in document.")) return None if not hasattr(edge_object, "Shape"): - _err(translate("draft","Wrong input: object doesn't have a 'Shape' to measure.")) + _err(translate("draft", "Wrong input: object doesn't have a 'Shape' to measure.")) return None - if (not hasattr(edge_object.Shape, "Edges") - or len(edge_object.Shape.Edges) < 1): - _err(translate("draft","Wrong input: object doesn't have at least one element in 'Edges' to use for measuring.")) + if not hasattr(edge_object.Shape, "Edges") or len(edge_object.Shape.Edges) < 1: + _err( + translate( + "draft", + "Wrong input: object doesn't have at least one element in 'Edges' to use for measuring.", + ) + ) return None try: utils.type_check([(index, int)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be an integer.")) + _err(translate("draft", "Wrong input: must be an integer.")) return None if index < 1: index = 1 - _wrn(translate("draft","index: values below 1 are not allowed; will be set to 1.")) + _wrn(translate("draft", "index: values below 1 are not allowed; will be set to 1.")) edge = edge_object.getSubObject("Edge" + str(index)) if not edge: - _err(translate("draft","Wrong input: index doesn't correspond to an edge in the object.")) + _err(translate("draft", "Wrong input: index doesn't correspond to an edge in the object.")) return None - if not hasattr(edge, "Curve") or edge.Curve.TypeId != 'Part::GeomCircle': - _err(translate("draft","Wrong input: index doesn't correspond to a circular edge.")) + if not hasattr(edge, "Curve") or edge.Curve.TypeId != "Part::GeomCircle": + _err(translate("draft", "Wrong input: index doesn't correspond to a circular edge.")) return None try: utils.type_check([(mode, str)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a string, 'radius' or 'diameter'.")) + _err(translate("draft", "Wrong input: must be a string, 'radius' or 'diameter'.")) return None if mode not in ("radius", "diameter"): - _err(translate("draft","Wrong input: must be a string, 'radius' or 'diameter'.")) + _err(translate("draft", "Wrong input: must be a string, 'radius' or 'diameter'.")) return None if dim_line: try: utils.type_check([(dim_line, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None else: center = edge_object.Shape.Edges[index - 1].Curve.Center @@ -532,9 +546,12 @@ def make_radial_dimension_obj(edge_object, index=1, mode="radius", return new_obj -def make_angular_dimension(center=App.Vector(0, 0, 0), - angles=None, # If None, set to [0,90] - dim_line=App.Vector(10, 10, 0), normal=None): +def make_angular_dimension( + center=App.Vector(0, 0, 0), + angles=None, # If None, set to [0,90] + dim_line=App.Vector(10, 10, 0), + normal=None, +): """Create an angular dimension from the given center and angles. Parameters @@ -581,27 +598,26 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None try: utils.type_check([(center, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None try: utils.type_check([(angles, (tuple, list))], name=_name) if len(angles) != 2: - _err(translate("draft","Wrong input: must be a list with two angles.")) + _err(translate("draft", "Wrong input: must be a list with two angles.")) return None ang1, ang2 = angles - utils.type_check([(ang1, (int, float)), - (ang2, (int, float))], name=_name) + utils.type_check([(ang1, (int, float)), (ang2, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a list with two angles.")) + _err(translate("draft", "Wrong input: must be a list with two angles.")) return None # If the angle is larger than 360 degrees, make sure @@ -613,14 +629,14 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), try: utils.type_check([(dim_line, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if normal: try: utils.type_check([(dim_line, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if not normal: @@ -636,7 +652,7 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), # This is determined by the angle between the current # 3D view and the provided normal being below 90 degrees vnorm = gui_utils.get3DView().getViewDirection() - if vnorm.getAngle(normal) < math.pi/2: + if vnorm.getAngle(normal) < math.pi / 2: normal = normal.negative() new_obj.Center = center @@ -660,7 +676,7 @@ def makeAngularDimension(center, angles, p3, normal=None): ang1, ang2 = angles angles = [math.degrees(ang2), math.degrees(ang1)] - return make_angular_dimension(center=center, angles=angles, - dim_line=p3, normal=normal) + return make_angular_dimension(center=center, angles=angles, dim_line=p3, normal=normal) + ## @} diff --git a/src/Mod/Draft/draftmake/make_facebinder.py b/src/Mod/Draft/draftmake/make_facebinder.py index da135e1d0c..7218135c2f 100644 --- a/src/Mod/Draft/draftmake/make_facebinder.py +++ b/src/Mod/Draft/draftmake/make_facebinder.py @@ -52,13 +52,13 @@ def make_facebinder(selectionset, name="Facebinder"): if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - if not isinstance(selectionset,list): + if not isinstance(selectionset, list): selectionset = [selectionset] - fb = App.ActiveDocument.addObject("Part::FeaturePython",name) + fb = App.ActiveDocument.addObject("Part::FeaturePython", name) Facebinder(fb) if App.GuiUp: ViewProviderFacebinder(fb.ViewObject) - faces = [] # unused variable? + faces = [] # unused variable? fb.Proxy.addSubobjects(fb, selectionset) gui_utils.select(fb) return fb diff --git a/src/Mod/Draft/draftmake/make_fillet.py b/src/Mod/Draft/draftmake/make_fillet.py index a0eee54db8..2cf73160f9 100644 --- a/src/Mod/Draft/draftmake/make_fillet.py +++ b/src/Mod/Draft/draftmake/make_fillet.py @@ -48,6 +48,7 @@ DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") ## \addtogroup draftmake # @{ + def _preprocess(objs, radius, chamfer): """Check the inputs and return the edges for the fillet and the objects to be deleted.""" edges = [] @@ -139,4 +140,5 @@ def make_fillet(objs, radius=100, chamfer=False, delete=False): return obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_hatch.py b/src/Mod/Draft/draftmake/make_hatch.py index 3a38333f0a..735d8974c3 100644 --- a/src/Mod/Draft/draftmake/make_hatch.py +++ b/src/Mod/Draft/draftmake/make_hatch.py @@ -1,35 +1,36 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2021 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * * +# * Copyright (c) 2021 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** """This module contains FreeCAD commands for the Draft workbench""" import FreeCAD from draftobjects.hatch import Hatch + if FreeCAD.GuiUp: from draftviewproviders.view_hatch import ViewProviderDraftHatch import draftutils.gui_utils as gui_utils -def make_hatch(baseobject, filename, pattern, scale, rotation, translate=True): +def make_hatch(baseobject, filename, pattern, scale, rotation, translate=True): """make_hatch(baseobject, filename, pattern, scale, rotation, translate): Creates and returns a hatch object made by applying the given pattern of the given PAT file to the faces of the given base object. Given scale, rotation and translate factors are applied to the hatch object. diff --git a/src/Mod/Draft/draftmake/make_label.py b/src/Mod/Draft/draftmake/make_label.py index bdef51646f..c05cb9b4da 100644 --- a/src/Mod/Draft/draftmake/make_label.py +++ b/src/Mod/Draft/draftmake/make_label.py @@ -41,12 +41,17 @@ if App.GuiUp: from draftviewproviders.view_label import ViewProviderLabel -def make_label(target_point=App.Vector(0, 0, 0), - placement=App.Vector(30, 30, 0), - target_object=None, subelements=None, - label_type="Custom", custom_text="Label", - direction="Horizontal", distance=-10, - points=None): +def make_label( + target_point=App.Vector(0, 0, 0), + placement=App.Vector(30, 30, 0), + target_object=None, + subelements=None, + label_type="Custom", + custom_text="Label", + direction="Horizontal", + distance=-10, + points=None, +): """Create a Label object containing different types of information. The current color and text height and font specified in preferences @@ -190,7 +195,7 @@ def make_label(target_point=App.Vector(0, 0, 0), found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None if not target_point: @@ -198,17 +203,15 @@ def make_label(target_point=App.Vector(0, 0, 0), try: utils.type_check([(target_point, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if not placement: placement = App.Placement() try: - utils.type_check([(placement, (App.Placement, - App.Vector, - App.Rotation))], name=_name) + utils.type_check([(placement, (App.Placement, App.Vector, App.Rotation))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a placement, a vector, or a rotation.")) + _err(translate("draft", "Wrong input: must be a placement, a vector, or a rotation.")) return None # Convert the vector or rotation to a full placement @@ -219,12 +222,12 @@ def make_label(target_point=App.Vector(0, 0, 0), if target_object: if isinstance(target_object, (list, tuple)): - _err(translate("draft","Wrong input: target_object must not be a list.")) + _err(translate("draft", "Wrong input: target_object must not be a list.")) return None found, target_object = utils.find_object(target_object, doc) if not found: - _err(translate("draft","Wrong input: target_object not in document.")) + _err(translate("draft", "Wrong input: target_object not in document.")) return None if target_object and subelements: @@ -233,10 +236,14 @@ def make_label(target_point=App.Vector(0, 0, 0), if isinstance(subelements, str): subelements = [subelements] - utils.type_check([(subelements, (list, tuple, str))], - name=_name) + utils.type_check([(subelements, (list, tuple, str))], name=_name) except TypeError: - _err(translate("draft","Wrong input: subelements must be a list or tuple of strings, or a single string.")) + _err( + translate( + "draft", + "Wrong input: subelements must be a list or tuple of strings, or a single string.", + ) + ) return None # The subelements list is used to build a special list @@ -247,7 +254,7 @@ def make_label(target_point=App.Vector(0, 0, 0), for sub in subelements: _sub = target_object.getSubObject(sub) if not _sub: - _err(translate("draft","Wrong input: subelement {} not in object.").format(sub)) + _err(translate("draft", "Wrong input: subelement {} not in object.").format(sub)) return None if not label_type: @@ -255,12 +262,16 @@ def make_label(target_point=App.Vector(0, 0, 0), try: utils.type_check([(label_type, str)], name=_name) except TypeError: - _err(translate("draft","Wrong input: label_type must be a string.")) + _err(translate("draft", "Wrong input: label_type must be a string.")) return None types = label.get_label_types() if label_type not in types: - _err(translate("draft", "Wrong input: label_type must be one of the following:") + " " + str(types).strip("[]")) + _err( + translate("draft", "Wrong input: label_type must be one of the following:") + + " " + + str(types).strip("[]") + ) return None if not custom_text: @@ -268,12 +279,11 @@ def make_label(target_point=App.Vector(0, 0, 0), try: utils.type_check([(custom_text, (str, list))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a list of strings or a single string.")) + _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) return None - if (type(custom_text) is list - and not all(isinstance(element, str) for element in custom_text)): - _err(translate("draft","Wrong input: must be a list of strings or a single string.")) + if type(custom_text) is list and not all(isinstance(element, str) for element in custom_text): + _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) return None if not direction: @@ -281,11 +291,19 @@ def make_label(target_point=App.Vector(0, 0, 0), try: utils.type_check([(direction, str)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'.")) + _err( + translate( + "draft", "Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'." + ) + ) return None if direction not in ("Horizontal", "Vertical", "Custom"): - _err(translate("draft","Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'.")) + _err( + translate( + "draft", "Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'." + ) + ) return None if not distance: @@ -293,11 +311,13 @@ def make_label(target_point=App.Vector(0, 0, 0), try: utils.type_check([(distance, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None if points: - _err_msg = translate("draft","Wrong input: points {} must be a list of at least two vectors.").format(points) + _err_msg = translate( + "draft", "Wrong input: points {} must be a list of at least two vectors." + ).format(points) try: utils.type_check([(points, (tuple, list))], name=_name) except TypeError: @@ -312,8 +332,7 @@ def make_label(target_point=App.Vector(0, 0, 0), _err(_err_msg) return None - new_obj = doc.addObject("App::FeaturePython", - "dLabel") + new_obj = doc.addObject("App::FeaturePython", "dLabel") label.Label(new_obj) new_obj.TargetPoint = target_point @@ -331,7 +350,7 @@ def make_label(target_point=App.Vector(0, 0, 0), new_obj.StraightDistance = distance if points: if direction != "Custom": - _wrn(translate("draft","Direction is not 'Custom'; points won't be used.")) + _wrn(translate("draft", "Direction is not 'Custom'; points won't be used.")) new_obj.Points = points if App.GuiUp: @@ -348,8 +367,9 @@ def make_label(target_point=App.Vector(0, 0, 0), return new_obj -def makeLabel(targetpoint=None, target=None, direction=None, - distance=None, labeltype=None, placement=None): +def makeLabel( + targetpoint=None, target=None, direction=None, distance=None, labeltype=None, placement=None +): """Create a Label. DEPRECATED. Use 'make_label'.""" utils.use_instead("make_label") @@ -358,10 +378,14 @@ def makeLabel(targetpoint=None, target=None, direction=None, if target: try: - utils.type_check([(target, (tuple, list))], - name=_name) + utils.type_check([(target, (tuple, list))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a list of two elements. For example, [object, 'Edge1'].")) + _err( + translate( + "draft", + "Wrong input: must be a list of two elements. For example, [object, 'Edge1'].", + ) + ) return None # In the old function `target` is the original parameter, @@ -383,12 +407,15 @@ def makeLabel(targetpoint=None, target=None, direction=None, target_object = target[0] subelements = target[1] - return make_label(target_point=targetpoint, - placement=placement, - target_object=target_object, - subelements=subelements, - label_type=labeltype, - direction=direction, - distance=distance) + return make_label( + target_point=targetpoint, + placement=placement, + target_object=target_object, + subelements=subelements, + label_type=labeltype, + direction=direction, + distance=distance, + ) + ## @} diff --git a/src/Mod/Draft/draftmake/make_layer.py b/src/Mod/Draft/draftmake/make_layer.py index 584c74ebf4..bd708b274a 100644 --- a/src/Mod/Draft/draftmake/make_layer.py +++ b/src/Mod/Draft/draftmake/make_layer.py @@ -35,8 +35,7 @@ from draftutils.messages import _err from draftutils.translate import translate if App.GuiUp: - from draftviewproviders.view_layer import (ViewProviderLayer, - ViewProviderLayerContainer) + from draftviewproviders.view_layer import ViewProviderLayer, ViewProviderLayerContainer def get_layer_container(): @@ -51,15 +50,14 @@ def get_layer_container(): """ found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None for obj in doc.Objects: if obj.Name == "LayerContainer": return obj - obj = doc.addObject("App::DocumentObjectGroupPython", - "LayerContainer") + obj = doc.addObject("App::DocumentObjectGroupPython", "LayerContainer") obj.Label = translate("draft", "Layers") LayerContainer(obj) @@ -77,12 +75,14 @@ def getLayerContainer(): return get_layer_container() -def make_layer(name=None, - line_color=(0.0, 0.0, 0.0), # does not match default DefaultShapeLineColor - shape_color=(0.8, 0.8, 0.8), # does not match default DefaultShapeColor - line_width=2.0, - draw_style="Solid", - transparency=0): +def make_layer( + name=None, + line_color=(0.0, 0.0, 0.0), # does not match default DefaultShapeLineColor + shape_color=(0.8, 0.8, 0.8), # does not match default DefaultShapeColor + line_width=2.0, + draw_style="Solid", + transparency=0, +): """Create a Layer object in the active document. If a layer container named `'LayerContainer'` does not exist, it is created. @@ -140,14 +140,14 @@ def make_layer(name=None, found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None if name is not None: try: utils.type_check([(name, str)], name=_name) except TypeError: - _err(translate("draft","Wrong input: it must be a string.")) + _err(translate("draft", "Wrong input: it must be a string.")) return None else: name = translate("draft", "Layer") @@ -156,22 +156,22 @@ def make_layer(name=None, try: utils.type_check([(line_color, tuple)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a tuple of three floats 0.0 to 1.0.")) + _err(translate("draft", "Wrong input: must be a tuple of three floats 0.0 to 1.0.")) return None if not all(isinstance(color, (int, float)) for color in line_color): - _err(translate("draft","Wrong input: must be a tuple of three floats 0.0 to 1.0.")) + _err(translate("draft", "Wrong input: must be a tuple of three floats 0.0 to 1.0.")) return None if shape_color is not None: try: utils.type_check([(shape_color, tuple)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a tuple of three floats 0.0 to 1.0.")) + _err(translate("draft", "Wrong input: must be a tuple of three floats 0.0 to 1.0.")) return None if not all(isinstance(color, (int, float)) for color in shape_color): - _err(translate("draft","Wrong input: must be a tuple of three floats 0.0 to 1.0.")) + _err(translate("draft", "Wrong input: must be a tuple of three floats 0.0 to 1.0.")) return None if line_width is not None: @@ -179,18 +179,26 @@ def make_layer(name=None, utils.type_check([(line_width, (int, float))], name=_name) line_width = float(abs(line_width)) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None if draw_style is not None: try: utils.type_check([(draw_style, str)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be 'Solid', 'Dashed', 'Dotted', or 'Dashdot'.")) + _err( + translate( + "draft", "Wrong input: must be 'Solid', 'Dashed', 'Dotted', or 'Dashdot'." + ) + ) return None - if draw_style not in ('Solid', 'Dashed', 'Dotted', 'Dashdot'): - _err(translate("draft","Wrong input: must be 'Solid', 'Dashed', 'Dotted', or 'Dashdot'.")) + if draw_style not in ("Solid", "Dashed", "Dotted", "Dashdot"): + _err( + translate( + "draft", "Wrong input: must be 'Solid', 'Dashed', 'Dotted', or 'Dashdot'." + ) + ) return None if transparency is not None: @@ -198,7 +206,7 @@ def make_layer(name=None, utils.type_check([(transparency, (int, float))], name=_name) transparency = int(abs(transparency)) except TypeError: - _err(translate("draft","Wrong input: must be a number between 0 and 100.")) + _err(translate("draft", "Wrong input: must be a number between 0 and 100.")) return None obj = doc.addObject("App::FeaturePython", "Layer") @@ -225,4 +233,5 @@ def make_layer(name=None, return obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_line.py b/src/Mod/Draft/draftmake/make_line.py index d1030a0be8..1b19e1d81b 100644 --- a/src/Mod/Draft/draftmake/make_line.py +++ b/src/Mod/Draft/draftmake/make_line.py @@ -54,7 +54,7 @@ def make_line(first_param, last_param=None): if hasattr(first_param, "StartPoint") and hasattr(first_param, "EndPoint"): p2 = first_param.EndPoint p1 = first_param.StartPoint - elif hasattr(p1,"Vertexes"): + elif hasattr(p1, "Vertexes"): p2 = first_param.Vertexes[-1].Point p1 = first_param.Vertexes[0].Point else: @@ -62,7 +62,7 @@ def make_line(first_param, last_param=None): App.Console.PrintError(_err + "\n") return - obj = make_wire.make_wire([p1,p2]) + obj = make_wire.make_wire([p1, p2]) return obj diff --git a/src/Mod/Draft/draftmake/make_orthoarray.py b/src/Mod/Draft/draftmake/make_orthoarray.py index f60085f8e7..c54d6d5453 100644 --- a/src/Mod/Draft/draftmake/make_orthoarray.py +++ b/src/Mod/Draft/draftmake/make_orthoarray.py @@ -35,14 +35,16 @@ from draftutils.messages import _wrn, _err from draftutils.translate import translate -def _make_ortho_array(base_object, - v_x=App.Vector(10, 0, 0), - v_y=App.Vector(0, 10, 0), - v_z=App.Vector(0, 0, 10), - n_x=2, - n_y=2, - n_z=1, - use_link=True): +def _make_ortho_array( + base_object, + v_x=App.Vector(10, 0, 0), + v_y=App.Vector(0, 10, 0), + v_z=App.Vector(0, 0, 10), + n_x=2, + n_y=2, + n_z=1, + use_link=True, +): """Create an orthogonal array from the given object. This is a simple wrapper of the `draftmake.make_array.make_array` @@ -58,10 +60,9 @@ def _make_ortho_array(base_object, """ _name = "_make_ortho_array" - new_obj = make_array.make_array(base_object, - arg1=v_x, arg2=v_y, arg3=v_z, - arg4=n_x, arg5=n_y, arg6=n_z, - use_link=use_link) + new_obj = make_array.make_array( + base_object, arg1=v_x, arg2=v_y, arg3=v_z, arg4=n_x, arg5=n_y, arg6=n_z, use_link=use_link + ) return new_obj @@ -69,27 +70,31 @@ def _are_vectors(v_x, v_y, v_z=None, name="Unknown"): """Check that the vectors are numbers.""" try: if v_z: - utils.type_check([(v_x, (int, float, App.Vector)), - (v_y, (int, float, App.Vector)), - (v_z, (int, float, App.Vector))], - name=name) + utils.type_check( + [ + (v_x, (int, float, App.Vector)), + (v_y, (int, float, App.Vector)), + (v_z, (int, float, App.Vector)), + ], + name=name, + ) else: - utils.type_check([(v_x, (int, float, App.Vector)), - (v_y, (int, float, App.Vector))], - name=name) + utils.type_check( + [(v_x, (int, float, App.Vector)), (v_y, (int, float, App.Vector))], name=name + ) except TypeError: - _err(translate("draft","Wrong input: must be a number or vector.")) + _err(translate("draft", "Wrong input: must be a number or vector.")) return False, v_x, v_y, v_z if not isinstance(v_x, App.Vector): v_x = App.Vector(v_x, 0, 0) - _wrn(translate("draft","Input: single value expanded to vector.")) + _wrn(translate("draft", "Input: single value expanded to vector.")) if not isinstance(v_y, App.Vector): v_y = App.Vector(0, v_y, 0) - _wrn(translate("draft","Input: single value expanded to vector.")) + _wrn(translate("draft", "Input: single value expanded to vector.")) if v_z and not isinstance(v_z, App.Vector): v_z = App.Vector(0, 0, v_z) - _wrn(translate("draft","Input: single value expanded to vector.")) + _wrn(translate("draft", "Input: single value expanded to vector.")) return True, v_x, v_y, v_z @@ -98,24 +103,21 @@ def _are_integers(n_x, n_y, n_z=None, name="Unknown"): """Check that the numbers are integers, with minimum value of 1.""" try: if n_z: - utils.type_check([(n_x, int), - (n_y, int), - (n_z, int)], name=name) + utils.type_check([(n_x, int), (n_y, int), (n_z, int)], name=name) else: - utils.type_check([(n_x, int), - (n_y, int)], name=name) + utils.type_check([(n_x, int), (n_y, int)], name=name) except TypeError: - _err(translate("draft","Wrong input: must be an integer number.")) + _err(translate("draft", "Wrong input: must be an integer number.")) return False, n_x, n_y, n_z if n_x < 1: - _wrn(translate("draft","Input: number of elements must be at least 1. It is set to 1.")) + _wrn(translate("draft", "Input: number of elements must be at least 1. It is set to 1.")) n_x = 1 if n_y < 1: - _wrn(translate("draft","Input: number of elements must be at least 1. It is set to 1.")) + _wrn(translate("draft", "Input: number of elements must be at least 1. It is set to 1.")) n_y = 1 if n_z and n_z < 1: - _wrn(translate("draft","Input: number of elements must be at least 1. It is set to 1.")) + _wrn(translate("draft", "Input: number of elements must be at least 1. It is set to 1.")) n_z = 1 return True, n_x, n_y, n_z @@ -125,14 +127,13 @@ def _are_numbers(d_x, d_y, d_z=None, name="Unknown"): """Check that the numbers are numbers.""" try: if d_z: - utils.type_check([(d_x, (int, float)), - (d_y, (int, float)), - (d_z, (int, float))], name=name) + utils.type_check( + [(d_x, (int, float)), (d_y, (int, float)), (d_z, (int, float))], name=name + ) else: - utils.type_check([(d_x, (int, float)), - (d_y, (int, float))], name=name) + utils.type_check([(d_x, (int, float)), (d_y, (int, float))], name=name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return False, d_x, d_y, d_z return True, d_x, d_y, d_z @@ -142,19 +143,21 @@ def _find_object_in_doc(base_object, doc=None): """Check that a document is available and the object exists.""" found, base_object = utils.find_object(base_object, doc=doc) if not found: - _err(translate("draft","Wrong input: base_object not in document.")) + _err(translate("draft", "Wrong input: base_object not in document.")) return found, base_object -def make_ortho_array(base_object, - v_x=App.Vector(10, 0, 0), - v_y=App.Vector(0, 10, 0), - v_z=App.Vector(0, 0, 10), - n_x=2, - n_y=2, - n_z=1, - use_link=True): +def make_ortho_array( + base_object, + v_x=App.Vector(10, 0, 0), + v_y=App.Vector(0, 10, 0), + v_z=App.Vector(0, 0, 10), + n_x=2, + n_y=2, + n_z=1, + use_link=True, +): """Create an orthogonal array from the given object. Parameters @@ -248,8 +251,7 @@ def make_ortho_array(base_object, """ _name = "make_ortho_array" - found, base_object = _find_object_in_doc(base_object, - doc=App.activeDocument()) + found, base_object = _find_object_in_doc(base_object, doc=App.activeDocument()) if not found: return None @@ -263,19 +265,15 @@ def make_ortho_array(base_object, use_link = bool(use_link) - new_obj = _make_ortho_array(base_object, - v_x=v_x, v_y=v_y, v_z=v_z, - n_x=n_x, n_y=n_y, n_z=n_z, - use_link=use_link) + new_obj = _make_ortho_array( + base_object, v_x=v_x, v_y=v_y, v_z=v_z, n_x=n_x, n_y=n_y, n_z=n_z, use_link=use_link + ) return new_obj -def make_ortho_array2d(base_object, - v_x=App.Vector(10, 0, 0), - v_y=App.Vector(0, 10, 0), - n_x=2, - n_y=2, - use_link=True): +def make_ortho_array2d( + base_object, v_x=App.Vector(10, 0, 0), v_y=App.Vector(0, 10, 0), n_x=2, n_y=2, use_link=True +): """Create a 2D orthogonal array from the given object. This works the same as `make_ortho_array`. @@ -321,8 +319,7 @@ def make_ortho_array2d(base_object, """ _name = "make_ortho_array2d" - found, base_object = _find_object_in_doc(base_object, - doc=App.activeDocument()) + found, base_object = _find_object_in_doc(base_object, doc=App.activeDocument()) if not found: return None @@ -336,21 +333,11 @@ def make_ortho_array2d(base_object, use_link = bool(use_link) - new_obj = _make_ortho_array(base_object, - v_x=v_x, v_y=v_y, - n_x=n_x, n_y=n_y, - use_link=use_link) + new_obj = _make_ortho_array(base_object, v_x=v_x, v_y=v_y, n_x=n_x, n_y=n_y, use_link=use_link) return new_obj -def make_rect_array(base_object, - d_x=10, - d_y=10, - d_z=10, - n_x=2, - n_y=2, - n_z=1, - use_link=True): +def make_rect_array(base_object, d_x=10, d_y=10, d_z=10, n_x=2, n_y=2, n_z=1, use_link=True): """Create a rectangular array from the given object. This function wraps around `make_ortho_array` @@ -393,8 +380,7 @@ def make_rect_array(base_object, """ _name = "make_rect_array" - found, base_object = _find_object_in_doc(base_object, - doc=App.activeDocument()) + found, base_object = _find_object_in_doc(base_object, doc=App.activeDocument()) if not found: return None @@ -408,23 +394,20 @@ def make_rect_array(base_object, use_link = bool(use_link) - new_obj = _make_ortho_array(base_object, - v_x=App.Vector(d_x, 0, 0), - v_y=App.Vector(0, d_y, 0), - v_z=App.Vector(0, 0, d_z), - n_x=n_x, - n_y=n_y, - n_z=n_z, - use_link=use_link) + new_obj = _make_ortho_array( + base_object, + v_x=App.Vector(d_x, 0, 0), + v_y=App.Vector(0, d_y, 0), + v_z=App.Vector(0, 0, d_z), + n_x=n_x, + n_y=n_y, + n_z=n_z, + use_link=use_link, + ) return new_obj -def make_rect_array2d(base_object, - d_x=10, - d_y=10, - n_x=2, - n_y=2, - use_link=True): +def make_rect_array2d(base_object, d_x=10, d_y=10, n_x=2, n_y=2, use_link=True): """Create a 2D rectangular array from the given object. This function wraps around `make_ortho_array`, @@ -468,8 +451,7 @@ def make_rect_array2d(base_object, """ _name = "make_rect_array2d" - found, base_object = _find_object_in_doc(base_object, - doc=App.activeDocument()) + found, base_object = _find_object_in_doc(base_object, doc=App.activeDocument()) if not found: return None @@ -483,12 +465,15 @@ def make_rect_array2d(base_object, use_link = bool(use_link) - new_obj = _make_ortho_array(base_object, - v_x=App.Vector(d_x, 0, 0), - v_y=App.Vector(0, d_y, 0), - n_x=n_x, - n_y=n_y, - use_link=use_link) + new_obj = _make_ortho_array( + base_object, + v_x=App.Vector(d_x, 0, 0), + v_y=App.Vector(0, d_y, 0), + n_x=n_x, + n_y=n_y, + use_link=use_link, + ) return new_obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_patharray.py b/src/Mod/Draft/draftmake/make_patharray.py index eb86cf3bf5..142ab7c608 100644 --- a/src/Mod/Draft/draftmake/make_patharray.py +++ b/src/Mod/Draft/draftmake/make_patharray.py @@ -50,14 +50,21 @@ if App.GuiUp: from draftviewproviders.view_draftlink import ViewProviderDraftLink -def make_path_array(base_object, path_object, count=4, - extra=App.Vector(0, 0, 0), subelements=None, - align=False, align_mode="Original", - tan_vector=App.Vector(1, 0, 0), - force_vertical=False, - vertical_vector=App.Vector(0, 0, 1), - start_offset=0.0, end_offset=0.0, - use_link=True): +def make_path_array( + base_object, + path_object, + count=4, + extra=App.Vector(0, 0, 0), + subelements=None, + align=False, + align_mode="Original", + tan_vector=App.Vector(1, 0, 0), + force_vertical=False, + vertical_vector=App.Vector(0, 0, 1), + start_offset=0.0, + end_offset=0.0, + use_link=True, +): """Make a Draft PathArray object. Distribute copies of a `base_object` along `path_object` @@ -166,32 +173,30 @@ def make_path_array(base_object, path_object, count=4, found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None found, base_object = utils.find_object(base_object, doc) if not found: - _err(translate("draft","Wrong input: base_object not in document.")) + _err(translate("draft", "Wrong input: base_object not in document.")) return None found, path_object = utils.find_object(path_object, doc) if not found: - _err(translate("draft","Wrong input: path_object not in document.")) + _err(translate("draft", "Wrong input: path_object not in document.")) return None try: - utils.type_check([(count, (int, float))], - name=_name) + utils.type_check([(count, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None count = int(count) try: - utils.type_check([(extra, App.Vector)], - name=_name) + utils.type_check([(extra, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None if subelements: @@ -200,10 +205,13 @@ def make_path_array(base_object, path_object, count=4, if isinstance(subelements, str): subelements = [subelements] - utils.type_check([(subelements, (list, tuple, str))], - name=_name) + utils.type_check([(subelements, (list, tuple, str))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a list or tuple of strings, or a single string.")) + _err( + translate( + "draft", "Wrong input: must be a list or tuple of strings, or a single string." + ) + ) return None # The subelements list is used to build a special list @@ -228,43 +236,38 @@ def make_path_array(base_object, path_object, count=4, align = bool(align) try: - utils.type_check([(align_mode, str)], - name=_name) + utils.type_check([(align_mode, str)], name=_name) if align_mode not in ("Original", "Frenet", "Tangent"): raise TypeError except TypeError: - _err(translate("draft","Wrong input: must be 'Original', 'Frenet', or 'Tangent'.")) + _err(translate("draft", "Wrong input: must be 'Original', 'Frenet', or 'Tangent'.")) return None try: - utils.type_check([(tan_vector, App.Vector)], - name=_name) + utils.type_check([(tan_vector, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None force_vertical = bool(force_vertical) try: - utils.type_check([(vertical_vector, App.Vector)], - name=_name) + utils.type_check([(vertical_vector, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None try: - utils.type_check([(start_offset, (int, float))], - name=_name) + utils.type_check([(start_offset, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None start_offset = float(start_offset) try: - utils.type_check([(end_offset, (int, float))], - name=_name) + utils.type_check([(end_offset, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None end_offset = float(end_offset) @@ -273,8 +276,7 @@ def make_path_array(base_object, path_object, count=4, if use_link: # The PathArray class must be called in this special way # to make it a PathLinkArray - new_obj = doc.addObject("Part::FeaturePython", "PathArray", - PathArray(None), None, True) + new_obj = doc.addObject("Part::FeaturePython", "PathArray", PathArray(None), None, True) else: new_obj = doc.addObject("Part::FeaturePython", "PathArray") PathArray(new_obj) @@ -305,44 +307,37 @@ def make_path_array(base_object, path_object, count=4, return new_obj -def makePathArray(baseobject, pathobject, count, - xlate=None, align=False, - pathobjsubs=[], - use_link=False): +def makePathArray( + baseobject, pathobject, count, xlate=None, align=False, pathobjsubs=[], use_link=False +): """Create PathArray. DEPRECATED. Use 'make_path_array'.""" - utils.use_instead('make_path_array') + utils.use_instead("make_path_array") - return make_path_array(baseobject, pathobject, count, - xlate, pathobjsubs, - align, - use_link) + return make_path_array(baseobject, pathobject, count, xlate, pathobjsubs, align, use_link) -def make_path_twisted_array(base_object, path_object, - count=15, rot_factor=0.25, - use_link=True): +def make_path_twisted_array(base_object, path_object, count=15, rot_factor=0.25, use_link=True): """Create a Path twisted array.""" _name = "make_path_twisted_array" found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None found, base_object = utils.find_object(base_object, doc) if not found: - _err(translate("draft","Wrong input: base_object not in document.")) + _err(translate("draft", "Wrong input: base_object not in document.")) return None found, path_object = utils.find_object(path_object, doc) if not found: - _err(translate("draft","Wrong input: path_object not in document.")) + _err(translate("draft", "Wrong input: path_object not in document.")) return None try: - utils.type_check([(count, (int, float))], - name=_name) + utils.type_check([(count, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None count = int(count) @@ -350,8 +345,9 @@ def make_path_twisted_array(base_object, path_object, if use_link: # The PathTwistedArray class must be called in this special way # to make it a PathTwistLinkArray - new_obj = doc.addObject("Part::FeaturePython", "PathTwistedArray", - PathTwistedArray(None), None, True) + new_obj = doc.addObject( + "Part::FeaturePython", "PathTwistedArray", PathTwistedArray(None), None, True + ) else: new_obj = doc.addObject("Part::FeaturePython", "PathTwistedArray") PathTwistedArray(new_obj) @@ -373,4 +369,5 @@ def make_path_twisted_array(base_object, path_object, return new_obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_point.py b/src/Mod/Draft/draftmake/make_point.py index 71556d160a..12cf2db1ff 100644 --- a/src/Mod/Draft/draftmake/make_point.py +++ b/src/Mod/Draft/draftmake/make_point.py @@ -38,7 +38,7 @@ if App.GuiUp: def make_point(X=0, Y=0, Z=0, color=None, name="Point", point_size=5): - """ make_point(x, y, z, [color(r, g, b), point_size]) or + """make_point(x, y, z, [color(r, g, b), point_size]) or make_point(Vector, color(r, g, b), point_size]) Creates a Draft Point in the current document. diff --git a/src/Mod/Draft/draftmake/make_pointarray.py b/src/Mod/Draft/draftmake/make_pointarray.py index 9deb017cd9..52dc4b0a6f 100644 --- a/src/Mod/Draft/draftmake/make_pointarray.py +++ b/src/Mod/Draft/draftmake/make_pointarray.py @@ -99,9 +99,11 @@ def make_point_array(base_object, point_object, extra=None, use_link=True): _err(translate("draft", "Wrong input: point_object not in document.")) return None - if not ((hasattr(point_object, "Shape") and hasattr(point_object.Shape, "Vertexes")) - or hasattr(point_object, "Mesh") - or hasattr(point_object, "Points")): + if not ( + (hasattr(point_object, "Shape") and hasattr(point_object.Shape, "Vertexes")) + or hasattr(point_object, "Mesh") + or hasattr(point_object, "Points") + ): _err(translate("draft", "Wrong input: object has the wrong type.")) return None @@ -109,10 +111,7 @@ def make_point_array(base_object, point_object, extra=None, use_link=True): extra = App.Placement() try: - utils.type_check([(extra, (App.Placement, - App.Vector, - App.Rotation))], - name=_name) + utils.type_check([(extra, (App.Placement, App.Vector, App.Rotation))], name=_name) except TypeError: _err(translate("draft", "Wrong input: must be a placement, a vector, or a rotation.")) return None @@ -126,8 +125,7 @@ def make_point_array(base_object, point_object, extra=None, use_link=True): if use_link: # The PointArray class must be called in this special way # to make it a LinkArray - new_obj = doc.addObject("Part::FeaturePython", "PointArray", - PointArray(None), None, True) + new_obj = doc.addObject("Part::FeaturePython", "PointArray", PointArray(None), None, True) else: new_obj = doc.addObject("Part::FeaturePython", "PointArray") PointArray(new_obj) @@ -140,7 +138,9 @@ def make_point_array(base_object, point_object, extra=None, use_link=True): if use_link: ViewProviderDraftLink(new_obj.ViewObject) else: - new_obj.Proxy.execute(new_obj) # Updates Count which is required for correct DiffuseColor. + new_obj.Proxy.execute( + new_obj + ) # Updates Count which is required for correct DiffuseColor. ViewProviderDraftArray(new_obj.ViewObject) gui_utils.format_object(new_obj, new_obj.Base) new_obj.ViewObject.Proxy.resetColors(new_obj.ViewObject) @@ -152,8 +152,9 @@ def make_point_array(base_object, point_object, extra=None, use_link=True): def makePointArray(base, ptlst): """Create PointArray. DEPRECATED. Use 'make_point_array'.""" - utils.use_instead('make_point_array') + utils.use_instead("make_point_array") return make_point_array(base, ptlst) + ## @} diff --git a/src/Mod/Draft/draftmake/make_polararray.py b/src/Mod/Draft/draftmake/make_polararray.py index c4e561567e..af332dc180 100644 --- a/src/Mod/Draft/draftmake/make_polararray.py +++ b/src/Mod/Draft/draftmake/make_polararray.py @@ -35,9 +35,7 @@ from draftutils.messages import _err from draftutils.translate import translate -def make_polar_array(base_object, - number=5, angle=360, center=App.Vector(0, 0, 0), - use_link=True): +def make_polar_array(base_object, number=5, angle=360, center=App.Vector(0, 0, 0), use_link=True): """Create a polar array from the given object. Parameters @@ -94,31 +92,32 @@ def make_polar_array(base_object, found, base_object = utils.find_object(base_object, doc=App.activeDocument()) if not found: - _err(translate("draft","Wrong input: base_object not in document.")) + _err(translate("draft", "Wrong input: base_object not in document.")) return None try: utils.type_check([(number, int)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be an integer number.")) + _err(translate("draft", "Wrong input: must be an integer number.")) return None try: utils.type_check([(angle, (int, float))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a number.")) + _err(translate("draft", "Wrong input: must be a number.")) return None try: utils.type_check([(center, App.Vector)], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a vector.")) + _err(translate("draft", "Wrong input: must be a vector.")) return None use_link = bool(use_link) - new_obj = make_array.make_array(base_object, - arg1=center, arg2=angle, arg3=number, - use_link=use_link) + new_obj = make_array.make_array( + base_object, arg1=center, arg2=angle, arg3=number, use_link=use_link + ) return new_obj + ## @} diff --git a/src/Mod/Draft/draftmake/make_polygon.py b/src/Mod/Draft/draftmake/make_polygon.py index 4e146e839b..a35479f1c7 100644 --- a/src/Mod/Draft/draftmake/make_polygon.py +++ b/src/Mod/Draft/draftmake/make_polygon.py @@ -63,8 +63,9 @@ def make_polygon(nfaces, radius=1, inscribed=True, placement=None, face=None, su if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - if nfaces < 3: return None - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython","Polygon") + if nfaces < 3: + return None + obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", "Polygon") Polygon(obj) obj.FacesNumber = nfaces obj.Radius = radius @@ -75,7 +76,8 @@ def make_polygon(nfaces, radius=1, inscribed=True, placement=None, face=None, su else: obj.DrawMode = "circumscribed" obj.AttachmentSupport = support - if placement: obj.Placement = placement + if placement: + obj.Placement = placement if App.GuiUp: ViewProviderDraft(obj.ViewObject) gui_utils.format_object(obj) diff --git a/src/Mod/Draft/draftmake/make_rectangle.py b/src/Mod/Draft/draftmake/make_rectangle.py index d4b2c4946a..9fe1166b53 100644 --- a/src/Mod/Draft/draftmake/make_rectangle.py +++ b/src/Mod/Draft/draftmake/make_rectangle.py @@ -65,7 +65,7 @@ def make_rectangle(length, height=0, placement=None, face=None, support=None): App.Console.PrintError("No active document. Aborting\n") return - if isinstance(length,(list,tuple)) and (len(length) == 4): + if isinstance(length, (list, tuple)) and (len(length) == 4): verts = length xv = verts[1].sub(verts[0]) yv = verts[3].sub(verts[0]) @@ -75,9 +75,9 @@ def make_rectangle(length, height=0, placement=None, face=None, support=None): return make_rectangle(xv.Length, yv.Length, rp, face, support) if placement: - utils.type_check([(placement,App.Placement)], "make_rectangle") + utils.type_check([(placement, App.Placement)], "make_rectangle") - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython","Rectangle") + obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", "Rectangle") Rectangle(obj) obj.Length = length @@ -87,7 +87,8 @@ def make_rectangle(length, height=0, placement=None, face=None, support=None): if face is not None: obj.MakeFace = face - if placement: obj.Placement = placement + if placement: + obj.Placement = placement if App.GuiUp: ViewProviderRectangle(obj.ViewObject) diff --git a/src/Mod/Draft/draftmake/make_shape2dview.py b/src/Mod/Draft/draftmake/make_shape2dview.py index 402b8ec3ba..50da4f2bc9 100644 --- a/src/Mod/Draft/draftmake/make_shape2dview.py +++ b/src/Mod/Draft/draftmake/make_shape2dview.py @@ -36,7 +36,7 @@ if App.GuiUp: from draftviewproviders.view_base import ViewProviderDraftAlt -def make_shape2dview(baseobj,projectionVector=None,facenumbers=[]): +def make_shape2dview(baseobj, projectionVector=None, facenumbers=[]): """make_shape2dview(object, [projectionVector], [facenumbers]) Add a 2D shape to the document, which is a 2D projection of the given object. @@ -55,7 +55,7 @@ def make_shape2dview(baseobj,projectionVector=None,facenumbers=[]): if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython","Shape2DView") + obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", "Shape2DView") Shape2DView(obj) if App.GuiUp: ViewProviderDraftAlt(obj.ViewObject) diff --git a/src/Mod/Draft/draftmake/make_shapestring.py b/src/Mod/Draft/draftmake/make_shapestring.py index b413b39145..b1b465e088 100644 --- a/src/Mod/Draft/draftmake/make_shapestring.py +++ b/src/Mod/Draft/draftmake/make_shapestring.py @@ -51,8 +51,7 @@ def make_shapestring(String, FontFile, Size=100, Tracking=0): App.Console.PrintError("No active document. Aborting\n") return - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", - "ShapeString") + obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", "ShapeString") ShapeString(obj) obj.String = String obj.FontFile = FontFile @@ -63,7 +62,8 @@ def make_shapestring(String, FontFile, Size=100, Tracking=0): ViewProviderShapeString(obj.ViewObject) gui_utils.format_object(obj) obrep = obj.ViewObject - if "PointSize" in obrep.PropertiesList: obrep.PointSize = 1 # hide the segment end points + if "PointSize" in obrep.PropertiesList: + obrep.PointSize = 1 # hide the segment end points gui_utils.select(obj) obj.recompute() return obj diff --git a/src/Mod/Draft/draftmake/make_sketch.py b/src/Mod/Draft/draftmake/make_sketch.py index 88f7a8031b..39d6bce22a 100644 --- a/src/Mod/Draft/draftmake/make_sketch.py +++ b/src/Mod/Draft/draftmake/make_sketch.py @@ -38,8 +38,15 @@ from draftutils import utils from draftutils.translate import translate -def make_sketch(objects_list, autoconstraints=False, addTo=None, - delete=False, name="Sketch", radiusPrecision=-1, tol=1e-3): +def make_sketch( + objects_list, + autoconstraints=False, + addTo=None, + delete=False, + name="Sketch", + radiusPrecision=-1, + tol=1e-3, +): """make_sketch(objects_list, [autoconstraints], [addTo], [delete], [name], [radiusPrecision], [tol]) @@ -82,22 +89,20 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, shape_norm_yes = list() shape_norm_no = list() - if not isinstance(objects_list,(list,tuple)): + if not isinstance(objects_list, (list, tuple)): objects_list = [objects_list] for obj in objects_list: - if isinstance(obj,Part.Shape): + if isinstance(obj, Part.Shape): shape = obj elif not hasattr(obj, "Shape"): - App.Console.PrintError(translate("draft", - "No shape found") + "\n") + App.Console.PrintError(translate("draft", "No shape found") + "\n") return None else: shape = obj.Shape if not DraftGeomUtils.is_planar(shape, tol): - App.Console.PrintError(translate("draft", - "All shapes must be planar") + "\n") + App.Console.PrintError(translate("draft", "All shapes must be planar") + "\n") return None if DraftGeomUtils.get_normal(shape, tol): @@ -105,15 +110,13 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, else: shape_norm_no.append(shape) - shapes_list = shape_norm_yes + shape_norm_no # test if all shapes are coplanar if len(shape_norm_yes) >= 1: for shape in shapes_list[1:]: if not DraftGeomUtils.are_coplanar(shapes_list[0], shape, tol): - App.Console.PrintError(translate("draft", - "All shapes must be coplanar") + "\n") + App.Console.PrintError(translate("draft", "All shapes must be coplanar") + "\n") return None # define sketch normal normal = DraftGeomUtils.get_normal(shapes_list[0], tol) @@ -129,8 +132,7 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, normal = App.Vector(0, 0, 1) else: if not DraftGeomUtils.is_planar(poly, tol): - App.Console.PrintError(translate("draft", - "All shapes must be coplanar") + "\n") + App.Console.PrintError(translate("draft", "All shapes must be coplanar") + "\n") return None normal = DraftGeomUtils.get_shape_normal(poly) else: @@ -148,24 +150,22 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, def addRadiusConstraint(edge): try: - if radiusPrecision<0: + if radiusPrecision < 0: return - if radiusPrecision==0: - constraints.append(Constraint("Radius", - nobj.GeometryCount-1, edge.Curve.Radius)) + if radiusPrecision == 0: + constraints.append(Constraint("Radius", nobj.GeometryCount - 1, edge.Curve.Radius)) return - r = round(edge.Curve.Radius,radiusPrecision) - constraints.append(Constraint("Equal", - radiuses[r], nobj.GeometryCount-1)) + r = round(edge.Curve.Radius, radiusPrecision) + constraints.append(Constraint("Equal", radiuses[r], nobj.GeometryCount - 1)) except KeyError: - radiuses[r] = nobj.GeometryCount-1 - constraints.append(Constraint("Radius", nobj.GeometryCount-1, r)) + radiuses[r] = nobj.GeometryCount - 1 + constraints.append(Constraint("Radius", nobj.GeometryCount - 1, r)) except AttributeError: pass def convertBezier(edge): if DraftGeomUtils.geomType(edge) == "BezierCurve": - return(edge.Curve.toBSpline(edge.FirstParameter,edge.LastParameter).toShape()) + return edge.Curve.toBSpline(edge.FirstParameter, edge.LastParameter).toShape() else: return edge @@ -181,7 +181,9 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, point = shapes_list[0].Vertexes[0].Point base = App.Vector(normal) - base.Length = point.dot(base.normalize()) # See https://forum.freecad.org/viewtopic.php?f=22&t=69304#p601149 + base.Length = point.dot( + base.normalize() + ) # See https://forum.freecad.org/viewtopic.php?f=22&t=69304#p601149 nobj.Placement = App.Placement(base, rotation) @@ -204,18 +206,23 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, shape = obj if tp == "Shape" else obj.Shape for e in shape.Edges: newedge = convertBezier(e) - nobj.addGeometry(DraftGeomUtils.orientEdge( - newedge, normal, make_arc=True)) + nobj.addGeometry(DraftGeomUtils.orientEdge(newedge, normal, make_arc=True)) addRadiusConstraint(newedge) ok = True if ok and delete: + def delObj(obj): if obj.InList: - App.Console.PrintWarning(translate("draft", - "Cannot delete object {} with dependency".format(obj.Label)) + "\n") + App.Console.PrintWarning( + translate( + "draft", "Cannot delete object {} with dependency".format(obj.Label) + ) + + "\n" + ) else: obj.Document.removeObject(obj.Name) + try: if delete == "all": objs = [obj] @@ -226,8 +233,10 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None, else: delObj(obj) except Exception as ex: - App.Console.PrintWarning(translate("draft", - "Failed to delete object {}: {}".format(obj.Label, ex)) + "\n") + App.Console.PrintWarning( + translate("draft", "Failed to delete object {}: {}".format(obj.Label, ex)) + + "\n" + ) nobj.addConstraint(constraints) if autoconstraints: diff --git a/src/Mod/Draft/draftmake/make_text.py b/src/Mod/Draft/draftmake/make_text.py index 6248f7b215..4ca4813753 100644 --- a/src/Mod/Draft/draftmake/make_text.py +++ b/src/Mod/Draft/draftmake/make_text.py @@ -89,28 +89,25 @@ def make_text(string, placement=None, screen=False, height=None, line_spacing=1) found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None try: utils.type_check([(string, (str, list))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a list of strings or a single string.")) + _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) return None - if (type(string) is list - and not all(isinstance(element, str) for element in string)): - _err(translate("draft","Wrong input: must be a list of strings or a single string.")) + if type(string) is list and not all(isinstance(element, str) for element in string): + _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) return None if not placement: placement = App.Placement() try: - utils.type_check([(placement, (App.Placement, - App.Vector, - App.Rotation))], name=_name) + utils.type_check([(placement, (App.Placement, App.Vector, App.Rotation))], name=_name) except TypeError: - _err(translate("draft","Wrong input: must be a placement, a vector, or a rotation.")) + _err(translate("draft", "Wrong input: must be a placement, a vector, or a rotation.")) return None # Convert the vector or rotation to a full placement @@ -175,7 +172,7 @@ def convert_draft_texts(textslist=None): found, doc = utils.find_doc(App.activeDocument()) if not found: - _err(translate("draft","No active document. Aborting.")) + _err(translate("draft", "No active document. Aborting.")) return None if not textslist: @@ -215,4 +212,5 @@ def convertDraftTexts(textslist=[]): utils.use_instead("convert_draft_texts") return convert_draft_texts(textslist) + ## @} diff --git a/src/Mod/Draft/draftmake/make_wire.py b/src/Mod/Draft/draftmake/make_wire.py index d650e431d4..c8e1e9b57b 100644 --- a/src/Mod/Draft/draftmake/make_wire.py +++ b/src/Mod/Draft/draftmake/make_wire.py @@ -72,12 +72,12 @@ def make_wire(pointslist, closed=False, placement=None, face=None, support=None, import Part - if isinstance(pointslist, (list,tuple)): + if isinstance(pointslist, (list, tuple)): for pnt in pointslist: if not isinstance(pnt, App.Vector): App.Console.PrintError( - "Items must be Base.Vector objects, not {}\n".format( - type(pnt))) + "Items must be Base.Vector objects, not {}\n".format(type(pnt)) + ) return None elif isinstance(pointslist, Part.Wire): @@ -89,11 +89,9 @@ def make_wire(pointslist, closed=False, placement=None, face=None, support=None, pointslist = [v.Point for v in pointslist.OrderedVertexes] else: - App.Console.PrintError("Can't make Draft Wire from {}\n".format( - type(pointslist))) + App.Console.PrintError("Can't make Draft Wire from {}\n".format(type(pointslist))) return None - if len(pointslist) == 0: App.Console.PrintWarning("Draft Wire created with empty point list\n") diff --git a/src/Mod/Draft/draftmake/make_wpproxy.py b/src/Mod/Draft/draftmake/make_wpproxy.py index 62ae7dedf6..6fec1a9de7 100644 --- a/src/Mod/Draft/draftmake/make_wpproxy.py +++ b/src/Mod/Draft/draftmake/make_wpproxy.py @@ -46,7 +46,7 @@ def make_workingplaneproxy(placement): specify the p. """ if App.ActiveDocument: - obj = App.ActiveDocument.addObject("App::FeaturePython","WPProxy") + obj = App.ActiveDocument.addObject("App::FeaturePython", "WPProxy") WorkingPlaneProxy(obj) if App.GuiUp: ViewProviderWorkingPlaneProxy(obj.ViewObject) diff --git a/src/Mod/Draft/draftobjects/array.py b/src/Mod/Draft/draftobjects/array.py index 15b106c37d..ce23aa6f31 100644 --- a/src/Mod/Draft/draftobjects/array.py +++ b/src/Mod/Draft/draftobjects/array.py @@ -75,7 +75,7 @@ class Array(DraftLink): _log("v1.1, " + obj.Name + ", added hidden property 'PlacementList'") self.set_general_properties(obj) - self.execute(obj) # Required to update Count and/or PlacementList. + self.execute(obj) # Required to update Count and/or PlacementList. def set_properties(self, obj): """Set properties only if they don't exist.""" @@ -94,67 +94,57 @@ class Array(DraftLink): properties = obj.PropertiesList if "Base" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The base object that will be duplicated") + _tip = QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated") obj.addProperty("App::PropertyLink", "Base", "Objects", _tip, locked=True) obj.Base = None if "ArrayType" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The type of array to create.\n" - "- Ortho: places the copies " - "in the direction of the global X, " - "Y, Z axes.\n" - "- Polar: places the copies along " - "a circular arc, up to a specified " - "angle, and with certain orientation " - "defined by a center and an axis.\n" - "- Circular: places the copies " - "in concentric circles " - "around the base object.") - obj.addProperty("App::PropertyEnumeration", - "ArrayType", - "Objects", - _tip, - locked=True) - obj.ArrayType = ['ortho', 'polar', 'circular'] + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The type of array to create.\n" + "- Ortho: places the copies " + "in the direction of the global X, " + "Y, Z axes.\n" + "- Polar: places the copies along " + "a circular arc, up to a specified " + "angle, and with certain orientation " + "defined by a center and an axis.\n" + "- Circular: places the copies " + "in concentric circles " + "around the base object.", + ) + obj.addProperty("App::PropertyEnumeration", "ArrayType", "Objects", _tip, locked=True) + obj.ArrayType = ["ortho", "polar", "circular"] if "Fuse" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Specifies if the copies " - "should be fused together " - "if they touch each other (slower)") - obj.addProperty("App::PropertyBool", - "Fuse", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Specifies if the copies " + "should be fused together " + "if they touch each other (slower)", + ) + obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True) obj.Fuse = False if "Count" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Total number of elements " - "in the array.\n" - "This property is read-only, " - "as the number depends " - "on the parameters of the array.") - obj.addProperty("App::PropertyInteger", - "Count", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Total number of elements " + "in the array.\n" + "This property is read-only, " + "as the number depends " + "on the parameters of the array.", + ) + obj.addProperty("App::PropertyInteger", "Count", "Objects", _tip, locked=True) obj.Count = 0 obj.setEditorMode("Count", 1) # Read only if not self.use_link: if "PlacementList" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement for each array element") - obj.addProperty("App::PropertyPlacementList", - "PlacementList", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element") + obj.addProperty( + "App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True + ) obj.PlacementList = [] def set_ortho_properties(self, obj): @@ -162,66 +152,51 @@ class Array(DraftLink): properties = obj.PropertiesList if "NumberX" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of copies in X-direction") - obj.addProperty("App::PropertyInteger", - "NumberX", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in X-direction") + obj.addProperty( + "App::PropertyInteger", "NumberX", "Orthogonal array", _tip, locked=True + ) obj.NumberX = 2 if "NumberY" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of copies in Y-direction") - obj.addProperty("App::PropertyInteger", - "NumberY", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in Y-direction") + obj.addProperty( + "App::PropertyInteger", "NumberY", "Orthogonal array", _tip, locked=True + ) obj.NumberY = 2 if "NumberZ" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of copies in Z-direction") - obj.addProperty("App::PropertyInteger", - "NumberZ", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in Z-direction") + obj.addProperty( + "App::PropertyInteger", "NumberZ", "Orthogonal array", _tip, locked=True + ) obj.NumberZ = 1 if "IntervalX" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance and orientation " - "of intervals in X-direction") - obj.addProperty("App::PropertyVectorDistance", - "IntervalX", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Distance and orientation " "of intervals in X-direction" + ) + obj.addProperty( + "App::PropertyVectorDistance", "IntervalX", "Orthogonal array", _tip, locked=True + ) obj.IntervalX = App.Vector(50, 0, 0) if "IntervalY" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance and orientation " - "of intervals in Y-direction") - obj.addProperty("App::PropertyVectorDistance", - "IntervalY", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Distance and orientation " "of intervals in Y-direction" + ) + obj.addProperty( + "App::PropertyVectorDistance", "IntervalY", "Orthogonal array", _tip, locked=True + ) obj.IntervalY = App.Vector(0, 50, 0) if "IntervalZ" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance and orientation " - "of intervals in Z-direction") - obj.addProperty("App::PropertyVectorDistance", - "IntervalZ", - "Orthogonal array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Distance and orientation " "of intervals in Z-direction" + ) + obj.addProperty( + "App::PropertyVectorDistance", "IntervalZ", "Orthogonal array", _tip, locked=True + ) obj.IntervalZ = App.Vector(0, 0, 50) def set_polar_circular_properties(self, obj): @@ -229,47 +204,47 @@ class Array(DraftLink): properties = obj.PropertiesList if "Axis" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The axis direction around which " - "the elements in a polar or " - "a circular array will be created") - obj.addProperty("App::PropertyVector", - "Axis", - "Polar/circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The axis direction around which " + "the elements in a polar or " + "a circular array will be created", + ) + obj.addProperty( + "App::PropertyVector", "Axis", "Polar/circular array", _tip, locked=True + ) obj.Axis = App.Vector(0, 0, 1) if "Center" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Center point for polar and " - "circular arrays.\n" - "The 'Axis' passes through this point.") - obj.addProperty("App::PropertyVectorDistance", - "Center", - "Polar/circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Center point for polar and " + "circular arrays.\n" + "The 'Axis' passes through this point.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "Center", "Polar/circular array", _tip, locked=True + ) obj.Center = App.Vector(0, 0, 0) # The AxisReference property must be attached after Axis and Center # so that onChanged works properly if "AxisReference" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The axis object that overrides " - "the value of 'Axis' and 'Center', " - "for example, a datum line.\n" - "Its placement, position and rotation, " - "will be used when creating polar " - "and circular arrays.\n" - "Leave this property empty " - "to be able to set 'Axis' and 'Center' " - "manually.") - obj.addProperty("App::PropertyLinkGlobal", - "AxisReference", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The axis object that overrides " + "the value of 'Axis' and 'Center', " + "for example, a datum line.\n" + "Its placement, position and rotation, " + "will be used when creating polar " + "and circular arrays.\n" + "Leave this property empty " + "to be able to set 'Axis' and 'Center' " + "manually.", + ) + obj.addProperty( + "App::PropertyLinkGlobal", "AxisReference", "Objects", _tip, locked=True + ) obj.AxisReference = None def set_polar_properties(self, obj): @@ -277,34 +252,22 @@ class Array(DraftLink): properties = obj.PropertiesList if "NumberPolar" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of copies in the polar direction") - obj.addProperty("App::PropertyInteger", - "NumberPolar", - "Polar array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in the polar direction") + obj.addProperty("App::PropertyInteger", "NumberPolar", "Polar array", _tip, locked=True) obj.NumberPolar = 5 if "IntervalAxis" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance and orientation " - "of intervals in 'Axis' direction") - obj.addProperty("App::PropertyVectorDistance", - "IntervalAxis", - "Polar array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Distance and orientation " "of intervals in 'Axis' direction" + ) + obj.addProperty( + "App::PropertyVectorDistance", "IntervalAxis", "Polar array", _tip, locked=True + ) obj.IntervalAxis = App.Vector(0, 0, 0) if "Angle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Angle to cover with copies") - obj.addProperty("App::PropertyAngle", - "Angle", - "Polar array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Angle to cover with copies") + obj.addProperty("App::PropertyAngle", "Angle", "Polar array", _tip, locked=True) obj.Angle = 360 def set_circular_properties(self, obj): @@ -312,47 +275,39 @@ class Array(DraftLink): properties = obj.PropertiesList if "RadialDistance" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance between concentric circles") - obj.addProperty("App::PropertyDistance", - "RadialDistance", - "Circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Distance between concentric circles") + obj.addProperty( + "App::PropertyDistance", "RadialDistance", "Circular array", _tip, locked=True + ) obj.RadialDistance = 50 if "TangentialDistance" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Distance between copies " - "in the same circle") - obj.addProperty("App::PropertyDistance", - "TangentialDistance", - "Circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Distance between copies " "in the same circle" + ) + obj.addProperty( + "App::PropertyDistance", "TangentialDistance", "Circular array", _tip, locked=True + ) obj.TangentialDistance = 25 if "NumberCircles" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of concentric circle. " - "The 'Base' object counts as one circle.") - obj.addProperty("App::PropertyInteger", - "NumberCircles", - "Circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Number of concentric circle. " "The 'Base' object counts as one circle.", + ) + obj.addProperty( + "App::PropertyInteger", "NumberCircles", "Circular array", _tip, locked=True + ) obj.NumberCircles = 3 if "Symmetry" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "A parameter that determines " - "how many symmetry planes " - "the circular array will have") - obj.addProperty("App::PropertyInteger", - "Symmetry", - "Circular array", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "A parameter that determines " + "how many symmetry planes " + "the circular array will have", + ) + obj.addProperty("App::PropertyInteger", "Symmetry", "Circular array", _tip, locked=True) obj.Symmetry = 1 def set_link_properties(self, obj): @@ -361,21 +316,17 @@ class Array(DraftLink): if self.use_link: if "ExpandArray" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Show the individual array elements " - "(only for Link arrays)") - obj.addProperty("App::PropertyBool", - "ExpandArray", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Show the individual array elements " "(only for Link arrays)" + ) + obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True) obj.ExpandArray = False def linkSetup(self, obj): """Set up the object as a link object.""" super(Array, self).linkSetup(obj) - obj.configLinkProperty(ElementCount='Count') - obj.setPropertyStatus('Count', 'Hidden') + obj.configLinkProperty(ElementCount="Count") + obj.setPropertyStatus("Count", "Hidden") def onChanged(self, obj, prop): """Execute when a property is changed.""" @@ -395,42 +346,67 @@ class Array(DraftLink): if prop == "ArrayType": if obj.ArrayType == "ortho": - for pr in ("NumberX", "NumberY", "NumberZ", - "IntervalX", "IntervalY", "IntervalZ"): + for pr in ("NumberX", "NumberY", "NumberZ", "IntervalX", "IntervalY", "IntervalZ"): obj.setPropertyStatus(pr, "-Hidden") - for pr in ("Axis", "Center", "NumberPolar", "Angle", - "IntervalAxis", "NumberCircles", - "RadialDistance", "TangentialDistance", - "Symmetry"): + for pr in ( + "Axis", + "Center", + "NumberPolar", + "Angle", + "IntervalAxis", + "NumberCircles", + "RadialDistance", + "TangentialDistance", + "Symmetry", + ): obj.setPropertyStatus(pr, "Hidden") if obj.ArrayType == "polar": - for pr in ("Axis", "Center", "NumberPolar", - "Angle", "IntervalAxis"): + for pr in ("Axis", "Center", "NumberPolar", "Angle", "IntervalAxis"): obj.setPropertyStatus(pr, "-Hidden") - for pr in ("NumberX", "NumberY", "NumberZ", - "IntervalX", "IntervalY", "IntervalZ", - "NumberCircles", "RadialDistance", - "TangentialDistance", "Symmetry"): + for pr in ( + "NumberX", + "NumberY", + "NumberZ", + "IntervalX", + "IntervalY", + "IntervalZ", + "NumberCircles", + "RadialDistance", + "TangentialDistance", + "Symmetry", + ): obj.setPropertyStatus(pr, "Hidden") if obj.ArrayType == "circular": - for pr in ("Axis", "Center", "NumberCircles", - "RadialDistance", "TangentialDistance", - "Symmetry"): + for pr in ( + "Axis", + "Center", + "NumberCircles", + "RadialDistance", + "TangentialDistance", + "Symmetry", + ): obj.setPropertyStatus(pr, "-Hidden") - for pr in ("NumberX", "NumberY", "NumberZ", - "IntervalX", "IntervalY", "IntervalZ", - "NumberPolar", "Angle", "IntervalAxis"): + for pr in ( + "NumberX", + "NumberY", + "NumberZ", + "IntervalX", + "IntervalY", + "IntervalZ", + "NumberPolar", + "Angle", + "IntervalAxis", + ): obj.setPropertyStatus(pr, "Hidden") def execute(self, obj): """Execute when the object is created or recomputed.""" - if self.props_changed_placement_only(obj) \ - or not obj.Base: + if self.props_changed_placement_only(obj) or not obj.Base: self.props_changed_clear() return @@ -444,43 +420,49 @@ class Array(DraftLink): axis = reference.Rotation * App.Vector(0, 0, 1) center = reference.Base else: - _info = ("'AxisReference' has no 'Placement' property. " - "Please select a different object to use as " - "reference.") + _info = ( + "'AxisReference' has no 'Placement' property. " + "Please select a different object to use as " + "reference." + ) raise TypeError(_info) if obj.ArrayType == "ortho": - pls = rect_placements(obj.Base.Placement, - obj.IntervalX, - obj.IntervalY, - obj.IntervalZ, - obj.NumberX, - obj.NumberY, - obj.NumberZ) + pls = rect_placements( + obj.Base.Placement, + obj.IntervalX, + obj.IntervalY, + obj.IntervalZ, + obj.NumberX, + obj.NumberY, + obj.NumberZ, + ) elif obj.ArrayType == "polar": av = obj.IntervalAxis if hasattr(obj, "IntervalAxis") else None - pls = polar_placements(obj.Base.Placement, - center, obj.Angle.Value, - obj.NumberPolar, axis, av) + pls = polar_placements( + obj.Base.Placement, center, obj.Angle.Value, obj.NumberPolar, axis, av + ) elif obj.ArrayType == "circular": - pls = circ_placements(obj.Base.Placement, - obj.RadialDistance, - obj.TangentialDistance, - axis, center, - obj.NumberCircles, obj.Symmetry) + pls = circ_placements( + obj.Base.Placement, + obj.RadialDistance, + obj.TangentialDistance, + axis, + center, + obj.NumberCircles, + obj.Symmetry, + ) self.buildShape(obj, pl, pls) self.props_changed_clear() - return (not self.use_link) + return not self.use_link # Alias for compatibility with v0.18 and earlier _Array = Array -def rect_placements(base_placement, - xvector, yvector, zvector, - xnum, ynum, znum): +def rect_placements(base_placement, xvector, yvector, zvector, xnum, ynum, znum): """Determine the placements where the rectangular copies will be.""" pl = base_placement placements = [pl.copy()] @@ -513,9 +495,7 @@ def rect_placements(base_placement, return placements -def polar_placements(base_placement, - center, angle, - number, axis, axisvector): +def polar_placements(base_placement, center, angle, number, axis, axisvector): """Determine the placements where the polar copies will be.""" # print("angle ",angle," num ",num) placements = [base_placement.copy()] @@ -540,10 +520,9 @@ def polar_placements(base_placement, return placements -def circ_placements(base_placement, - r_distance, tan_distance, - axis, center, - circle_number, symmetry): +def circ_placements( + base_placement, r_distance, tan_distance, axis, center, circle_number, symmetry +): """Determine the placements where the circular copies will be.""" symmetry = max(1, symmetry) lead = (0, 1, 0) @@ -572,4 +551,5 @@ def circ_placements(base_placement, return placements + ## @} diff --git a/src/Mod/Draft/draftobjects/base.py b/src/Mod/Draft/draftobjects/base.py index 507a92fec1..ecd4396d62 100644 --- a/src/Mod/Draft/draftobjects/base.py +++ b/src/Mod/Draft/draftobjects/base.py @@ -79,7 +79,7 @@ class DraftObject(object): obj.Proxy = self self.Type = tp - def onDocumentRestored(self,obj): + def onDocumentRestored(self, obj): # Object properties are updated when the document is opened. self.props_changed_clear() diff --git a/src/Mod/Draft/draftobjects/bezcurve.py b/src/Mod/Draft/draftobjects/bezcurve.py index 24f8d4a4e3..6d1b89798f 100644 --- a/src/Mod/Draft/draftobjects/bezcurve.py +++ b/src/Mod/Draft/draftobjects/bezcurve.py @@ -41,39 +41,32 @@ class BezCurve(DraftObject): def __init__(self, obj): super().__init__(obj, "BezCurve") - _tip = QT_TRANSLATE_NOOP("App::Property", - "The points of the Bezier curve") + _tip = QT_TRANSLATE_NOOP("App::Property", "The points of the Bezier curve") obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The degree of the Bezier function") + _tip = QT_TRANSLATE_NOOP("App::Property", "The degree of the Bezier function") obj.addProperty("App::PropertyInteger", "Degree", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Continuity") + _tip = QT_TRANSLATE_NOOP("App::Property", "Continuity") obj.addProperty("App::PropertyIntegerList", "Continuity", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "If the Bezier curve should be closed or not") + _tip = QT_TRANSLATE_NOOP("App::Property", "If the Bezier curve should be closed or not") obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Create a face if this curve is closed") + _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this curve is closed") obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The length of this object") + _tip = QT_TRANSLATE_NOOP("App::Property", "The length of this object") obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The area of this object") + _tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object") obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") obj.Closed = False obj.Degree = 3 obj.Continuity = [] - #obj.setEditorMode("Degree", 2) + # obj.setEditorMode("Degree", 2) obj.setEditorMode("Continuity", 1) def onDocumentRestored(self, obj): @@ -92,67 +85,69 @@ class BezCurve(DraftObject): fp.positionBySupport() self.props_changed_clear() - def _segpoleslst(self,fp): + def _segpoleslst(self, fp): """Split the points into segments.""" - if not fp.Closed and len(fp.Points) >= 2: #allow lower degree segment - poles=fp.Points[1:] - elif fp.Closed and len(fp.Points) >= fp.Degree: #drawable - #poles=fp.Points[1:(fp.Degree*(len(fp.Points)//fp.Degree))]+fp.Points[0:1] - poles=fp.Points[1:]+fp.Points[0:1] + if not fp.Closed and len(fp.Points) >= 2: # allow lower degree segment + poles = fp.Points[1:] + elif fp.Closed and len(fp.Points) >= fp.Degree: # drawable + # poles=fp.Points[1:(fp.Degree*(len(fp.Points)//fp.Degree))]+fp.Points[0:1] + poles = fp.Points[1:] + fp.Points[0:1] else: - poles=[] - return [poles[x:x+fp.Degree] for x in \ - range(0, len(poles), (fp.Degree or 1))] + poles = [] + return [poles[x : x + fp.Degree] for x in range(0, len(poles), (fp.Degree or 1))] - def resetcontinuity(self,fp): - fp.Continuity = [0]*(len(self._segpoleslst(fp))-1+1*fp.Closed) - #nump= len(fp.Points)-1+fp.Closed*1 - #numsegments = (nump // fp.Degree) + 1 * (nump % fp.Degree > 0) -1 - #fp.Continuity = [0]*numsegments + def resetcontinuity(self, fp): + fp.Continuity = [0] * (len(self._segpoleslst(fp)) - 1 + 1 * fp.Closed) + # nump= len(fp.Points)-1+fp.Closed*1 + # numsegments = (nump // fp.Degree) + 1 * (nump % fp.Degree > 0) -1 + # fp.Continuity = [0]*numsegments def onChanged(self, fp, prop): self.props_changed_store(prop) - if prop == 'Closed': + if prop == "Closed": # if remove the last entry when curve gets opened oldlen = len(fp.Continuity) - newlen = (len(self._segpoleslst(fp))-1+1*fp.Closed) + newlen = len(self._segpoleslst(fp)) - 1 + 1 * fp.Closed if oldlen > newlen: fp.Continuity = fp.Continuity[:newlen] if oldlen < newlen: - fp.Continuity = fp.Continuity + [0]*(newlen-oldlen) + fp.Continuity = fp.Continuity + [0] * (newlen - oldlen) - if (hasattr(fp,'Closed') and - fp.Closed and - prop in ['Points','Degree','Closed'] and - len(fp.Points) % fp.Degree): + if ( + hasattr(fp, "Closed") + and fp.Closed + and prop in ["Points", "Degree", "Closed"] + and len(fp.Points) % fp.Degree + ): # the curve editing tools can't handle extra points - fp.Points=fp.Points[:(fp.Degree*(len(fp.Points)//fp.Degree))] - #for closed curves + fp.Points = fp.Points[: (fp.Degree * (len(fp.Points) // fp.Degree))] + # for closed curves if prop in ["Degree"] and fp.Degree >= 1: self.resetcontinuity(fp) - if prop in ["Points","Degree","Continuity","Closed"]: + if prop in ["Points", "Degree", "Continuity", "Closed"]: self.createGeometry(fp) - def createGeometry(self,fp): + def createGeometry(self, fp): import Part + plm = fp.Placement if fp.Points: startpoint = fp.Points[0] edges = [] for segpoles in self._segpoleslst(fp): -# if len(segpoles) == fp.Degree # would skip additional poles - c = Part.BezierCurve() #last segment may have lower degree + # if len(segpoles) == fp.Degree # would skip additional poles + c = Part.BezierCurve() # last segment may have lower degree c.increase(len(segpoles)) - c.setPoles([startpoint]+segpoles) + c.setPoles([startpoint] + segpoles) edges.append(Part.Edge(c)) startpoint = segpoles[-1] w = Part.Wire(edges) if fp.Closed and w.isClosed(): try: - if hasattr(fp,"MakeFace"): + if hasattr(fp, "MakeFace"): if fp.MakeFace: w = Part.Face(w) else: @@ -160,31 +155,31 @@ class BezCurve(DraftObject): except Part.OCCError: pass fp.Shape = w - if hasattr(fp,"Area") and hasattr(w,"Area"): + if hasattr(fp, "Area") and hasattr(w, "Area"): fp.Area = w.Area - if hasattr(fp,"Length") and hasattr(w,"Length"): + if hasattr(fp, "Length") and hasattr(w, "Length"): fp.Length = w.Length fp.Placement = plm @classmethod - def symmetricpoles(cls,knot, p1, p2): + def symmetricpoles(cls, knot, p1, p2): """Make two poles symmetric respective to the knot.""" p1h = App.Vector(p1) p2h = App.Vector(p2) p1h.multiply(0.5) p2h.multiply(0.5) - return ( knot+p1h-p2h , knot+p2h-p1h ) + return (knot + p1h - p2h, knot + p2h - p1h) @classmethod - def tangentpoles(cls,knot, p1, p2,allowsameside=False): + def tangentpoles(cls, knot, p1, p2, allowsameside=False): """Make two poles have the same tangent at knot.""" p12n = p2.sub(p1) p12n.normalize() - p1k = knot-p1 - p2k = knot-p2 - p1k_= App.Vector(p12n) - kon12=(p1k * p12n) - if allowsameside or not (kon12 < 0 or p2k * p12n > 0):# instead of moving + p1k = knot - p1 + p2k = knot - p2 + p1k_ = App.Vector(p12n) + kon12 = p1k * p12n + if allowsameside or not (kon12 < 0 or p2k * p12n > 0): # instead of moving p1k_.multiply(kon12) pk_k = knot - p1 - p1k_ return (p1 + pk_k, p2 + pk_k) @@ -192,13 +187,13 @@ class BezCurve(DraftObject): return cls.symmetricpoles(knot, p1, p2) @staticmethod - def modifysymmetricpole(knot,p1): + def modifysymmetricpole(knot, p1): """calculate the coordinates of the opposite pole of a symmetric knot""" return knot + knot - p1 @staticmethod - def modifytangentpole(knot,p1,oldp2): + def modifytangentpole(knot, p1, oldp2): """calculate the coordinates of the opposite pole of a tangent knot""" pn = knot - p1 diff --git a/src/Mod/Draft/draftobjects/block.py b/src/Mod/Draft/draftobjects/block.py index 478d5674d6..5ac385b41f 100644 --- a/src/Mod/Draft/draftobjects/block.py +++ b/src/Mod/Draft/draftobjects/block.py @@ -39,9 +39,8 @@ class Block(DraftObject): def __init__(self, obj): super().__init__(obj, "Block") - _tip = QT_TRANSLATE_NOOP("App::Property", - "The components of this block") - obj.addProperty("App::PropertyLinkList","Components", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The components of this block") + obj.addProperty("App::PropertyLinkList", "Components", "Draft", _tip, locked=True) def onDocumentRestored(self, obj): super().onDocumentRestored(obj) @@ -56,6 +55,7 @@ class Block(DraftObject): return import Part + plm = obj.Placement shps = [] for c in obj.Components: diff --git a/src/Mod/Draft/draftobjects/bspline.py b/src/Mod/Draft/draftobjects/bspline.py index 56c8ef6feb..41292dc8d1 100644 --- a/src/Mod/Draft/draftobjects/bspline.py +++ b/src/Mod/Draft/draftobjects/bspline.py @@ -41,20 +41,17 @@ class BSpline(DraftObject): def __init__(self, obj): super().__init__(obj, "BSpline") - _tip = QT_TRANSLATE_NOOP("App::Property", - "The points of the B-spline") - obj.addProperty("App::PropertyVectorList","Points", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The points of the B-spline") + obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "If the B-spline is closed or not") - obj.addProperty("App::PropertyBool","Closed", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "If the B-spline is closed or not") + obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Create a face if this B-spline is closed") - obj.addProperty("App::PropertyBool","MakeFace", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this B-spline is closed") + obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) _tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object") - obj.addProperty("App::PropertyArea","Area", "Draft", _tip, locked=True) + obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") obj.Closed = False @@ -63,28 +60,26 @@ class BSpline(DraftObject): def onDocumentRestored(self, obj): super().onDocumentRestored(obj) - gui_utils.restore_view_object( - obj, vp_module="view_bspline", vp_class="ViewProviderBSpline" - ) + gui_utils.restore_view_object(obj, vp_module="view_bspline", vp_class="ViewProviderBSpline") - def assureProperties(self, obj): # for Compatibility with older versions + def assureProperties(self, obj): # for Compatibility with older versions if not hasattr(obj, "Parameterization"): - _tip = QT_TRANSLATE_NOOP("App::Property","Parameterization factor") + _tip = QT_TRANSLATE_NOOP("App::Property", "Parameterization factor") obj.addProperty("App::PropertyFloat", "Parameterization", "Draft", _tip, locked=True) obj.Parameterization = 1.0 self.knotSeq = [] - def parameterization (self, pts, a, closed): + def parameterization(self, pts, a, closed): """Computes a knot Sequence for a set of points. fac (0-1) : parameterization factor fac = 0 -> Uniform / fac=0.5 -> Centripetal / fac=1.0 -> Chord-Length """ - if closed: # we need to add the first point as the end point + if closed: # we need to add the first point as the end point pts.append(pts[0]) params = [0] - for i in range(1,len(pts)): - p = pts[i].sub(pts[i-1]) - pl = pow(p.Length,a) + for i in range(1, len(pts)): + p = pts[i].sub(pts[i - 1]) + pl = pow(p.Length, a) params.append(params[-1] + pl) return params @@ -92,14 +87,13 @@ class BSpline(DraftObject): self.props_changed_store(prop) if prop == "Parameterization": - if fp.Parameterization < 0.: - fp.Parameterization = 0. + if fp.Parameterization < 0.0: + fp.Parameterization = 0.0 if fp.Parameterization > 1.0: fp.Parameterization = 1.0 def execute(self, obj): - if self.props_changed_placement_only() \ - or not obj.Points: + if self.props_changed_placement_only() or not obj.Points: obj.positionBySupport() self.props_changed_clear() return @@ -112,18 +106,21 @@ class BSpline(DraftObject): plm = obj.Placement if obj.Closed and (len(obj.Points) > 2): if obj.Points[0] == obj.Points[-1]: # should not occur, but OCC will crash - _err = QT_TRANSLATE_NOOP('Draft', "_BSpline.createGeometry: " - "Closed with same first/last Point. Geometry not updated.") - App.Console.PrintError(_err+"\n") + _err = QT_TRANSLATE_NOOP( + "Draft", + "_BSpline.createGeometry: " + "Closed with same first/last Point. Geometry not updated.", + ) + App.Console.PrintError(_err + "\n") return spline = Part.BSplineCurve() - spline.interpolate(obj.Points, PeriodicFlag = True, Parameters = self.knotSeq) + spline.interpolate(obj.Points, PeriodicFlag=True, Parameters=self.knotSeq) # DNC: bug fix: convert to face if closed shape = Part.Wire(spline.toShape()) # Creating a face from a closed spline cannot be expected to always work # Usually, if the spline is not flat the call of Part.Face() fails try: - if hasattr(obj,"MakeFace"): + if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: @@ -131,14 +128,14 @@ class BSpline(DraftObject): except Part.OCCError: pass obj.Shape = shape - if hasattr(obj,"Area") and hasattr(shape,"Area"): + if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area else: spline = Part.BSplineCurve() - spline.interpolate(obj.Points, PeriodicFlag = False, Parameters = self.knotSeq) + spline.interpolate(obj.Points, PeriodicFlag=False, Parameters=self.knotSeq) shape = spline.toShape() obj.Shape = shape - if hasattr(obj,"Area") and hasattr(shape,"Area"): + if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport() diff --git a/src/Mod/Draft/draftobjects/circle.py b/src/Mod/Draft/draftobjects/circle.py index ec4e0c54e1..65c4183519 100644 --- a/src/Mod/Draft/draftobjects/circle.py +++ b/src/Mod/Draft/draftobjects/circle.py @@ -42,25 +42,23 @@ class Circle(DraftObject): super().__init__(obj, "Circle") _tip = QT_TRANSLATE_NOOP("App::Property", "Start angle of the arc") - obj.addProperty("App::PropertyAngle", "FirstAngle", - "Draft", _tip, locked=True) + obj.addProperty("App::PropertyAngle", "FirstAngle", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", "End angle of the arc (for a full circle, \ - give it same value as First Angle)") - obj.addProperty("App::PropertyAngle","LastAngle", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "End angle of the arc (for a full circle, \ + give it same value as First Angle)", + ) + obj.addProperty("App::PropertyAngle", "LastAngle", "Draft", _tip, locked=True) _tip = QT_TRANSLATE_NOOP("App::Property", "Radius of the circle") - obj.addProperty("App::PropertyLength", "Radius", - "Draft", _tip, locked=True) + obj.addProperty("App::PropertyLength", "Radius", "Draft", _tip, locked=True) _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face") - obj.addProperty("App::PropertyBool", "MakeFace", - "Draft", _tip, locked=True) + obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) _tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object") - obj.addProperty("App::PropertyArea", "Area", - "Draft", _tip, locked=True) + obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") @@ -79,20 +77,22 @@ class Circle(DraftObject): plm = obj.Placement - shape = Part.makeCircle(obj.Radius.Value, - App.Vector(0,0,0), - App.Vector(0,0,1), - obj.FirstAngle.Value, - obj.LastAngle.Value) + shape = Part.makeCircle( + obj.Radius.Value, + App.Vector(0, 0, 0), + App.Vector(0, 0, 1), + obj.FirstAngle.Value, + obj.LastAngle.Value, + ) if obj.FirstAngle.Value == obj.LastAngle.Value: shape = Part.Wire(shape) - if getattr(obj,"MakeFace",True): + if getattr(obj, "MakeFace", True): shape = Part.Face(shape) obj.Shape = shape - if hasattr(obj,"Area") and hasattr(shape,"Area"): + if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area obj.Placement = plm diff --git a/src/Mod/Draft/draftobjects/clone.py b/src/Mod/Draft/draftobjects/clone.py index af1b65b474..6858f6f83a 100644 --- a/src/Mod/Draft/draftobjects/clone.py +++ b/src/Mod/Draft/draftobjects/clone.py @@ -43,7 +43,6 @@ class Clone(DraftObject): self.set_properties(obj) super().__init__(obj, "Clone") - def set_properties(self, obj): pl = obj.PropertiesList if not "Objects" in pl: @@ -54,9 +53,10 @@ class Clone(DraftObject): obj.addProperty("App::PropertyVector", "Scale", "Draft", _tip, locked=True) obj.Scale = App.Vector(1, 1, 1) if not "Fuse" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If Clones includes several objects,\n" - "set True for fusion or False for compound") + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If Clones includes several objects,\n" "set True for fusion or False for compound", + ) obj.addProperty("App::PropertyBool", "Fuse", "Draft", _tip, locked=True) if not "ForceCompound" in pl: _tip = QT_TRANSLATE_NOOP("App::Property", "Always create a compound") @@ -88,6 +88,7 @@ class Clone(DraftObject): tmps += s.Edges shapes = tmps import Part + if len(shapes) == 1: if force_compound: return Part.makeCompound([shapes[0]]) @@ -106,21 +107,24 @@ class Clone(DraftObject): return sh return Part.makeCompound(shapes) - def execute(self,obj): + def execute(self, obj): if self.props_changed_placement_only(obj): - if hasattr(obj,"positionBySupport"): + if hasattr(obj, "positionBySupport"): obj.positionBySupport() self.props_changed_clear() return import Part + pl = obj.Placement shapes = [] if obj.isDerivedFrom("Part::Part2DObject"): # if our clone is 2D, make sure all its linked geometry is 2D too for o in obj.Objects: if not o.getLinkedObject(True).isDerivedFrom("Part::Part2DObject"): - App.Console.PrintWarning("Warning 2D Clone "+obj.Name+" contains 3D geometry") + App.Console.PrintWarning( + "Warning 2D Clone " + obj.Name + " contains 3D geometry" + ) return for o in obj.Objects: sh = Part.getShape(o) @@ -129,7 +133,7 @@ class Clone(DraftObject): if shapes: sh = self.join(obj, shapes) m = App.Matrix() - if hasattr(obj,"Scale") and not sh.isNull(): + if hasattr(obj, "Scale") and not sh.isNull(): if not DraftVecUtils.equals(obj.Scale, App.Vector(1, 1, 1)): op = sh.Placement sh.Placement = App.Placement() @@ -139,17 +143,17 @@ class Clone(DraftObject): obj.Shape = sh obj.Placement = pl - if hasattr(obj,"positionBySupport"): + if hasattr(obj, "positionBySupport"): obj.positionBySupport() self.props_changed_clear() def onChanged(self, obj, prop): self.props_changed_store(prop) - def getSubVolume(self,obj,placement=None): + def getSubVolume(self, obj, placement=None): # this allows clones of arch windows to return a subvolume too if obj.Objects: - if hasattr(obj.Objects[0],"Proxy"): + if hasattr(obj.Objects[0], "Proxy"): if hasattr(obj.Objects[0].Proxy, "getSubVolume"): if not placement: # clones must displace the original subvolume too diff --git a/src/Mod/Draft/draftobjects/dimension.py b/src/Mod/Draft/draftobjects/dimension.py index ecc56ede10..7177ed5a39 100644 --- a/src/Mod/Draft/draftobjects/dimension.py +++ b/src/Mod/Draft/draftobjects/dimension.py @@ -1,4 +1,4 @@ -# +# # *************************************************************************** # * Copyright (c) 2009, 2010 Yorik van Havre * # * Copyright (c) 2009, 2010 Ken Cline * @@ -128,69 +128,60 @@ class DimensionBase(DraftAnnotation): properties = obj.PropertiesList if "Normal" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The normal direction of the text " - "of the dimension") - obj.addProperty("App::PropertyVector", - "Normal", - "Dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The normal direction of the text " "of the dimension" + ) + obj.addProperty("App::PropertyVector", "Normal", "Dimension", _tip, locked=True) obj.Normal = App.Vector(0, 0, 1) # TODO: remove Support property as it is not used at all. # It is just set at creation time by the make_dimension function # but it is not used. if "Support" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The object measured by this dimension") - obj.addProperty("App::PropertyLink", - "Support", - "Dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The object measured by this dimension") + obj.addProperty("App::PropertyLink", "Support", "Dimension", _tip, locked=True) obj.Support = None if "LinkedGeometry" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The object, and specific subelements " - "of it,\n" - "that this dimension " - "is measuring.\n" - "\n" - "There are various possibilities:\n" - "- An object, and one of its edges.\n" - "- An object, and two of its vertices.\n" - "- An arc object, and its edge.") - obj.addProperty("App::PropertyLinkSubList", - "LinkedGeometry", - "Dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The object, and specific subelements " + "of it,\n" + "that this dimension " + "is measuring.\n" + "\n" + "There are various possibilities:\n" + "- An object, and one of its edges.\n" + "- An object, and two of its vertices.\n" + "- An arc object, and its edge.", + ) + obj.addProperty( + "App::PropertyLinkSubList", "LinkedGeometry", "Dimension", _tip, locked=True + ) obj.LinkedGeometry = [] if "Dimline" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "A point through which the dimension " - "line, or an extrapolation of it, " - "will pass.\n" - "\n" - "- For linear dimensions, this property " - "controls how close the dimension line\n" - "is to the measured object.\n" - "- For radial dimensions, this controls " - "the direction of the dimension line\n" - "that displays the measured radius or " - "diameter.\n" - "- For angular dimensions, " - "this controls the radius of the " - "dimension arc\n" - "that displays the measured angle.") - obj.addProperty("App::PropertyVectorDistance", - "Dimline", - "Dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "A point through which the dimension " + "line, or an extrapolation of it, " + "will pass.\n" + "\n" + "- For linear dimensions, this property " + "controls how close the dimension line\n" + "is to the measured object.\n" + "- For radial dimensions, this controls " + "the direction of the dimension line\n" + "that displays the measured radius or " + "diameter.\n" + "- For angular dimensions, " + "this controls the radius of the " + "dimension arc\n" + "that displays the measured angle.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "Dimline", "Dimension", _tip, locked=True + ) obj.Dimline = App.Vector(0, 1, 0) def update_properties_0v21(self, obj, vobj): @@ -223,77 +214,75 @@ class LinearDimension(DimensionBase): properties = obj.PropertiesList if "Start" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Starting point of the dimension line.\n" - "\n" - "If it is a radius dimension it will be " - "the center of the arc.\n" - "If it is a diameter dimension " - "it will be a point that lies " - "on the arc.") - obj.addProperty("App::PropertyVectorDistance", - "Start", - "Linear/radial dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Starting point of the dimension line.\n" + "\n" + "If it is a radius dimension it will be " + "the center of the arc.\n" + "If it is a diameter dimension " + "it will be a point that lies " + "on the arc.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "Start", "Linear/radial dimension", _tip, locked=True + ) obj.Start = App.Vector(0, 0, 0) if "End" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Ending point of the dimension line.\n" - "\n" - "If it is a radius or diameter " - "dimension\n" - "it will be a point that lies " - "on the arc.") - obj.addProperty("App::PropertyVectorDistance", - "End", - "Linear/radial dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Ending point of the dimension line.\n" + "\n" + "If it is a radius or diameter " + "dimension\n" + "it will be a point that lies " + "on the arc.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "End", "Linear/radial dimension", _tip, locked=True + ) obj.End = App.Vector(1, 0, 0) if "Direction" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The direction of the dimension line.\n" - "If this remains '(0,0,0)', " - "the direction will be calculated " - "automatically.") - obj.addProperty("App::PropertyVector", - "Direction", - "Linear/radial dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The direction of the dimension line.\n" + "If this remains '(0,0,0)', " + "the direction will be calculated " + "automatically.", + ) + obj.addProperty( + "App::PropertyVector", "Direction", "Linear/radial dimension", _tip, locked=True + ) if "Distance" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The value of the measurement.\n" - "\n" - "This property is read-only because " - "the value is calculated\n" - "from the 'Start' and 'End' properties.\n" - "\n" - "If the 'Linked Geometry' " - "is an arc or circle, this 'Distance'\n" - "is the radius or diameter, depending " - "on the 'Diameter' property.") - obj.addProperty("App::PropertyLength", - "Distance", - "Linear/radial dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The value of the measurement.\n" + "\n" + "This property is read-only because " + "the value is calculated\n" + "from the 'Start' and 'End' properties.\n" + "\n" + "If the 'Linked Geometry' " + "is an arc or circle, this 'Distance'\n" + "is the radius or diameter, depending " + "on the 'Diameter' property.", + ) + obj.addProperty( + "App::PropertyLength", "Distance", "Linear/radial dimension", _tip, locked=True + ) obj.Distance = 0 if "Diameter" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "When measuring circular arcs, " - "it determines whether to display\n" - "the radius or the diameter value") - obj.addProperty("App::PropertyBool", - "Diameter", - "Radial dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "When measuring circular arcs, " + "it determines whether to display\n" + "the radius or the diameter value", + ) + obj.addProperty("App::PropertyBool", "Diameter", "Radial dimension", _tip, locked=True) obj.Diameter = False def onDocumentRestored(self, obj): @@ -320,12 +309,12 @@ class LinearDimension(DimensionBase): as they aren't used. """ if hasattr(obj, "Distance"): - obj.setPropertyStatus('Distance', 'ReadOnly') + obj.setPropertyStatus("Distance", "ReadOnly") # if hasattr(obj, "Normal"): # obj.setPropertyStatus('Normal', 'Hidden') if hasattr(obj, "Support"): - obj.setPropertyStatus('Support', 'Hidden') + obj.setPropertyStatus("Support", "Hidden") def transform(self, obj, pla): """Transform the object by applying a placement.""" @@ -353,24 +342,20 @@ class LinearDimension(DimensionBase): # If it has one subelement, we assume an edge # that can be a straight line, or a circular edge subelement = sub_list[0] - (obj.Start, - obj.End) = measure_one_obj_edge(linked_obj, - subelement, - obj.Dimline, - obj.Diameter) + (obj.Start, obj.End) = measure_one_obj_edge( + linked_obj, subelement, obj.Dimline, obj.Diameter + ) elif len(sub_list) == 2: # If it has two subelements, we assume a straight edge # that is measured by two vertices - (obj.Start, - obj.End) = measure_one_obj_vertices(linked_obj, - sub_list) + (obj.Start, obj.End) = measure_one_obj_vertices(linked_obj, sub_list) elif len(obj.LinkedGeometry) == 2: # If the list has two objects, it measures the distance # between the two vertices in those two objects - (obj.Start, - obj.End) = measure_two_objects(obj.LinkedGeometry[0], - obj.LinkedGeometry[1]) + (obj.Start, obj.End) = measure_two_objects( + obj.LinkedGeometry[0], obj.LinkedGeometry[1] + ) # Update the distance property by comparing the floats # with the precision @@ -521,58 +506,56 @@ class AngularDimension(DimensionBase): properties = obj.PropertiesList if "FirstAngle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Starting angle of the dimension line " - "(circular arc).\n" - "The arc is drawn counter-clockwise.") - obj.addProperty("App::PropertyAngle", - "FirstAngle", - "Angular dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Starting angle of the dimension line " + "(circular arc).\n" + "The arc is drawn counter-clockwise.", + ) + obj.addProperty( + "App::PropertyAngle", "FirstAngle", "Angular dimension", _tip, locked=True + ) obj.FirstAngle = 0 if "LastAngle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Ending angle of the dimension line " - "(circular arc).\n" - "The arc is drawn counter-clockwise.") - obj.addProperty("App::PropertyAngle", - "LastAngle", - "Angular dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Ending angle of the dimension line " + "(circular arc).\n" + "The arc is drawn counter-clockwise.", + ) + obj.addProperty( + "App::PropertyAngle", "LastAngle", "Angular dimension", _tip, locked=True + ) obj.LastAngle = 90 if "Center" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The center point of the dimension " - "line, which is a circular arc.\n" - "\n" - "This is normally the point where two " - "line segments, or their extensions\n" - "intersect, resulting in the " - "measured 'Angle' between them.") - obj.addProperty("App::PropertyVectorDistance", - "Center", - "Angular dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The center point of the dimension " + "line, which is a circular arc.\n" + "\n" + "This is normally the point where two " + "line segments, or their extensions\n" + "intersect, resulting in the " + "measured 'Angle' between them.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "Center", "Angular dimension", _tip, locked=True + ) obj.Center = App.Vector(0, 0, 0) if "Angle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The value of the measurement.\n" - "\n" - "This property is read-only because " - "the value is calculated from\n" - "the 'First Angle' and " - "'Last Angle' properties.") - obj.addProperty("App::PropertyAngle", - "Angle", - "Angular dimension", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The value of the measurement.\n" + "\n" + "This property is read-only because " + "the value is calculated from\n" + "the 'First Angle' and " + "'Last Angle' properties.", + ) + obj.addProperty("App::PropertyAngle", "Angle", "Angular dimension", _tip, locked=True) obj.Angle = 0 def onDocumentRestored(self, obj): @@ -644,14 +627,14 @@ class AngularDimension(DimensionBase): as they aren't used. """ if hasattr(obj, "Angle"): - obj.setPropertyStatus('Angle', 'ReadOnly') + obj.setPropertyStatus("Angle", "ReadOnly") if hasattr(obj, "Normal"): - obj.setPropertyStatus('Normal', 'Hidden') + obj.setPropertyStatus("Normal", "Hidden") if hasattr(obj, "Support"): - obj.setPropertyStatus('Support', 'Hidden') + obj.setPropertyStatus("Support", "Hidden") if hasattr(obj, "LinkedGeometry"): - obj.setPropertyStatus('LinkedGeometry', 'Hidden') + obj.setPropertyStatus("LinkedGeometry", "Hidden") def measure_two_obj_angles(link_sub_1, link_sub_2): diff --git a/src/Mod/Draft/draftobjects/draft_annotation.py b/src/Mod/Draft/draftobjects/draft_annotation.py index cbd7e621b5..849c6745e2 100644 --- a/src/Mod/Draft/draftobjects/draft_annotation.py +++ b/src/Mod/Draft/draftobjects/draft_annotation.py @@ -92,9 +92,7 @@ class DraftAnnotation(object): typ = obj.Proxy.Type if typ == "Label": vobj.ArrowTypeStart = vobj.ArrowType - elif typ == "AngularDimension" \ - or obj.Diameter \ - or not vobj.Proxy.is_linked_to_circle(): + elif typ == "AngularDimension" or obj.Diameter or not vobj.Proxy.is_linked_to_circle(): vobj.ArrowTypeStart = vobj.ArrowType vobj.ArrowTypeEnd = vobj.ArrowType else: # Radial dimension @@ -115,7 +113,7 @@ class DraftAnnotation(object): return - def loads(self,state): + def loads(self, state): return diff --git a/src/Mod/Draft/draftobjects/draftlink.py b/src/Mod/Draft/draftobjects/draftlink.py index 3d86fa578b..ab9eee10da 100644 --- a/src/Mod/Draft/draftobjects/draftlink.py +++ b/src/Mod/Draft/draftobjects/draftlink.py @@ -80,7 +80,7 @@ class DraftLink(DraftObject): def attach(self, obj): """Set up the properties when the object is attached.""" if self.use_link: - obj.addExtension('App::LinkExtensionPython') + obj.addExtension("App::LinkExtensionPython") self.linkSetup(obj) def canLinkProperties(self, _obj): @@ -92,68 +92,55 @@ class DraftLink(DraftObject): def linkSetup(self, obj): """Set up the link properties on attachment.""" - obj.configLinkProperty('Placement', LinkedObject='Base') + obj.configLinkProperty("Placement", LinkedObject="Base") - if not hasattr(obj, 'AlwaysSyncPlacement'): - _tip = QT_TRANSLATE_NOOP("App::Property", - 'Force sync pattern placements even when array elements are expanded') - obj.addProperty("App::PropertyBool", - "AlwaysSyncPlacement", - "Draft", - _tip, - locked=True) + if not hasattr(obj, "AlwaysSyncPlacement"): + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Force sync pattern placements even when array elements are expanded", + ) + obj.addProperty("App::PropertyBool", "AlwaysSyncPlacement", "Draft", _tip, locked=True) - if hasattr(obj, 'ShowElement'): + if hasattr(obj, "ShowElement"): # Rename 'ShowElement' property to 'ExpandArray' to avoid conflict # with native App::Link - obj.configLinkProperty('ShowElement') + obj.configLinkProperty("ShowElement") showElement = obj.ShowElement - _tip = QT_TRANSLATE_NOOP("App::Property", - "Show the individual array elements") - obj.addProperty("App::PropertyBool", - "ExpandArray", - "Draft", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Show the individual array elements") + obj.addProperty("App::PropertyBool", "ExpandArray", "Draft", _tip, locked=True) obj.ExpandArray = showElement - obj.configLinkProperty(ShowElement='ExpandArray') - obj.removeProperty('ShowElement') + obj.configLinkProperty(ShowElement="ExpandArray") + obj.removeProperty("ShowElement") else: - obj.configLinkProperty(ShowElement='ExpandArray') + obj.configLinkProperty(ShowElement="ExpandArray") - if getattr(obj, 'ExpandArray', False): - obj.setPropertyStatus('PlacementList', 'Immutable') + if getattr(obj, "ExpandArray", False): + obj.setPropertyStatus("PlacementList", "Immutable") else: - obj.setPropertyStatus('PlacementList', '-Immutable') + obj.setPropertyStatus("PlacementList", "-Immutable") - if not hasattr(obj, 'LinkTransform'): - obj.addProperty('App::PropertyBool', - 'LinkTransform', - ' Link', - locked=True) + if not hasattr(obj, "LinkTransform"): + obj.addProperty("App::PropertyBool", "LinkTransform", " Link", locked=True) - if not hasattr(obj, 'ColoredElements'): - obj.addProperty('App::PropertyLinkSubHidden', - 'ColoredElements', - ' Link', - locked=True) - obj.setPropertyStatus('ColoredElements', 'Hidden') + if not hasattr(obj, "ColoredElements"): + obj.addProperty("App::PropertyLinkSubHidden", "ColoredElements", " Link", locked=True) + obj.setPropertyStatus("ColoredElements", "Hidden") - if not hasattr(obj,'LinkCopyOnChange'): - obj.addProperty("App::PropertyEnumeration","LinkCopyOnChange"," Link",locked=True) + if not hasattr(obj, "LinkCopyOnChange"): + obj.addProperty("App::PropertyEnumeration", "LinkCopyOnChange", " Link", locked=True) - obj.configLinkProperty('LinkCopyOnChange','LinkTransform','ColoredElements') + obj.configLinkProperty("LinkCopyOnChange", "LinkTransform", "ColoredElements") - if not getattr(obj, 'Fuse', False): - obj.setPropertyStatus('Shape', 'Transient') + if not getattr(obj, "Fuse", False): + obj.setPropertyStatus("Shape", "Transient") def getViewProviderName(self, _obj): """Override the view provider name.""" if self.use_link: - return 'Gui::ViewProviderLinkPython' - return '' + return "Gui::ViewProviderLinkPython" + return "" def migrate_attributes(self, obj): """Migrate old attribute names to new names if they exist. @@ -177,10 +164,10 @@ class DraftLink(DraftObject): if self.use_link: self.linkSetup(obj) else: - obj.setPropertyStatus('Shape', '-Transient') + obj.setPropertyStatus("Shape", "-Transient") if obj.Shape.isNull(): - if getattr(obj, 'PlacementList', None): + if getattr(obj, "PlacementList", None): self.buildShape(obj, obj.Placement, obj.PlacementList) else: self.execute(obj) @@ -198,14 +185,13 @@ class DraftLink(DraftObject): def buildShape(self, obj, pl, pls): """Build the shape of the link object.""" if self.use_link: - if not getattr(obj, 'ExpandArray', False) or obj.Count != len(pls): - obj.setPropertyStatus('PlacementList', '-Immutable') + if not getattr(obj, "ExpandArray", False) or obj.Count != len(pls): + obj.setPropertyStatus("PlacementList", "-Immutable") obj.PlacementList = pls - obj.setPropertyStatus('PlacementList', 'Immutable') + obj.setPropertyStatus("PlacementList", "Immutable") obj.Count = len(pls) - if getattr(obj, 'ExpandArray', False) \ - and getattr(obj, 'AlwaysSyncPlacement', False): - for pla,child in zip(pls,obj.ElementList): + if getattr(obj, "ExpandArray", False) and getattr(obj, "AlwaysSyncPlacement", False): + for pla, child in zip(pls, obj.ElementList): child.Placement = pla else: obj.PlacementList = pls @@ -213,12 +199,13 @@ class DraftLink(DraftObject): obj.Count = len(pls) if obj.Base: - shape = getattr(obj.Base, 'Shape', None) + shape = getattr(obj.Base, "Shape", None) if not isinstance(shape, Part.Shape): obj.Shape = Part.Shape() elif shape.isNull(): - _err_msg = ("'{}' cannot build shape " - "from '{}'\n".format(obj.Label, obj.Base.Label)) + _err_msg = "'{}' cannot build shape " "from '{}'\n".format( + obj.Label, obj.Base.Label + ) raise RuntimeError(_err_msg) else: # Resetting the Placement of the copied shape does not work for @@ -228,13 +215,13 @@ class DraftLink(DraftObject): shape.transformShape(place.Matrix.inverse()) base = [] for i, pla in enumerate(pls): - vis = getattr(obj, 'VisibilityList', []) + vis = getattr(obj, "VisibilityList", []) if len(vis) > i and not vis[i]: continue base.append(shape.transformed(pla.toMatrix())) - if getattr(obj, 'Fuse', False) and len(base) > 1: + if getattr(obj, "Fuse", False) and len(base) > 1: obj.Shape = base[0].multiFuse(base[1:]).removeSplitter() else: obj.Shape = Part.makeCompound(base) @@ -249,20 +236,20 @@ class DraftLink(DraftObject): """Execute when a property changes.""" self.props_changed_store(prop) - if not getattr(self, 'use_link', False): + if not getattr(self, "use_link", False): return - if prop == 'Fuse': + if prop == "Fuse": if obj.Fuse: - obj.setPropertyStatus('Shape', '-Transient') + obj.setPropertyStatus("Shape", "-Transient") else: - obj.setPropertyStatus('Shape', 'Transient') - elif prop == 'ExpandArray': - if hasattr(obj, 'PlacementList'): + obj.setPropertyStatus("Shape", "Transient") + elif prop == "ExpandArray": + if hasattr(obj, "PlacementList"): if obj.ExpandArray: - obj.setPropertyStatus('PlacementList', '-Immutable') + obj.setPropertyStatus("PlacementList", "-Immutable") else: - obj.setPropertyStatus('PlacementList', 'Immutable') + obj.setPropertyStatus("PlacementList", "Immutable") # Alias for compatibility with old versions of v0.19 diff --git a/src/Mod/Draft/draftobjects/ellipse.py b/src/Mod/Draft/draftobjects/ellipse.py index e8e31d224e..b413793380 100644 --- a/src/Mod/Draft/draftobjects/ellipse.py +++ b/src/Mod/Draft/draftobjects/ellipse.py @@ -41,24 +41,27 @@ class Ellipse(DraftObject): def __init__(self, obj): super().__init__(obj, "Ellipse") - _tip = QT_TRANSLATE_NOOP("App::Property","Start angle of the elliptical arc") + _tip = QT_TRANSLATE_NOOP("App::Property", "Start angle of the elliptical arc") obj.addProperty("App::PropertyAngle", "FirstAngle", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","End angle of the elliptical arc \n\ - (for a full circle, give it same value as First Angle)") + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "End angle of the elliptical arc \n\ + (for a full circle, give it same value as First Angle)", + ) obj.addProperty("App::PropertyAngle", "LastAngle", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","Minor radius of the ellipse") + _tip = QT_TRANSLATE_NOOP("App::Property", "Minor radius of the ellipse") obj.addProperty("App::PropertyLength", "MinorRadius", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","Major radius of the ellipse") + _tip = QT_TRANSLATE_NOOP("App::Property", "Major radius of the ellipse") obj.addProperty("App::PropertyLength", "MajorRadius", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","Create a face") + _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face") obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","Area of this object") - obj.addProperty("App::PropertyArea", "Area","Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Area of this object") + obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") @@ -73,24 +76,23 @@ class Ellipse(DraftObject): return import Part + plm = obj.Placement if obj.MajorRadius.Value < obj.MinorRadius.Value: _err = "Error: Major radius is smaller than the minor radius" App.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft", _err)) return if obj.MajorRadius.Value and obj.MinorRadius.Value: - ell = Part.Ellipse(App.Vector(0, 0, 0), - obj.MajorRadius.Value, - obj.MinorRadius.Value) + ell = Part.Ellipse(App.Vector(0, 0, 0), obj.MajorRadius.Value, obj.MinorRadius.Value) shape = ell.toShape() - if hasattr(obj,"FirstAngle"): + if hasattr(obj, "FirstAngle"): if obj.FirstAngle.Value != obj.LastAngle.Value: a1 = obj.FirstAngle.getValueAs(App.Units.Radian) a2 = obj.LastAngle.getValueAs(App.Units.Radian) shape = Part.ArcOfEllipse(ell, a1, a2).toShape() shape = Part.Wire(shape) if shape.isClosed(): - if hasattr(obj,"MakeFace"): + if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: diff --git a/src/Mod/Draft/draftobjects/facebinder.py b/src/Mod/Draft/draftobjects/facebinder.py index 09562c9f4c..d3d647d054 100644 --- a/src/Mod/Draft/draftobjects/facebinder.py +++ b/src/Mod/Draft/draftobjects/facebinder.py @@ -40,26 +40,31 @@ from draftutils.translate import translate class Facebinder(DraftObject): """The Draft Facebinder object""" - def __init__(self,obj): + + def __init__(self, obj): super().__init__(obj, "Facebinder") - _tip = QT_TRANSLATE_NOOP("App::Property","Linked faces") + _tip = QT_TRANSLATE_NOOP("App::Property", "Linked faces") obj.addProperty("App::PropertyLinkSubList", "Faces", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","Specifies if splitter lines must be removed") - obj.addProperty("App::PropertyBool","RemoveSplitter", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Specifies if splitter lines must be removed") + obj.addProperty("App::PropertyBool", "RemoveSplitter", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","An optional extrusion value to be applied to all faces") - obj.addProperty("App::PropertyDistance","Extrusion", "Draft" , _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "An optional extrusion value to be applied to all faces" + ) + obj.addProperty("App::PropertyDistance", "Extrusion", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","An optional offset value to be applied to all faces") - obj.addProperty("App::PropertyDistance","Offset", "Draft" , _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "An optional offset value to be applied to all faces" + ) + obj.addProperty("App::PropertyDistance", "Offset", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","This specifies if the shapes sew") - obj.addProperty("App::PropertyBool","Sew", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "This specifies if the shapes sew") + obj.addProperty("App::PropertyBool", "Sew", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property","The area of the faces of this Facebinder") - obj.addProperty("App::PropertyArea","Area", "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The area of the faces of this Facebinder") + obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.setEditorMode("Area", 1) def onDocumentRestored(self, obj): @@ -78,6 +83,7 @@ class Facebinder(DraftObject): return import Part + faces = [] try: for sel in obj.Faces: @@ -131,11 +137,16 @@ class Facebinder(DraftObject): _wrn(obj.Label + ": " + translate("draft", "No valid faces for facebinder")) def _report_sew_error(self, obj): - _wrn(obj.Label + ": " + translate("draft", "Unable to build facebinder, resuming with sew disabled")) + _wrn( + obj.Label + + ": " + + translate("draft", "Unable to build facebinder, resuming with sew disabled") + ) def _build_shape(self, obj, faces, sew=False): """returns the built shape and the area of the offset faces""" import Part + offs_val = getattr(obj, "Offset", 0) extr_val = getattr(obj, "Extrusion", 0) @@ -175,6 +186,7 @@ class Facebinder(DraftObject): def _convert_to_planar(self, obj, shp): """convert flat B-spline faces to planar faces if possible""" import Part + faces = [] for face in shp.Faces: if face.Surface.TypeId == "Part::GeomPlane": @@ -196,9 +208,13 @@ class Facebinder(DraftObject): solid = Part.makeSolid(Part.makeShell(faces)) if solid.isValid(): return solid - _msg(obj.Label + ": " + translate("draft", - "Converting flat B-spline faces of facebinder to planar faces failed" - )) + _msg( + obj.Label + + ": " + + translate( + "draft", "Converting flat B-spline faces of facebinder to planar faces failed" + ) + ) return shp def onChanged(self, obj, prop): diff --git a/src/Mod/Draft/draftobjects/fillet.py b/src/Mod/Draft/draftobjects/fillet.py index 5cb9ccdf97..4e5e3c2631 100644 --- a/src/Mod/Draft/draftobjects/fillet.py +++ b/src/Mod/Draft/draftobjects/fillet.py @@ -47,38 +47,22 @@ class Fillet(DraftObject): """Set the properties of objects if they don't exist.""" if not hasattr(obj, "Start"): _tip = QT_TRANSLATE_NOOP("App::Property", "The start point of this line.") - obj.addProperty("App::PropertyVectorDistance", - "Start", - "Draft", - _tip, - locked=True) + obj.addProperty("App::PropertyVectorDistance", "Start", "Draft", _tip, locked=True) obj.Start = App.Vector(0, 0, 0) if not hasattr(obj, "End"): _tip = QT_TRANSLATE_NOOP("App::Property", "The end point of this line.") - obj.addProperty("App::PropertyVectorDistance", - "End", - "Draft", - _tip, - locked=True) + obj.addProperty("App::PropertyVectorDistance", "End", "Draft", _tip, locked=True) obj.End = App.Vector(0, 0, 0) if not hasattr(obj, "Length"): _tip = QT_TRANSLATE_NOOP("App::Property", "The length of this line.") - obj.addProperty("App::PropertyLength", - "Length", - "Draft", - _tip, - locked=True) + obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True) obj.Length = 0 if not hasattr(obj, "FilletRadius"): _tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corner.") - obj.addProperty("App::PropertyLength", - "FilletRadius", - "Draft", - _tip, - locked=True) + obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True) obj.FilletRadius = 0 # TODO: these two properties should link two straight lines @@ -117,7 +101,7 @@ class Fillet(DraftObject): obj.End = obj.Shape.Vertexes[-1].Point def _update_radius(self, obj, radius): - #if (hasattr(obj, "Line1") and hasattr(obj, "Line2") + # if (hasattr(obj, "Line1") and hasattr(obj, "Line2") # and obj.Line1 and obj.Line2): # do the unimplemented work pass @@ -131,4 +115,5 @@ class Fillet(DraftObject): if prop in "FilletRadius": self._update_radius(obj, obj.FilletRadius) + ## @} diff --git a/src/Mod/Draft/draftobjects/hatch.py b/src/Mod/Draft/draftobjects/hatch.py index 5645dd2aeb..933e8e1fb9 100644 --- a/src/Mod/Draft/draftobjects/hatch.py +++ b/src/Mod/Draft/draftobjects/hatch.py @@ -1,24 +1,24 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2021 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * * +# * Copyright (c) 2021 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** """This module contains FreeCAD commands for the Draft workbench""" @@ -36,37 +36,69 @@ from draftutils.translate import translate class Hatch(DraftObject): - - def __init__(self,obj): + def __init__(self, obj): obj.Proxy = self self.Type = "Hatch" self.setProperties(obj) - def setProperties(self,obj): + def setProperties(self, obj): pl = obj.PropertiesList if not "Base" in pl: - obj.addProperty("App::PropertyLink","Base","Hatch", - QT_TRANSLATE_NOOP("App::Property","The base object used by this object"), locked=True) + obj.addProperty( + "App::PropertyLink", + "Base", + "Hatch", + QT_TRANSLATE_NOOP("App::Property", "The base object used by this object"), + locked=True, + ) if not "File" in pl: - obj.addProperty("App::PropertyFile","File","Hatch", - QT_TRANSLATE_NOOP("App::Property","The PAT file used by this object"), locked=True) + obj.addProperty( + "App::PropertyFile", + "File", + "Hatch", + QT_TRANSLATE_NOOP("App::Property", "The PAT file used by this object"), + locked=True, + ) if not "Pattern" in pl: - obj.addProperty("App::PropertyString","Pattern","Hatch", - QT_TRANSLATE_NOOP("App::Property","The pattern name used by this object"), locked=True) + obj.addProperty( + "App::PropertyString", + "Pattern", + "Hatch", + QT_TRANSLATE_NOOP("App::Property", "The pattern name used by this object"), + locked=True, + ) if not "Scale" in pl: - obj.addProperty("App::PropertyFloat","Scale","Hatch", - QT_TRANSLATE_NOOP("App::Property","The pattern scale used by this object"), locked=True) + obj.addProperty( + "App::PropertyFloat", + "Scale", + "Hatch", + QT_TRANSLATE_NOOP("App::Property", "The pattern scale used by this object"), + locked=True, + ) if not "Rotation" in pl: - obj.addProperty("App::PropertyAngle","Rotation","Hatch", - QT_TRANSLATE_NOOP("App::Property","The pattern rotation used by this object"), locked=True) + obj.addProperty( + "App::PropertyAngle", + "Rotation", + "Hatch", + QT_TRANSLATE_NOOP("App::Property", "The pattern rotation used by this object"), + locked=True, + ) if not "Translate" in pl: - obj.addProperty("App::PropertyBool","Translate","Hatch", - QT_TRANSLATE_NOOP("App::Property","If set to False, hatch is applied as is to the faces, without translation (this might give wrong results for non-XY faces)"), locked=True) + obj.addProperty( + "App::PropertyBool", + "Translate", + "Hatch", + QT_TRANSLATE_NOOP( + "App::Property", + "If set to False, hatch is applied as is to the faces, without translation (this might give wrong results for non-XY faces)", + ), + locked=True, + ) obj.Translate = True - def onDocumentRestored(self,obj): + def onDocumentRestored(self, obj): self.setProperties(obj) super().onDocumentRestored(obj) gui_utils.restore_view_object( @@ -79,15 +111,17 @@ class Hatch(DraftObject): def loads(self, state): self.Type = "Hatch" - def execute(self,obj): + def execute(self, obj): - if self.props_changed_placement_only(obj) \ - or not obj.Base \ - or not obj.File \ - or not obj.Pattern \ - or not obj.Scale \ - or not obj.Base.isDerivedFrom("Part::Feature") \ - or not obj.Base.Shape.Faces: + if ( + self.props_changed_placement_only(obj) + or not obj.Base + or not obj.File + or not obj.Pattern + or not obj.Scale + or not obj.Base.isDerivedFrom("Part::Feature") + or not obj.Base.Shape.Faces + ): self.props_changed_clear() return @@ -131,7 +165,7 @@ class Hatch(DraftObject): shapes = [] for face in obj.Base.Shape.Faces: - if face.findPlane(): # Only planar faces. + if face.findPlane(): # Only planar faces. face = face.copy() if obj.Translate: mtx = None @@ -183,8 +217,7 @@ class Hatch(DraftObject): self.props_changed_store(prop) - def getPatterns(self,filename): - + def getPatterns(self, filename): """returns a list of pattern names found in a PAT file""" patterns = [] if os.path.exists(filename): diff --git a/src/Mod/Draft/draftobjects/label.py b/src/Mod/Draft/draftobjects/label.py index 5f843db283..a3b0e868df 100644 --- a/src/Mod/Draft/draftobjects/label.py +++ b/src/Mod/Draft/draftobjects/label.py @@ -58,31 +58,27 @@ class Label(DraftAnnotation): properties = obj.PropertiesList if "TargetPoint" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The position of the tip of the leader " - "line.\n" - "This point can be decorated " - "with an arrow or another symbol.") - obj.addProperty("App::PropertyVector", - "TargetPoint", - "Target", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The position of the tip of the leader " + "line.\n" + "This point can be decorated " + "with an arrow or another symbol.", + ) + obj.addProperty("App::PropertyVector", "TargetPoint", "Target", _tip, locked=True) obj.TargetPoint = App.Vector(2, -1, 0) if "Target" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Object, and optionally subelement, " - "whose properties will be displayed\n" - "as 'Text', depending on 'Label Type'.\n" - "\n" - "'Target' won't be used " - "if 'Label Type' is set to 'Custom'.") - obj.addProperty("App::PropertyLinkSub", - "Target", - "Target", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Object, and optionally subelement, " + "whose properties will be displayed\n" + "as 'Text', depending on 'Label Type'.\n" + "\n" + "'Target' won't be used " + "if 'Label Type' is set to 'Custom'.", + ) + obj.addProperty("App::PropertyLinkSub", "Target", "Target", _tip, locked=True) obj.Target = None def set_leader_properties(self, obj): @@ -90,65 +86,63 @@ class Label(DraftAnnotation): properties = obj.PropertiesList if "Points" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The list of points defining the leader " - "line; normally a list of three points.\n" - "\n" - "The first point should be the position " - "of the text, that is, the 'Placement',\n" - "and the last point should be " - "the tip of the line, that is, " - "the 'Target Point'.\n" - "The middle point is calculated " - "automatically depending on the chosen\n" - "'Straight Direction' " - "and the 'Straight Distance' value " - "and sign.\n" - "\n" - "If 'Straight Direction' is set to " - "'Custom', the 'Points' property\n" - "can be set as a list " - "of arbitrary points.") - obj.addProperty("App::PropertyVectorList", - "Points", - "Leader", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The list of points defining the leader " + "line; normally a list of three points.\n" + "\n" + "The first point should be the position " + "of the text, that is, the 'Placement',\n" + "and the last point should be " + "the tip of the line, that is, " + "the 'Target Point'.\n" + "The middle point is calculated " + "automatically depending on the chosen\n" + "'Straight Direction' " + "and the 'Straight Distance' value " + "and sign.\n" + "\n" + "If 'Straight Direction' is set to " + "'Custom', the 'Points' property\n" + "can be set as a list " + "of arbitrary points.", + ) + obj.addProperty("App::PropertyVectorList", "Points", "Leader", _tip, locked=True) obj.Points = [] if "StraightDirection" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The direction of the straight segment " - "of the leader line.\n" - "\n" - "If 'Custom' is chosen, the points " - "of the leader can be specified by\n" - "assigning a custom list " - "to the 'Points' attribute.") - obj.addProperty("App::PropertyEnumeration", - "StraightDirection", - "Leader", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The direction of the straight segment " + "of the leader line.\n" + "\n" + "If 'Custom' is chosen, the points " + "of the leader can be specified by\n" + "assigning a custom list " + "to the 'Points' attribute.", + ) + obj.addProperty( + "App::PropertyEnumeration", "StraightDirection", "Leader", _tip, locked=True + ) obj.StraightDirection = ["Horizontal", "Vertical", "Custom"] if "StraightDistance" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The length of the straight segment " - "of the leader line.\n" - "\n" - "This is an oriented distance; " - "if it is negative, the line will " - "be drawn\n" - "to the left or below the 'Text', " - "otherwise to the right or above it,\n" - "depending on the value of " - "'Straight Direction'.") - obj.addProperty("App::PropertyDistance", - "StraightDistance", - "Leader", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The length of the straight segment " + "of the leader line.\n" + "\n" + "This is an oriented distance; " + "if it is negative, the line will " + "be drawn\n" + "to the left or below the 'Text', " + "otherwise to the right or above it,\n" + "depending on the value of " + "'Straight Direction'.", + ) + obj.addProperty( + "App::PropertyDistance", "StraightDistance", "Leader", _tip, locked=True + ) obj.StraightDistance = 1 def set_label_properties(self, obj): @@ -156,41 +150,31 @@ class Label(DraftAnnotation): properties = obj.PropertiesList if "Placement" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement of the 'Text' element " - "in 3D space") - obj.addProperty("App::PropertyPlacement", - "Placement", - "Label", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The placement of the 'Text' element " "in 3D space" + ) + obj.addProperty("App::PropertyPlacement", "Placement", "Label", _tip, locked=True) obj.Placement = App.Placement() if "CustomText" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The text to display when 'Label Type' " - "is set to 'Custom'") - obj.addProperty("App::PropertyStringList", - "CustomText", - "Label", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The text to display when 'Label Type' " "is set to 'Custom'" + ) + obj.addProperty("App::PropertyStringList", "CustomText", "Label", _tip, locked=True) obj.CustomText = "Label" if "Text" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The text displayed by this label.\n" - "\n" - "This property is read-only, as the " - "final text depends on 'Label Type',\n" - "and the object defined in 'Target'.\n" - "The 'Custom Text' is displayed only " - "if 'Label Type' is set to 'Custom'.") - obj.addProperty("App::PropertyStringList", - "Text", - "Label", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The text displayed by this label.\n" + "\n" + "This property is read-only, as the " + "final text depends on 'Label Type',\n" + "and the object defined in 'Target'.\n" + "The 'Custom Text' is displayed only " + "if 'Label Type' is set to 'Custom'.", + ) + obj.addProperty("App::PropertyStringList", "Text", "Label", _tip, locked=True) obj.setEditorMode("Text", 1) # Read only # TODO: maybe here we can define a second and third 'label type' @@ -203,30 +187,28 @@ class Label(DraftAnnotation): # This would also require updating the `return_info` function # to handle any combination that we want. if "LabelType" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The type of information displayed " - "by this label.\n" - "\n" - "If 'Custom' is chosen, the contents of " - "'Custom Text' will be used.\n" - "For other types, the string will be " - "calculated automatically from the " - "object defined in 'Target'.\n" - "'Tag' and 'Material' only work " - "for objects that have these properties, " - "like BIM objects.\n" - "\n" - "For 'Position', 'Length', and 'Area' " - "these properties will be extracted " - "from the main object in 'Target',\n" - "or from the subelement " - "'VertexN', 'EdgeN', or 'FaceN', " - "respectively, if it is specified.") - obj.addProperty("App::PropertyEnumeration", - "LabelType", - "Label", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The type of information displayed " + "by this label.\n" + "\n" + "If 'Custom' is chosen, the contents of " + "'Custom Text' will be used.\n" + "For other types, the string will be " + "calculated automatically from the " + "object defined in 'Target'.\n" + "'Tag' and 'Material' only work " + "for objects that have these properties, " + "like BIM objects.\n" + "\n" + "For 'Position', 'Length', and 'Area' " + "these properties will be extracted " + "from the main object in 'Target',\n" + "or from the subelement " + "'VertexN', 'EdgeN', or 'FaceN', " + "respectively, if it is specified.", + ) + obj.addProperty("App::PropertyEnumeration", "LabelType", "Label", _tip, locked=True) obj.LabelType = get_label_types() def onDocumentRestored(self, obj): @@ -327,20 +309,22 @@ DraftLabel = Label def get_label_types(): - return [QT_TRANSLATE_NOOP("Draft","Custom"), - QT_TRANSLATE_NOOP("Draft","Name"), - QT_TRANSLATE_NOOP("Draft","Label"), - QT_TRANSLATE_NOOP("Draft","Position"), - QT_TRANSLATE_NOOP("Draft","Length"), - QT_TRANSLATE_NOOP("Draft","Area"), - QT_TRANSLATE_NOOP("Draft","Volume"), - QT_TRANSLATE_NOOP("Draft","Tag"), - QT_TRANSLATE_NOOP("Draft","Material"), - QT_TRANSLATE_NOOP("Draft","Label + Position"), - QT_TRANSLATE_NOOP("Draft","Label + Length"), - QT_TRANSLATE_NOOP("Draft","Label + Area"), - QT_TRANSLATE_NOOP("Draft","Label + Volume"), - QT_TRANSLATE_NOOP("Draft","Label + Material")] + return [ + QT_TRANSLATE_NOOP("Draft", "Custom"), + QT_TRANSLATE_NOOP("Draft", "Name"), + QT_TRANSLATE_NOOP("Draft", "Label"), + QT_TRANSLATE_NOOP("Draft", "Position"), + QT_TRANSLATE_NOOP("Draft", "Length"), + QT_TRANSLATE_NOOP("Draft", "Area"), + QT_TRANSLATE_NOOP("Draft", "Volume"), + QT_TRANSLATE_NOOP("Draft", "Tag"), + QT_TRANSLATE_NOOP("Draft", "Material"), + QT_TRANSLATE_NOOP("Draft", "Label + Position"), + QT_TRANSLATE_NOOP("Draft", "Label + Length"), + QT_TRANSLATE_NOOP("Draft", "Label + Area"), + QT_TRANSLATE_NOOP("Draft", "Label + Volume"), + QT_TRANSLATE_NOOP("Draft", "Label + Material"), + ] def return_info(target, typ, subelement=None): @@ -420,7 +404,7 @@ def _get_tag(target): def _get_material(target): - if (hasattr(target, "Material") and hasattr(target.Material, "Label")): + if hasattr(target, "Material") and hasattr(target.Material, "Label"): return [target.Material.Label] else: return [translate("draft", "Material not available for object")] diff --git a/src/Mod/Draft/draftobjects/layer.py b/src/Mod/Draft/draftobjects/layer.py index 70844d5d52..fdd03f59cc 100644 --- a/src/Mod/Draft/draftobjects/layer.py +++ b/src/Mod/Draft/draftobjects/layer.py @@ -52,16 +52,11 @@ class Layer: def set_properties(self, obj): """Set properties only if they don't exist.""" if "Group" not in obj.PropertiesList: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The objects that are part of this layer") + _tip = QT_TRANSLATE_NOOP("App::Property", "The objects that are part of this layer") # "App::PropertyLinkListHidden" instead of "App::PropertyLinkList" has 2 advantages: # 1. No 'might break' warning when deleting an object nested in a layer. # 2. No 'out of scope' warning for objects also nested in f.e. a Std_Part. - obj.addProperty("App::PropertyLinkListHidden", - "Group", - "Layer", - _tip, - locked=True) + obj.addProperty("App::PropertyLinkListHidden", "Group", "Layer", _tip, locked=True) def onDocumentRestored(self, obj): """Execute code when the document is restored.""" @@ -93,7 +88,7 @@ class Layer: material = App.Material() # Material with default v0.21 properties. material.DiffuseColor = vobj.ShapeColor material.Transparency = vobj.Transparency / 100 - vobj.ShapeAppearance = (material, ) + vobj.ShapeAppearance = (material,) vobj.setPropertyStatus("ShapeColor", "Hidden") if hasattr(vobj, "OverrideShapeColorChildren"): # v0.19 - v0.21 vobj.OverrideShapeAppearanceChildren = vobj.OverrideShapeColorChildren @@ -214,4 +209,5 @@ def get_layer(obj): return find return None + ## @} diff --git a/src/Mod/Draft/draftobjects/patharray.py b/src/Mod/Draft/draftobjects/patharray.py index 3273740fae..69d10f38c5 100644 --- a/src/Mod/Draft/draftobjects/patharray.py +++ b/src/Mod/Draft/draftobjects/patharray.py @@ -69,7 +69,12 @@ import lazy_loader.lazy_loader as lz from draftutils.messages import _err, _log, _wrn from draftutils.translate import translate -def QT_TRANSLATE_NOOP(ctx,txt): return txt + + +def QT_TRANSLATE_NOOP(ctx, txt): + return txt + + from draftobjects.base import DraftObject from draftobjects.draftlink import DraftLink @@ -212,21 +217,16 @@ class PathArray(DraftLink): def set_general_properties(self, obj, properties): """Set general properties only if they don't exist.""" if "Base" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","The base object that will be duplicated") - obj.addProperty("App::PropertyLinkGlobal", - "Base", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated") + obj.addProperty("App::PropertyLinkGlobal", "Base", "Objects", _tip, locked=True) obj.Base = None if "PathObject" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","The object along which the copies will be distributed. It must contain 'Edges'.") - obj.addProperty("App::PropertyLinkGlobal", - "PathObject", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The object along which the copies will be distributed. It must contain 'Edges'.", + ) + obj.addProperty("App::PropertyLinkGlobal", "PathObject", "Objects", _tip, locked=True) obj.PathObject = None # TODO: the 'PathSubelements' property must be changed, @@ -237,199 +237,161 @@ class PathArray(DraftLink): # as this property can be used to select a single object, # or a single object with its subelements. if "PathSubelements" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","List of connected edges in the 'Path Object'.\nIf these are present, the copies will be created along these subelements only.\nLeave this property empty to create copies along the entire 'Path Object'.") - obj.addProperty("App::PropertyLinkSubListGlobal", - "PathSubelements", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "List of connected edges in the 'Path Object'.\nIf these are present, the copies will be created along these subelements only.\nLeave this property empty to create copies along the entire 'Path Object'.", + ) + obj.addProperty( + "App::PropertyLinkSubListGlobal", "PathSubelements", "Objects", _tip, locked=True + ) obj.PathSubelements = [] if "Fuse" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Specifies if the copies " - "should be fused together " - "if they touch each other (slower)") - obj.addProperty("App::PropertyBool", - "Fuse", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Specifies if the copies " + "should be fused together " + "if they touch each other (slower)", + ) + obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True) obj.Fuse = False if self.use_link and "ExpandArray" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Show the individual array elements (only for Link arrays)") - obj.addProperty("App::PropertyBool", - "ExpandArray", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Show the individual array elements (only for Link arrays)" + ) + obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True) obj.ExpandArray = False - obj.setPropertyStatus('Shape', 'Transient') + obj.setPropertyStatus("Shape", "Transient") if not self.use_link: if "PlacementList" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement for each array element") - obj.addProperty("App::PropertyPlacementList", - "PlacementList", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element") + obj.addProperty( + "App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True + ) obj.PlacementList = [] def set_align_properties(self, obj, properties): """Set general properties only if they don't exist.""" if "ExtraTranslation" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Additional translation that will be applied to each copy.\nThis is useful to adjust for the difference between shape centre and shape reference point.") - obj.addProperty("App::PropertyVectorDistance", - "ExtraTranslation", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Additional translation that will be applied to each copy.\nThis is useful to adjust for the difference between shape centre and shape reference point.", + ) + obj.addProperty( + "App::PropertyVectorDistance", "ExtraTranslation", "Alignment", _tip, locked=True + ) obj.ExtraTranslation = App.Vector(0, 0, 0) if "TangentVector" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Alignment vector for 'Tangent' mode") - obj.addProperty("App::PropertyVector", - "TangentVector", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Alignment vector for 'Tangent' mode") + obj.addProperty("App::PropertyVector", "TangentVector", "Alignment", _tip, locked=True) obj.TangentVector = App.Vector(1, 0, 0) if "ForceVertical" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Force use of 'Vertical Vector' as local Z-direction when using 'Original' or 'Tangent' alignment mode") - obj.addProperty("App::PropertyBool", - "ForceVertical", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Force use of 'Vertical Vector' as local Z-direction when using 'Original' or 'Tangent' alignment mode", + ) + obj.addProperty("App::PropertyBool", "ForceVertical", "Alignment", _tip, locked=True) obj.ForceVertical = False if "VerticalVector" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Direction of the local Z axis when 'Force Vertical' is true") - obj.addProperty("App::PropertyVector", - "VerticalVector", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Direction of the local Z axis when 'Force Vertical' is true" + ) + obj.addProperty("App::PropertyVector", "VerticalVector", "Alignment", _tip, locked=True) obj.VerticalVector = App.Vector(0, 0, 1) if "AlignMode" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Method to orient the copies along the path.\n- Original: X is curve tangent, Y is normal, and Z is the cross product.\n- Frenet: aligns the object following the local coordinate system along the path.\n- Tangent: similar to 'Original' but the local X axis is pre-aligned to 'Tangent Vector'.\n\nTo get better results with 'Original' or 'Tangent' you may have to set 'Force Vertical' to true.") - obj.addProperty("App::PropertyEnumeration", - "AlignMode", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Method to orient the copies along the path.\n- Original: X is curve tangent, Y is normal, and Z is the cross product.\n- Frenet: aligns the object following the local coordinate system along the path.\n- Tangent: similar to 'Original' but the local X axis is pre-aligned to 'Tangent Vector'.\n\nTo get better results with 'Original' or 'Tangent' you may have to set 'Force Vertical' to true.", + ) + obj.addProperty("App::PropertyEnumeration", "AlignMode", "Alignment", _tip, locked=True) obj.AlignMode = ["Original", "Frenet", "Tangent"] obj.AlignMode = "Original" if "ReversePath" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Walk the path backwards.") - obj.addProperty("App::PropertyBool", - "ReversePath", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Walk the path backwards.") + obj.addProperty("App::PropertyBool", "ReversePath", "Alignment", _tip, locked=True) obj.ReversePath = False # The Align property must be attached after other align properties # so that onChanged works properly if "Align" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Orient the copies along the path depending on the 'Align Mode'.\nOtherwise the copies will have the same orientation as the original Base object.") - obj.addProperty("App::PropertyBool", - "Align", - "Alignment", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Orient the copies along the path depending on the 'Align Mode'.\nOtherwise the copies will have the same orientation as the original Base object.", + ) + obj.addProperty("App::PropertyBool", "Align", "Alignment", _tip, locked=True) obj.Align = False def set_spacing_properties(self, obj, properties): if "Count" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Number of copies to create") - obj.addProperty("App::PropertyInteger", - "Count", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies to create") + obj.addProperty("App::PropertyInteger", "Count", "Spacing", _tip, locked=True) obj.Count = 4 if "SpacingMode" not in properties: _tip = QT_TRANSLATE_NOOP( "App::Property", - "How copies are spaced.\n" + - " - Fixed count: available path length (minus start and end offsets) is evenly divided into n.\n" + - " - Fixed spacing: start at \"Start offset\" and place new copies after traveling a fixed distance along the path.\n" + - " - Fixed count and spacing: same as \"Fixed spacing\", but also stop at given number of copies." - ) - obj.addProperty("App::PropertyEnumeration", - "SpacingMode", - "Spacing", - _tip, - locked=True) + "How copies are spaced.\n" + + " - Fixed count: available path length (minus start and end offsets) is evenly divided into n.\n" + + ' - Fixed spacing: start at "Start offset" and place new copies after traveling a fixed distance along the path.\n' + + ' - Fixed count and spacing: same as "Fixed spacing", but also stop at given number of copies.', + ) + obj.addProperty("App::PropertyEnumeration", "SpacingMode", "Spacing", _tip, locked=True) obj.SpacingMode = ["Fixed count", "Fixed spacing", "Fixed count and spacing"] obj.SpacingMode = "Fixed count" if "SpacingUnit" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Base fixed distance between elements.") - obj.addProperty("App::PropertyLength", - "SpacingUnit", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Base fixed distance between elements.") + obj.addProperty("App::PropertyLength", "SpacingUnit", "Spacing", _tip, locked=True) obj.SpacingUnit = 20.0 obj.setPropertyStatus("SpacingUnit", "Hidden") if "UseSpacingPattern" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Use repeating spacing patterns instead of uniform spacing.") - obj.addProperty("App::PropertyBool", - "UseSpacingPattern", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Use repeating spacing patterns instead of uniform spacing." + ) + obj.addProperty("App::PropertyBool", "UseSpacingPattern", "Spacing", _tip, locked=True) obj.UseSpacingPattern = False if "SpacingPattern" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Spacing is multiplied by a corresponding number in this sequence.") - obj.addProperty("App::PropertyFloatList", - "SpacingPattern", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Spacing is multiplied by a corresponding number in this sequence." + ) + obj.addProperty( + "App::PropertyFloatList", "SpacingPattern", "Spacing", _tip, locked=True + ) obj.SpacingPattern = [1, 2] obj.setPropertyStatus("SpacingPattern", "Hidden") if "StartOffset" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Length from the start of the path to the first copy.") - obj.addProperty("App::PropertyLength", - "StartOffset", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Length from the start of the path to the first copy." + ) + obj.addProperty("App::PropertyLength", "StartOffset", "Spacing", _tip, locked=True) obj.StartOffset = 0.0 if "EndOffset" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property","Length from the end of the path to the last copy.") - obj.addProperty("App::PropertyLength", - "EndOffset", - "Spacing", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Length from the end of the path to the last copy." + ) + obj.addProperty("App::PropertyLength", "EndOffset", "Spacing", _tip, locked=True) obj.EndOffset = 0.0 def linkSetup(self, obj): """Set up the object as a link object.""" super().linkSetup(obj) - obj.configLinkProperty(ElementCount='Count') + obj.configLinkProperty(ElementCount="Count") def execute(self, obj): """Execute when the object is created or recomputed.""" - if self.props_changed_placement_only(obj) \ - or not obj.Base \ - or not obj.PathObject: + if self.props_changed_placement_only(obj) or not obj.Base or not obj.PathObject: self.props_changed_clear() return @@ -438,15 +400,13 @@ class PathArray(DraftLink): w = self.get_wires(obj.PathObject, obj.PathSubelements) if not w: - _err(obj.PathObject.Label - + translate("draft",", path object does not have 'Edges'.")) + _err(obj.PathObject.Label + translate("draft", ", path object does not have 'Edges'.")) return base_rotation = obj.Base.Shape.Placement.Rotation final_rotation = base_rotation - if (obj.Align and obj.AlignMode == "Tangent" - and hasattr(obj, "TangentVector")): + if obj.Align and obj.AlignMode == "Tangent" and hasattr(obj, "TangentVector"): Xaxis = App.Vector(1.0, 0.0, 0.0) # default TangentVector if not DraftVecUtils.equals(Xaxis, obj.TangentVector): @@ -454,30 +414,33 @@ class PathArray(DraftLink): pre_rotation = App.Rotation(obj.TangentVector, Xaxis) final_rotation = base_rotation.multiply(pre_rotation) - copy_placements = placements_on_path(final_rotation, - w, obj.Count, - obj.ExtraTranslation, - obj.Align, obj.AlignMode, - obj.ForceVertical, - obj.VerticalVector, - obj.StartOffset.Value, - obj.EndOffset.Value, - obj.ReversePath, - obj.SpacingMode, - obj.SpacingUnit.Value, - obj.UseSpacingPattern, - obj.SpacingPattern) + copy_placements = placements_on_path( + final_rotation, + w, + obj.Count, + obj.ExtraTranslation, + obj.Align, + obj.AlignMode, + obj.ForceVertical, + obj.VerticalVector, + obj.StartOffset.Value, + obj.EndOffset.Value, + obj.ReversePath, + obj.SpacingMode, + obj.SpacingUnit.Value, + obj.UseSpacingPattern, + obj.SpacingPattern, + ) self.buildShape(obj, array_placement, copy_placements) self.props_changed_clear() - return (not self.use_link) + return not self.use_link def get_wires(self, path_object, subelements): """Get wires from the path object.""" if subelements: w = self.get_wire_from_subelements(subelements) - elif (hasattr(path_object.Shape, 'Wires') - and path_object.Shape.Wires): + elif hasattr(path_object.Shape, "Wires") and path_object.Shape.Wires: w = path_object.Shape.Wires[0] elif path_object.Shape.Edges: w = Part.Wire(path_object.Shape.Edges) @@ -511,10 +474,7 @@ class PathArray(DraftLink): if prop == "SpacingMode": # Check if all referenced properties are available: - for pr in ("SpacingMode", - "SpacingUnit", - "UseSpacingPattern", - "SpacingPattern"): + for pr in ("SpacingMode", "SpacingUnit", "UseSpacingPattern", "SpacingPattern"): if not hasattr(obj, pr): return @@ -544,8 +504,7 @@ class PathArray(DraftLink): if prop in ("Align", "AlignMode"): # Check if all referenced properties are available: - for pr in ("Align", "AlignMode", "ForceVertical", - "VerticalVector", "TangentVector"): + for pr in ("Align", "AlignMode", "ForceVertical", "VerticalVector", "TangentVector"): if not hasattr(obj, pr): return @@ -565,8 +524,7 @@ class PathArray(DraftLink): obj.setPropertyStatus("TangentVector", "Hidden") else: - for pr in ("AlignMode", "ForceVertical", - "VerticalVector", "TangentVector"): + for pr in ("AlignMode", "ForceVertical", "VerticalVector", "TangentVector"): obj.setPropertyStatus(pr, "Hidden") def onDocumentRestored(self, obj): @@ -609,22 +567,30 @@ class PathArray(DraftLink): if hasattr(obj, "Xlate"): obj.ExtraTranslation = obj.Xlate obj.removeProperty("Xlate") - self.execute(obj) # Required to update PlacementList. + self.execute(obj) # Required to update PlacementList. # Alias for compatibility with v0.18 and earlier _PathArray = PathArray -def placements_on_path(shapeRotation, pathwire, count, xlate, align, - mode="Original", forceNormal=False, - normalOverride=None, - startOffset=0.0, endOffset=0.0, - reversePath=False, - spacingMode="Fixed count", - spacingUnit=20.0, - useSpacingPattern=False, - spacingPattern=[1, 1, 1, 1]): +def placements_on_path( + shapeRotation, + pathwire, + count, + xlate, + align, + mode="Original", + forceNormal=False, + normalOverride=None, + startOffset=0.0, + endOffset=0.0, + reversePath=False, + spacingMode="Fixed count", + spacingUnit=20.0, + useSpacingPattern=False, + spacingPattern=[1, 1, 1, 1], +): """Calculate the placements of a shape along a given path. Copies will be distributed according to spacing mode - evenly or in fixed offsets. @@ -658,12 +624,7 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, if startOffset > (totalDist - minLength): if startOffset != 0: - _wrn( - translate( - "draft", - "Start Offset too large for path length. Using 0 instead." - ) - ) + _wrn(translate("draft", "Start Offset too large for path length. Using 0 instead.")) startOffset = 0 if endOffset > (totalDist - startOffset - minLength): @@ -671,7 +632,7 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, _wrn( translate( "draft", - "End Offset too large for path length minus Start Offset. Using 0 instead." + "End Offset too large for path length minus Start Offset. Using 0 instead.", ) ) endOffset = 0 @@ -728,7 +689,6 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, # Each interval will be the same: steps = [spacingUnit] - remains = 0 travel = startOffset endTravel = startOffset + totalDist @@ -750,18 +710,27 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, # place shape at proper spot on proper edge pt = path[iend].valueAt(get_parameter_from_v0(path[iend], offset)) - place = calculate_placement(shapeRotation, - path[iend], offset, - pt, xlate, align, normal, - mode, forceNormal, - reversePath) + place = calculate_placement( + shapeRotation, + path[iend], + offset, + pt, + xlate, + align, + normal, + mode, + forceNormal, + reversePath, + ) placements.append(place) travel += steps[i % len(steps)] i = i + 1 # End conditions: - if stopAfterDistance and travel > endTravel: break - if stopAfterCount and i >= count: break + if stopAfterDistance and travel > endTravel: + break + if stopAfterCount and i >= count: + break # Failsafe: if i > 10_000: @@ -774,11 +743,18 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align, calculatePlacementsOnPath = placements_on_path -def calculate_placement(globalRotation, - edge, offset, RefPt, xlate, align, - normal=App.Vector(0.0, 0.0, 1.0), - mode="Original", overrideNormal=False, - reversePath=False): +def calculate_placement( + globalRotation, + edge, + offset, + RefPt, + xlate, + align, + normal=App.Vector(0.0, 0.0, 1.0), + mode="Original", + overrideNormal=False, + reversePath=False, +): """Orient shape in the local coordinate system at parameter offset. http://en.wikipedia.org/wiki/Euler_angles (previous version) @@ -792,7 +768,7 @@ def calculate_placement(globalRotation, if not align: return placement - tol = 1e-6 # App.Rotation() tolerance is 1e-7. Shorter vectors are ignored. + tol = 1e-6 # App.Rotation() tolerance is 1e-7. Shorter vectors are ignored. nullv = App.Vector() t = edge.tangentAt(get_parameter_from_v0(edge, offset)) @@ -821,19 +797,28 @@ def calculate_placement(globalRotation, n_nor = n.normalize() t_nor = t.normalize() if n_nor.isEqual(t_nor, tol) or n_nor.isEqual(t_nor.negative(), tol): - _wrn(translate("draft", "Tangent and normal vectors are parallel. Normal replaced by a default axis.")) + _wrn( + translate( + "draft", + "Tangent and normal vectors are parallel. Normal replaced by a default axis.", + ) + ) n = t if overrideNormal: - onPathRotation = App.Rotation(t, nullv, n, "XZY") # priority = "XZY" + onPathRotation = App.Rotation(t, nullv, n, "XZY") # priority = "XZY" else: - onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ" + onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ" elif mode == "Frenet": try: n = edge.normalAt(get_parameter_from_v0(edge, offset)) - except App.Base.FreeCADError: # no/infinite normals here - _wrn(translate("draft", "Cannot calculate normal vector. Using the default normal instead.")) + except App.Base.FreeCADError: # no/infinite normals here + _wrn( + translate( + "draft", "Cannot calculate normal vector. Using the default normal instead." + ) + ) n = normal if n.isEqual(nullv, tol): @@ -843,10 +828,15 @@ def calculate_placement(globalRotation, n_nor = n.normalize() t_nor = t.normalize() if n_nor.isEqual(t_nor, tol) or n_nor.isEqual(t_nor.negative(), tol): - _wrn(translate("draft", "Tangent and normal vectors are parallel. Normal replaced by a default axis.")) + _wrn( + translate( + "draft", + "Tangent and normal vectors are parallel. Normal replaced by a default axis.", + ) + ) n = t - onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ" + onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ" else: _err(translate("draft", "AlignMode {} is not implemented").format(mode)) @@ -860,6 +850,7 @@ def calculate_placement(globalRotation, calculatePlacement = calculate_placement + def get_parameter_from_v0(edge, offset): """Return parameter at distance offset from edge.Vertexes[0]. diff --git a/src/Mod/Draft/draftobjects/pathtwistedarray.py b/src/Mod/Draft/draftobjects/pathtwistedarray.py index 52cb6efdc9..7b200d8a67 100644 --- a/src/Mod/Draft/draftobjects/pathtwistedarray.py +++ b/src/Mod/Draft/draftobjects/pathtwistedarray.py @@ -49,7 +49,12 @@ object in the Arch Workbench. import draftgeoutils.geo_arrays as geo from draftutils.messages import _log -def QT_TRANSLATE_NOOP(ctx,txt): return txt + + +def QT_TRANSLATE_NOOP(ctx, txt): + return txt + + from draftobjects.draftlink import DraftLink ## \addtogroup draftobjects @@ -80,73 +85,83 @@ class PathTwistedArray(DraftLink): properties = [] if "Base" not in properties: - obj.addProperty("App::PropertyLink", - "Base", - "Objects", - QT_TRANSLATE_NOOP("App::Property","The base object that will be duplicated."), - locked=True) + obj.addProperty( + "App::PropertyLink", + "Base", + "Objects", + QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated."), + locked=True, + ) obj.Base = None if "PathObject" not in properties: - obj.addProperty("App::PropertyLink", - "PathObject", - "Objects", - QT_TRANSLATE_NOOP("App::Property","The object along which the copies will be distributed. It must contain 'Edges'."), - locked=True) + obj.addProperty( + "App::PropertyLink", + "PathObject", + "Objects", + QT_TRANSLATE_NOOP( + "App::Property", + "The object along which the copies will be distributed. It must contain 'Edges'.", + ), + locked=True, + ) obj.PathObject = None if "Fuse" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Specifies if the copies " - "should be fused together " - "if they touch each other (slower)") - obj.addProperty("App::PropertyBool", - "Fuse", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Specifies if the copies " + "should be fused together " + "if they touch each other (slower)", + ) + obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True) obj.Fuse = False if "Count" not in properties: - obj.addProperty("App::PropertyInteger", - "Count", - "Objects", - QT_TRANSLATE_NOOP("App::Property","Number of copies to create."), - locked=True) + obj.addProperty( + "App::PropertyInteger", + "Count", + "Objects", + QT_TRANSLATE_NOOP("App::Property", "Number of copies to create."), + locked=True, + ) obj.Count = 15 if "RotationFactor" not in properties: - obj.addProperty("App::PropertyFloat", - "RotationFactor", - "Objects", - QT_TRANSLATE_NOOP("App::Property","Rotation factor of the twisted array."), - locked=True) + obj.addProperty( + "App::PropertyFloat", + "RotationFactor", + "Objects", + QT_TRANSLATE_NOOP("App::Property", "Rotation factor of the twisted array."), + locked=True, + ) obj.RotationFactor = 0.25 if self.use_link and "ExpandArray" not in properties: - obj.addProperty("App::PropertyBool", - "ExpandArray", - "Objects", - QT_TRANSLATE_NOOP("App::Property","Show the individual array elements (only for Link arrays)"), - locked=True) + obj.addProperty( + "App::PropertyBool", + "ExpandArray", + "Objects", + QT_TRANSLATE_NOOP( + "App::Property", "Show the individual array elements (only for Link arrays)" + ), + locked=True, + ) obj.ExpandArray = False - obj.setPropertyStatus('Shape', 'Transient') + obj.setPropertyStatus("Shape", "Transient") if not self.use_link: if "PlacementList" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement for each array element") - obj.addProperty("App::PropertyPlacementList", - "PlacementList", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element") + obj.addProperty( + "App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True + ) obj.PlacementList = [] def linkSetup(self, obj): """Set up the object as a link object.""" super().linkSetup(obj) - obj.configLinkProperty(ElementCount='Count') + obj.configLinkProperty(ElementCount="Count") def onDocumentRestored(self, obj): super().onDocumentRestored(obj) @@ -161,13 +176,11 @@ class PathTwistedArray(DraftLink): _log("v1.1, " + obj.Name + ", added hidden property 'PlacementList'") self.set_properties(obj) - self.execute(obj) # Required to update PlacementList. + self.execute(obj) # Required to update PlacementList. def execute(self, obj): """Execute when the object is created or recomputed.""" - if self.props_changed_placement_only(obj) \ - or not obj.Base \ - or not obj.PathObject: + if self.props_changed_placement_only(obj) or not obj.Base or not obj.PathObject: self.props_changed_clear() return @@ -178,12 +191,11 @@ class PathTwistedArray(DraftLink): count = obj.Count rot_factor = obj.RotationFactor - copy_placements, _ = geo.get_twisted_placements(path, - count=count, - rot_factor=rot_factor) + copy_placements, _ = geo.get_twisted_placements(path, count=count, rot_factor=rot_factor) self.buildShape(obj, array_placement, copy_placements) self.props_changed_clear() - return (not self.use_link) + return not self.use_link + ## @} diff --git a/src/Mod/Draft/draftobjects/point.py b/src/Mod/Draft/draftobjects/point.py index 3f64712b86..0412e21ef5 100644 --- a/src/Mod/Draft/draftobjects/point.py +++ b/src/Mod/Draft/draftobjects/point.py @@ -54,7 +54,7 @@ class Point(DraftObject): obj.Y = y obj.Z = z - obj.setPropertyStatus('Placement', 'Hidden') + obj.setPropertyStatus("Placement", "Hidden") def onDocumentRestored(self, obj): super().onDocumentRestored(obj) @@ -73,6 +73,7 @@ class Point(DraftObject): return import Part + obj.Shape = Part.Vertex(App.Vector(0, 0, 0)) if base != xyz_vec: obj.Placement.Base = xyz_vec diff --git a/src/Mod/Draft/draftobjects/pointarray.py b/src/Mod/Draft/draftobjects/pointarray.py index 0cd5793c11..d4e59a5538 100644 --- a/src/Mod/Draft/draftobjects/pointarray.py +++ b/src/Mod/Draft/draftobjects/pointarray.py @@ -22,8 +22,7 @@ # * USA * # * * # *************************************************************************** -"""Provides the object code for the PointArray object. -""" +"""Provides the object code for the PointArray object.""" ## @package pointarray # \ingroup draftobjects # \brief Provides the object code for the PointArray object. @@ -56,7 +55,7 @@ class PointArray(DraftLink): def linkSetup(self, obj): """Set up the object as a link object.""" super().linkSetup(obj) - obj.configLinkProperty(ElementCount='Count') + obj.configLinkProperty(ElementCount="Count") def set_properties(self, obj): """Set properties only if they don't exist.""" @@ -64,78 +63,63 @@ class PointArray(DraftLink): if "Base" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Base object that will be duplicated") - obj.addProperty("App::PropertyLink", - "Base", - "Objects", - _tip, - locked=True) + obj.addProperty("App::PropertyLink", "Base", "Objects", _tip, locked=True) obj.Base = None if "PointObject" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Object containing points used to distribute the copies.") - obj.addProperty("App::PropertyLink", - "PointObject", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Object containing points used to distribute the copies." + ) + obj.addProperty("App::PropertyLink", "PointObject", "Objects", _tip, locked=True) obj.PointObject = None if "Fuse" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Specifies if the copies " - "should be fused together " - "if they touch each other (slower)") - obj.addProperty("App::PropertyBool", - "Fuse", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Specifies if the copies " + "should be fused together " + "if they touch each other (slower)", + ) + obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True) obj.Fuse = False if "Count" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in the array.\nThis property is read-only, as the number depends on the points in 'Point Object'.") - obj.addProperty("App::PropertyInteger", - "Count", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Number of copies in the array.\nThis property is read-only, as the number depends on the points in 'Point Object'.", + ) + obj.addProperty("App::PropertyInteger", "Count", "Objects", _tip, locked=True) obj.Count = 0 obj.setEditorMode("Count", 1) # Read only if "ExtraPlacement" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Additional placement, shift and rotation, that will be applied to each copy") - obj.addProperty("App::PropertyPlacement", - "ExtraPlacement", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Additional placement, shift and rotation, that will be applied to each copy", + ) + obj.addProperty( + "App::PropertyPlacement", "ExtraPlacement", "Objects", _tip, locked=True + ) obj.ExtraPlacement = App.Placement() if self.use_link and "ExpandArray" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Show the individual array elements (only for Link arrays)") - obj.addProperty("App::PropertyBool", - "ExpandArray", - "Objects", - _tip, - locked=True) - obj.setPropertyStatus('Shape', 'Transient') + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Show the individual array elements (only for Link arrays)" + ) + obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True) + obj.setPropertyStatus("Shape", "Transient") if not self.use_link: if "PlacementList" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement for each array element") - obj.addProperty("App::PropertyPlacementList", - "PlacementList", - "Objects", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element") + obj.addProperty( + "App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True + ) obj.PlacementList = [] def execute(self, obj): """Run when the object is created or recomputed.""" - if self.props_changed_placement_only(obj) \ - or not obj.Base \ - or not obj.PointObject: + if self.props_changed_placement_only(obj) or not obj.Base or not obj.PointObject: self.props_changed_clear() return @@ -145,7 +129,7 @@ class PointArray(DraftLink): self.buildShape(obj, obj.Placement, pls) self.props_changed_clear() - return (not self.use_link) + return not self.use_link def onDocumentRestored(self, obj): super().onDocumentRestored(obj) @@ -167,9 +151,10 @@ class PointArray(DraftLink): if hasattr(obj, "PointList"): obj.PointObject = obj.PointList obj.removeProperty("PointList") - self.execute(obj) # Required to update PlacementList. + self.execute(obj) # Required to update PlacementList. -def remove_equal_vecs (vec_list): + +def remove_equal_vecs(vec_list): """Remove equal vectors from a list. Parameters @@ -189,6 +174,7 @@ def remove_equal_vecs (vec_list): res_list.append(vec) return res_list + def get_point_list(point_object): """Extract a list of points from a point object. @@ -205,7 +191,7 @@ def get_point_list(point_object): if hasattr(point_object, "Shape") and hasattr(point_object.Shape, "Vertexes"): pt_list = [v.Point for v in point_object.Shape.Vertexes] # For compatibility with previous versions: add all points from sketch (including construction geometry): - if hasattr(point_object, 'Geometry'): + if hasattr(point_object, "Geometry"): place = point_object.Placement for geo in point_object.Geometry: if geo.TypeId == "Part::GeomPoint": @@ -219,6 +205,7 @@ def get_point_list(point_object): return remove_equal_vecs(pt_list) + def build_placements(base_object, pt_list=None, placement=App.Placement()): """Build a placements from the base object and list of points. @@ -227,9 +214,12 @@ def build_placements(base_object, pt_list=None, placement=App.Placement()): list of App.Placements """ if not pt_list: - _err(translate("Draft", - "Point object does not have a discrete point, " - "it cannot be used for an array")) + _err( + translate( + "Draft", + "Point object does not have a discrete point, " "it cannot be used for an array", + ) + ) return [] pls = list() diff --git a/src/Mod/Draft/draftobjects/polygon.py b/src/Mod/Draft/draftobjects/polygon.py index ebbf62f455..50f5bf204c 100644 --- a/src/Mod/Draft/draftobjects/polygon.py +++ b/src/Mod/Draft/draftobjects/polygon.py @@ -43,36 +43,31 @@ class Polygon(DraftObject): def __init__(self, obj): super().__init__(obj, "Polygon") - _tip = QT_TRANSLATE_NOOP("App::Property", - "Number of faces") + _tip = QT_TRANSLATE_NOOP("App::Property", "Number of faces") obj.addProperty("App::PropertyInteger", "FacesNumber", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Radius of the control circle") + _tip = QT_TRANSLATE_NOOP("App::Property", "Radius of the control circle") obj.addProperty("App::PropertyLength", "Radius", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "How the polygon must be drawn from the control circle") + _tip = QT_TRANSLATE_NOOP( + "App::Property", "How the polygon must be drawn from the control circle" + ) obj.addProperty("App::PropertyEnumeration", "DrawMode", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Radius to use to fillet the corners") + _tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corners") obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Size of the chamfer to give to the corners") + _tip = QT_TRANSLATE_NOOP("App::Property", "Size of the chamfer to give to the corners") obj.addProperty("App::PropertyLength", "ChamferSize", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Create a face") + _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face") obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The area of this object") + _tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object") obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") - obj.DrawMode = ['inscribed','circumscribed'] + obj.DrawMode = ["inscribed", "circumscribed"] obj.FacesNumber = 0 obj.Radius = 1 @@ -88,33 +83,30 @@ class Polygon(DraftObject): if (obj.FacesNumber >= 3) and (obj.Radius.Value > 0): import Part + plm = obj.Placement angle = (math.pi * 2) / obj.FacesNumber - if obj.DrawMode == 'inscribed': + if obj.DrawMode == "inscribed": delta = obj.Radius.Value else: delta = obj.Radius.Value / math.cos(angle / 2.0) pts = [App.Vector(delta, 0, 0)] for i in range(obj.FacesNumber - 1): ang = (i + 1) * angle - pts.append(App.Vector(delta * math.cos(ang), - delta*math.sin(ang), - 0)) + pts.append(App.Vector(delta * math.cos(ang), delta * math.sin(ang), 0)) pts.append(pts[0]) shape = Part.makePolygon(pts) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: - w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value, - chamfer=True) + w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: - w = DraftGeomUtils.filletWire(shape, - obj.FilletRadius.Value) + w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w - if hasattr(obj,"MakeFace"): + if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: diff --git a/src/Mod/Draft/draftobjects/rectangle.py b/src/Mod/Draft/draftobjects/rectangle.py index 1bf4fcd108..d9ea64d6b5 100644 --- a/src/Mod/Draft/draftobjects/rectangle.py +++ b/src/Mod/Draft/draftobjects/rectangle.py @@ -67,10 +67,10 @@ class Rectangle(DraftObject): obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") - obj.Length=1 - obj.Height=1 - obj.Rows=1 - obj.Columns=1 + obj.Length = 1 + obj.Height = 1 + obj.Rows = 1 + obj.Columns = 1 def onDocumentRestored(self, obj): super().onDocumentRestored(obj) @@ -95,7 +95,7 @@ class Rectangle(DraftObject): shape = None - if hasattr(obj,"Rows") and hasattr(obj,"Columns"): + if hasattr(obj, "Rows") and hasattr(obj, "Columns"): # TODO: verify if this is needed: if obj.Rows > 1: rows = obj.Rows @@ -109,29 +109,28 @@ class Rectangle(DraftObject): if (rows > 1) or (columns > 1): shapes = [] - l = obj.Length.Value/columns - h = obj.Height.Value/rows + l = obj.Length.Value / columns + h = obj.Height.Value / rows for i in range(columns): for j in range(rows): - p1 = App.Vector(i*l,j*h,0) - p2 = App.Vector(p1.x+l,p1.y,p1.z) - p3 = App.Vector(p1.x+l,p1.y+h,p1.z) - p4 = App.Vector(p1.x,p1.y+h,p1.z) - p = Part.makePolygon([p1,p2,p3,p4,p1]) + p1 = App.Vector(i * l, j * h, 0) + p2 = App.Vector(p1.x + l, p1.y, p1.z) + p3 = App.Vector(p1.x + l, p1.y + h, p1.z) + p4 = App.Vector(p1.x, p1.y + h, p1.z) + p = Part.makePolygon([p1, p2, p3, p4, p1]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: - w = DraftGeomUtils.filletWire(p, - obj.ChamferSize.Value, - chamfer=True) + w = DraftGeomUtils.filletWire( + p, obj.ChamferSize.Value, chamfer=True + ) if w: p = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: - w = DraftGeomUtils.filletWire(p, - obj.FilletRadius.Value) + w = DraftGeomUtils.filletWire(p, obj.FilletRadius.Value) if w: p = w - if hasattr(obj,"MakeFace"): + if hasattr(obj, "MakeFace"): if obj.MakeFace: p = Part.Face(p) shapes.append(p) @@ -139,31 +138,22 @@ class Rectangle(DraftObject): shape = Part.makeCompound(shapes) if not shape: - p1 = App.Vector(0,0,0) - p2 = App.Vector(p1.x+obj.Length.Value, - p1.y, - p1.z) - p3 = App.Vector(p1.x+obj.Length.Value, - p1.y+obj.Height.Value, - p1.z) - p4 = App.Vector(p1.x, - p1.y+obj.Height.Value, - p1.z) + p1 = App.Vector(0, 0, 0) + p2 = App.Vector(p1.x + obj.Length.Value, p1.y, p1.z) + p3 = App.Vector(p1.x + obj.Length.Value, p1.y + obj.Height.Value, p1.z) + p4 = App.Vector(p1.x, p1.y + obj.Height.Value, p1.z) shape = Part.makePolygon([p1, p2, p3, p4, p1]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: - w = DraftGeomUtils.filletWire(shape, - obj.ChamferSize.Value, - chamfer=True) + w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: - w = DraftGeomUtils.filletWire(shape, - obj.FilletRadius.Value) + w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w - if hasattr(obj,"MakeFace"): + if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: @@ -171,7 +161,7 @@ class Rectangle(DraftObject): obj.Shape = shape - if hasattr(obj,"Area") and hasattr(shape,"Area"): + if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area obj.Placement = plm diff --git a/src/Mod/Draft/draftobjects/shape2dview.py b/src/Mod/Draft/draftobjects/shape2dview.py index a04da16891..496dd84d55 100644 --- a/src/Mod/Draft/draftobjects/shape2dview.py +++ b/src/Mod/Draft/draftobjects/shape2dview.py @@ -41,7 +41,7 @@ from draftutils.translate import translate class Shape2DView(DraftObject): """The Shape2DView object""" - def __init__(self,obj): + def __init__(self, obj): self.setProperties(obj) super().__init__(obj, "Shape2DView") @@ -53,101 +53,108 @@ class Shape2DView(DraftObject): obj, vp_module="view_base", vp_class="ViewProviderDraftAlt", format=False ) - def setProperties(self,obj): + def setProperties(self, obj): pl = obj.PropertiesList if not "Base" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The base object this 2D view must represent") - obj.addProperty("App::PropertyLink", "Base", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The base object this 2D view must represent") + obj.addProperty("App::PropertyLink", "Base", "Draft", _tip, locked=True) if not "Projection" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The projection vector of this object") - obj.addProperty("App::PropertyVector", "Projection", - "Draft", _tip, locked=True) - obj.Projection = App.Vector(0,0,1) + _tip = QT_TRANSLATE_NOOP("App::Property", "The projection vector of this object") + obj.addProperty("App::PropertyVector", "Projection", "Draft", _tip, locked=True) + obj.Projection = App.Vector(0, 0, 1) if not "ProjectionMode" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The way the viewed object must be projected") - obj.addProperty("App::PropertyEnumeration", "ProjectionMode", - "Draft", _tip, locked=True) - obj.ProjectionMode = ["Solid", "Individual Faces", - "Cutlines", "Cutfaces","Solid faces"] + _tip = QT_TRANSLATE_NOOP("App::Property", "The way the viewed object must be projected") + obj.addProperty( + "App::PropertyEnumeration", "ProjectionMode", "Draft", _tip, locked=True + ) + obj.ProjectionMode = [ + "Solid", + "Individual Faces", + "Cutlines", + "Cutfaces", + "Solid faces", + ] if not "FaceNumbers" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The indices of the faces to be projected in Individual Faces mode") - obj.addProperty("App::PropertyIntegerList", "FaceNumbers", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The indices of the faces to be projected in Individual Faces mode" + ) + obj.addProperty("App::PropertyIntegerList", "FaceNumbers", "Draft", _tip, locked=True) if not "HiddenLines" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Show hidden lines") - obj.addProperty("App::PropertyBool", "HiddenLines", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Show hidden lines") + obj.addProperty("App::PropertyBool", "HiddenLines", "Draft", _tip, locked=True) obj.HiddenLines = False if not "FuseArch" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Fuse wall and structure objects of same type and material") - obj.addProperty("App::PropertyBool", "FuseArch", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Fuse wall and structure objects of same type and material" + ) + obj.addProperty("App::PropertyBool", "FuseArch", "Draft", _tip, locked=True) if not "Tessellation" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Tessellate Ellipses and B-splines into line segments") - obj.addProperty("App::PropertyBool", "Tessellation", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Tessellate Ellipses and B-splines into line segments" + ) + obj.addProperty("App::PropertyBool", "Tessellation", "Draft", _tip, locked=True) obj.Tessellation = False if not "InPlace" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "For Cutlines and Cutfaces modes, this leaves the faces at the cut location") - obj.addProperty("App::PropertyBool", "InPlace", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "For Cutlines and Cutfaces modes, this leaves the faces at the cut location", + ) + obj.addProperty("App::PropertyBool", "InPlace", "Draft", _tip, locked=True) obj.InPlace = True if not "SegmentLength" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Length of line segments if tessellating Ellipses or B-splines into line segments") - obj.addProperty("App::PropertyFloat", "SegmentLength", - "Draft", _tip, locked=True) - obj.SegmentLength = .05 + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Length of line segments if tessellating Ellipses or B-splines into line segments", + ) + obj.addProperty("App::PropertyFloat", "SegmentLength", "Draft", _tip, locked=True) + obj.SegmentLength = 0.05 if not "VisibleOnly" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If this is True, this object will include only visible objects") - obj.addProperty("App::PropertyBool", "VisibleOnly", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "If this is True, this object will include only visible objects" + ) + obj.addProperty("App::PropertyBool", "VisibleOnly", "Draft", _tip, locked=True) obj.VisibleOnly = False if not "ExclusionPoints" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "A list of exclusion points. Any edge touching any of those points will not be drawn.") - obj.addProperty("App::PropertyVectorList", "ExclusionPoints", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "A list of exclusion points. Any edge touching any of those points will not be drawn.", + ) + obj.addProperty( + "App::PropertyVectorList", "ExclusionPoints", "Draft", _tip, locked=True + ) if not "ExclusionNames" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "A list of exclusion object names. Any object viewed that matches a name from the list will not be drawn.") - obj.addProperty("App::PropertyStringList", "ExclusionNames", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "A list of exclusion object names. Any object viewed that matches a name from the list will not be drawn.", + ) + obj.addProperty("App::PropertyStringList", "ExclusionNames", "Draft", _tip, locked=True) if not "OnlySolids" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If this is True, only solid geometry is handled. This overrides the base object's Only Solids property") - obj.addProperty("App::PropertyBool", "OnlySolids", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If this is True, only solid geometry is handled. This overrides the base object's Only Solids property", + ) + obj.addProperty("App::PropertyBool", "OnlySolids", "Draft", _tip, locked=True) if not "Clip" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If this is True, the contents are clipped to the borders of the section plane, if applicable. This overrides the base object's Clip property") - obj.addProperty("App::PropertyBool", "Clip", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If this is True, the contents are clipped to the borders of the section plane, if applicable. This overrides the base object's Clip property", + ) + obj.addProperty("App::PropertyBool", "Clip", "Draft", _tip, locked=True) if not "AutoUpdate" in pl: - _tip = QT_TRANSLATE_NOOP("App::Property", - "This object will be recomputed only if this is True.") - obj.addProperty("App::PropertyBool", "AutoUpdate", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "This object will be recomputed only if this is True." + ) + obj.addProperty("App::PropertyBool", "AutoUpdate", "Draft", _tip, locked=True) obj.AutoUpdate = True - def getProjected(self,obj,shape,direction): - + def getProjected(self, obj, shape, direction): "returns projected edges from a shape and a direction" import Part import TechDraw import DraftGeomUtils + edges = [] _groups = TechDraw.projectEx(shape, direction) for g in _groups[0:5]: @@ -157,22 +164,22 @@ class Shape2DView(DraftObject): for g in _groups[5:]: if not g.isNull(): edges.append(g) - edges = self.cleanExcluded(obj,edges) + edges = self.cleanExcluded(obj, edges) if getattr(obj, "Tessellation", False): - return DraftGeomUtils.cleanProjection(Part.makeCompound(edges), - obj.Tessellation, - obj.SegmentLength) + return DraftGeomUtils.cleanProjection( + Part.makeCompound(edges), obj.Tessellation, obj.SegmentLength + ) else: return Part.makeCompound(edges) - def cleanExcluded(self,obj,shapes): - + def cleanExcluded(self, obj, shapes): """removes any edge touching exclusion points""" import Part + MAXDIST = 0.0001 - if (not hasattr(obj,"ExclusionPoints")) or (not obj.ExclusionPoints): + if (not hasattr(obj, "ExclusionPoints")) or (not obj.ExclusionPoints): return shapes - #verts = [Part.Vertex(obj.Placement.multVec(p)) for p in obj.ExclusionPoints] + # verts = [Part.Vertex(obj.Placement.multVec(p)) for p in obj.ExclusionPoints] verts = [Part.Vertex(p) for p in obj.ExclusionPoints] nedges = [] for s in shapes: @@ -183,14 +190,16 @@ class Shape2DView(DraftObject): if d and (d[0] <= MAXDIST): break except RuntimeError: - print("FIXME: shape2dview: distance unavailable for edge",e,"in",obj.Label) + print( + "FIXME: shape2dview: distance unavailable for edge", e, "in", obj.Label + ) else: nedges.append(e) return nedges - def excludeNames(self,obj,objs): - if hasattr(obj,"ExclusionNames"): - objs = [o for o in objs if not(o.Name in obj.ExclusionNames)] + def excludeNames(self, obj, objs): + if hasattr(obj, "ExclusionNames"): + objs = [o for o in objs if not (o.Name in obj.ExclusionNames)] return objs def _get_shapes(self, shape, onlysolids=False): @@ -203,39 +212,39 @@ class Shape2DView(DraftObject): return [shape.copy()] def execute(self, obj): - if self.props_changed_placement_only(obj) \ - or not getattr(obj, "AutoUpdate", True): + if self.props_changed_placement_only(obj) or not getattr(obj, "AutoUpdate", True): obj.positionBySupport() self.props_changed_clear() return import Part import DraftGeomUtils + pl = obj.Placement if obj.Base: - if utils.get_type(obj.Base) in ["BuildingPart","SectionPlane","IfcAnnotation"]: + if utils.get_type(obj.Base) in ["BuildingPart", "SectionPlane", "IfcAnnotation"]: objs = [] if utils.get_type(obj.Base) == "SectionPlane": - objs = self.excludeNames(obj,obj.Base.Objects) + objs = self.excludeNames(obj, obj.Base.Objects) cutplane = obj.Base.Shape elif utils.get_type(obj.Base) == "IfcAnnotation": # this is a NativeIFC section plane objs, cutplane = obj.Base.Proxy.get_section_data(obj.Base) objs = self.excludeNames(obj, objs) else: - objs = self.excludeNames(obj,obj.Base.Group) + objs = self.excludeNames(obj, obj.Base.Group) cutplane = Part.makePlane(1000, 1000, App.Vector(-500, -500, 0)) m = 1 - if obj.Base.ViewObject and hasattr(obj.Base.ViewObject,"CutMargin"): + if obj.Base.ViewObject and hasattr(obj.Base.ViewObject, "CutMargin"): m = obj.Base.ViewObject.CutMargin.Value - cutplane.translate(App.Vector(0,0,m)) + cutplane.translate(App.Vector(0, 0, m)) cutplane.Placement = cutplane.Placement.multiply(obj.Base.Placement) if objs: onlysolids = True # TODO Fix this : 2025.1.26, why test obj.Base.OnlySolids if override by obj.OnlySolids - if hasattr(obj.Base,"OnlySolids"): + if hasattr(obj.Base, "OnlySolids"): onlysolids = obj.Base.OnlySolids - if hasattr(obj,"OnlySolids"): # override base object + if hasattr(obj, "OnlySolids"): # override base object onlysolids = obj.OnlySolids try: import Arch @@ -243,17 +252,20 @@ class Shape2DView(DraftObject): print("Shape2DView: BIM not present, unable to recompute") return objs = groups.get_group_contents(objs, walls=True) - if getattr(obj,"VisibleOnly",True): + if getattr(obj, "VisibleOnly", True): objs = gui_utils.remove_hidden(objs) shapes = [] - if getattr(obj,"FuseArch", False): + if getattr(obj, "FuseArch", False): shtypes = {} for o in objs: - if utils.get_type(o) in ["Wall","Structure"]: + if utils.get_type(o) in ["Wall", "Structure"]: shtypes.setdefault( - o.Material.Name - if (hasattr(o,"Material") and o.Material) else "None", - [] + ( + o.Material.Name + if (hasattr(o, "Material") and o.Material) + else "None" + ), + [], ).extend(self._get_shapes(o.Shape, onlysolids)) elif hasattr(o, "Shape"): shapes.extend(self._get_shapes(o.Shape, onlysolids)) @@ -281,18 +293,18 @@ class Shape2DView(DraftObject): shapes.extend(self._get_shapes(o.Shape, onlysolids)) clip = False # TODO Fix this : 2025.1.26, why test obj.Base.Clip if override by obj.Clip - if hasattr(obj.Base,"Clip"): + if hasattr(obj.Base, "Clip"): clip = obj.Base.Clip - if hasattr(obj,"Clip"): #override base object + if hasattr(obj, "Clip"): # override base object clip = obj.Clip depth = None - if hasattr(obj.Base,"Depth"): + if hasattr(obj.Base, "Depth"): depth = obj.Base.Depth.Value cutp, cutv, iv = Arch.getCutVolume(cutplane, shapes, clip, depth) cuts = [] opl = App.Placement(obj.Base.Placement) proj = opl.Rotation.multVec(App.Vector(0, 0, 1)) - if obj.ProjectionMode in ["Solid","Solid faces"]: + if obj.ProjectionMode in ["Solid", "Solid faces"]: shapes_to_cut = shapes if obj.ProjectionMode == "Solid faces": shapes_to_cut = [] @@ -302,9 +314,9 @@ class Shape2DView(DraftObject): if cutv and (not cutv.isNull()) and (not sh.isNull()): if sh.Volume < 0: sh.reverse() - #if cutv.BoundBox.intersect(sh.BoundBox): + # if cutv.BoundBox.intersect(sh.BoundBox): # c = sh.cut(cutv) - #else: + # else: # c = sh.copy() try: c = sh.cut(cutv) @@ -316,7 +328,7 @@ class Shape2DView(DraftObject): else: cuts.extend(self._get_shapes(sh, onlysolids)) comp = Part.makeCompound(cuts) - obj.Shape = self.getProjected(obj,comp,proj) + obj.Shape = self.getProjected(obj, comp, proj) elif obj.ProjectionMode in ["Cutlines", "Cutfaces"]: if not cutp: # Cutfaces and Cutlines needs cutp obj.Shape = Part.Shape() @@ -332,7 +344,7 @@ class Shape2DView(DraftObject): facesOrg = sc.Faces if not facesOrg: continue - if hasattr(obj,"InPlace"): + if hasattr(obj, "InPlace"): if obj.InPlace: faces = facesOrg # Alternative approach in https://forum.freecad.org/viewtopic.php?p=807314#p807314, not adopted @@ -340,7 +352,7 @@ class Shape2DView(DraftObject): for faceOrg in facesOrg: if len(faceOrg.Wires) == 1: wireProj = self.getProjected(obj, faceOrg, proj) - #return Compound + # return Compound wireProjWire = Part.Wire(wireProj.Edges) faceProj = Part.Face(wireProjWire) elif len(faceOrg.Wires) == 2: @@ -349,22 +361,28 @@ class Shape2DView(DraftObject): if not w.isEqual(wireClosedOuter): wireClosedInner = w break - wireProjOuter = self.getProjected(obj, wireClosedOuter, proj) - #return Compound + wireProjOuter = self.getProjected( + obj, wireClosedOuter, proj + ) + # return Compound wireProjOuterWire = Part.Wire(wireProjOuter.Edges) faceProj = Part.Face(wireProjOuterWire) - wireProjInner = self.getProjected(obj, wireClosedInner, proj) - #return Compound + wireProjInner = self.getProjected( + obj, wireClosedInner, proj + ) + # return Compound wireProjInnerWire = Part.Wire(wireProjInner.Edges) - faceProj.cutHoles([wireProjInnerWire]) # (list of wires) + faceProj.cutHoles( + [wireProjInnerWire] + ) # (list of wires) faces.append(faceProj) else: c = sh.section(cutp) - if hasattr(obj,"InPlace"): + if hasattr(obj, "InPlace"): if not obj.InPlace: c = self.getProjected(obj, c, proj) - #faces = [] - #if (obj.ProjectionMode == "Cutfaces") and (sh.ShapeType == "Solid"): + # faces = [] + # if (obj.ProjectionMode == "Cutfaces") and (sh.ShapeType == "Solid"): # wires = DraftGeomUtils.findWires(c.Edges) # for w in wires: # if w.isClosed(): @@ -381,21 +399,23 @@ class Shape2DView(DraftObject): elif obj.Base.isDerivedFrom("App::DocumentObjectGroup"): shapes = [] - objs = self.excludeNames(obj,groups.get_group_contents(obj.Base)) + objs = self.excludeNames(obj, groups.get_group_contents(obj.Base)) for o in objs: if hasattr(o, "Shape"): shapes.extend(self._get_shapes(o.Shape)) if shapes: import Part + comp = Part.makeCompound(shapes) - obj.Shape = self.getProjected(obj,comp,obj.Projection) + obj.Shape = self.getProjected(obj, comp, obj.Projection) elif hasattr(obj.Base, "Shape"): if not DraftVecUtils.isNull(obj.Projection): if obj.ProjectionMode == "Solid": - obj.Shape = self.getProjected(obj,obj.Base.Shape,obj.Projection) + obj.Shape = self.getProjected(obj, obj.Base.Shape, obj.Projection) elif obj.ProjectionMode == "Individual Faces": import Part + if obj.FaceNumbers: faces = [] for i in obj.FaceNumbers: @@ -403,11 +423,11 @@ class Shape2DView(DraftObject): faces.append(obj.Base.Shape.Faces[i]) views = [] for f in faces: - views.append(self.getProjected(obj,f,obj.Projection)) + views.append(self.getProjected(obj, f, obj.Projection)) if views: obj.Shape = Part.makeCompound(views) else: - App.Console.PrintWarning(obj.ProjectionMode+" mode not implemented\n") + App.Console.PrintWarning(obj.ProjectionMode + " mode not implemented\n") obj.Placement = pl obj.positionBySupport() diff --git a/src/Mod/Draft/draftobjects/shapestring.py b/src/Mod/Draft/draftobjects/shapestring.py index f2cf266898..70bf1ffba0 100644 --- a/src/Mod/Draft/draftobjects/shapestring.py +++ b/src/Mod/Draft/draftobjects/shapestring.py @@ -66,24 +66,41 @@ class ShapeString(DraftObject): if "Justification" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Horizontal and vertical alignment") obj.addProperty("App::PropertyEnumeration", "Justification", "Draft", _tip, locked=True) - obj.Justification = ["Top-Left", "Top-Center", "Top-Right", - "Middle-Left", "Middle-Center", "Middle-Right", - "Bottom-Left", "Bottom-Center", "Bottom-Right"] + obj.Justification = [ + "Top-Left", + "Top-Center", + "Top-Right", + "Middle-Left", + "Middle-Center", + "Middle-Right", + "Bottom-Left", + "Bottom-Center", + "Bottom-Right", + ] obj.Justification = "Bottom-Left" if "JustificationReference" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Height reference used for justification") - obj.addProperty("App::PropertyEnumeration", "JustificationReference", "Draft", _tip, locked=True) + obj.addProperty( + "App::PropertyEnumeration", "JustificationReference", "Draft", _tip, locked=True + ) obj.JustificationReference = ["Cap Height", "Shape Height"] obj.JustificationReference = "Cap Height" if "KeepLeftMargin" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Keep left margin and leading white space when justification is left") - obj.addProperty("App::PropertyBool", "KeepLeftMargin", "Draft", _tip, locked=True).KeepLeftMargin = False + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Keep left margin and leading white space when justification is left", + ) + obj.addProperty( + "App::PropertyBool", "KeepLeftMargin", "Draft", _tip, locked=True + ).KeepLeftMargin = False if "ScaleToSize" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Scale to ensure cap height is equal to size") - obj.addProperty("App::PropertyBool", "ScaleToSize", "Draft", _tip, locked=True).ScaleToSize = True + obj.addProperty( + "App::PropertyBool", "ScaleToSize", "Draft", _tip, locked=True + ).ScaleToSize = True if "Tracking" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Inter-character spacing") @@ -95,10 +112,15 @@ class ShapeString(DraftObject): if "MakeFace" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Fill letters with faces") - obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True).MakeFace = True + obj.addProperty( + "App::PropertyBool", "MakeFace", "Draft", _tip, locked=True + ).MakeFace = True if "Fuse" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", "Fuse faces if faces overlap, usually not required (can be very slow)") + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Fuse faces if faces overlap, usually not required (can be very slow)", + ) obj.addProperty("App::PropertyBool", "Fuse", "Draft", _tip, locked=True).Fuse = False def onDocumentRestored(self, obj): @@ -106,12 +128,12 @@ class ShapeString(DraftObject): gui_utils.restore_view_object( obj, vp_module="view_shapestring", vp_class="ViewProviderShapeString" ) - if not hasattr(obj, "ObliqueAngle"): # several more properties were added + if not hasattr(obj, "ObliqueAngle"): # several more properties were added self.update_properties_1v0(obj) def update_properties_1v0(self, obj): """Update view properties.""" - old_tracking = obj.Tracking # no need for obj.getTypeIdOfProperty("Tracking") + old_tracking = obj.Tracking # no need for obj.getTypeIdOfProperty("Tracking") obj.removeProperty("Tracking") self.set_properties(obj) obj.KeepLeftMargin = True @@ -123,13 +145,11 @@ class ShapeString(DraftObject): + ", " + "added 'Fuse', 'Justification', 'JustificationReference', 'KeepLeftMargin', " + "'ObliqueAngle' and 'ScaleToSize' properties" - ) + ) _log("v1.0, " + obj.Name + ", changed 'Tracking' property type") def execute(self, obj): - if self.props_changed_placement_only() \ - or not obj.String \ - or not obj.FontFile: + if self.props_changed_placement_only() or not obj.String or not obj.FontFile: obj.positionBySupport() self.props_changed_clear() return @@ -174,10 +194,11 @@ class ShapeString(DraftObject): # https://github.com/FreeCAD/FreeCAD/issues/21501 char_comp = Part.Compound(char) factor = 1 / char_comp.BoundBox.YLength - fill = sum([shape.Area for shape in shapes]) > (0.03 / factor ** 2) \ - and math.isclose(char_comp.BoundBox.DiagonalLength, - Part.Compound(shapes).BoundBox.DiagonalLength, - rel_tol=1e-7) + fill = sum([shape.Area for shape in shapes]) > (0.03 / factor**2) and math.isclose( + char_comp.BoundBox.DiagonalLength, + Part.Compound(shapes).BoundBox.DiagonalLength, + rel_tol=1e-7, + ) chars = Part.makeWireString(obj.String, font_file, obj.Size, obj.Tracking) shapes = [] @@ -208,13 +229,21 @@ class ShapeString(DraftObject): mtx.A12 = math.tan(math.radians(obj.ObliqueAngle)) ss_shape = ss_shape.transformGeometry(mtx) else: - wrn = translate("draft", "ShapeString: oblique angle must be in the -80 to +80 degree range") + "\n" + wrn = ( + translate( + "draft", + "ShapeString: oblique angle must be in the -80 to +80 degree range", + ) + + "\n" + ) App.Console.PrintWarning(wrn) - just_vec = self.justification_vector(ss_shape, - cap_height, - obj.Justification, - obj.JustificationReference, - obj.KeepLeftMargin) + just_vec = self.justification_vector( + ss_shape, + cap_height, + obj.Justification, + obj.JustificationReference, + obj.KeepLeftMargin, + ) shapes = ss_shape.SubShapes for shape in shapes: shape.translate(just_vec) @@ -229,13 +258,17 @@ class ShapeString(DraftObject): def onChanged(self, obj, prop): self.props_changed_store(prop) - def justification_vector(self, ss_shape, cap_height, just, just_ref, keep_left_margin): # ss_shape is a compound + def justification_vector( + self, ss_shape, cap_height, just, just_ref, keep_left_margin + ): # ss_shape is a compound box = ss_shape.optimalBoundingBox() if keep_left_margin is True and "Left" in just: vec = App.Vector(0, 0, 0) else: - vec = App.Vector(-box.XMin, 0, 0) # remove left margin caused by kerning and white space characters - width = box.XLength + vec = App.Vector( + -box.XMin, 0, 0 + ) # remove left margin caused by kerning and white space characters + width = box.XLength if "Shape" in just_ref: vec = vec + App.Vector(0, -box.YMin, 0) height = box.YLength @@ -244,11 +277,11 @@ class ShapeString(DraftObject): if "Top" in just: vec = vec + App.Vector(0, -height, 0) elif "Middle" in just: - vec = vec + App.Vector(0, -height/2, 0) + vec = vec + App.Vector(0, -height / 2, 0) if "Right" in just: vec = vec + App.Vector(-width, 0, 0) elif "Center" in just: - vec = vec + App.Vector(-width/2, 0, 0) + vec = vec + App.Vector(-width / 2, 0, 0) return vec def make_faces(self, wireChar): @@ -307,7 +340,7 @@ class ShapeString(DraftObject): for face in faces: try: # some fonts fail here - if face.normalAt(0, 0).z < 0: # Does not seem to occur for FaceMakerBullseye. + if face.normalAt(0, 0).z < 0: # Does not seem to occur for FaceMakerBullseye. face.reverse() except Exception: pass diff --git a/src/Mod/Draft/draftobjects/text.py b/src/Mod/Draft/draftobjects/text.py index 5f173b2594..27b800f7a2 100644 --- a/src/Mod/Draft/draftobjects/text.py +++ b/src/Mod/Draft/draftobjects/text.py @@ -49,30 +49,24 @@ class Text(DraftAnnotation): properties = obj.PropertiesList if "Placement" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The placement of the base point " - "of the first line") - obj.addProperty("App::PropertyPlacement", - "Placement", - "Base", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The placement of the base point " "of the first line" + ) + obj.addProperty("App::PropertyPlacement", "Placement", "Base", _tip, locked=True) obj.Placement = App.Placement() if "Text" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The text displayed by this object.\n" - "It is a list of strings; each element " - "in the list will be displayed " - "in its own line.") - obj.addProperty("App::PropertyStringList", - "Text", - "Base", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The text displayed by this object.\n" + "It is a list of strings; each element " + "in the list will be displayed " + "in its own line.", + ) + obj.addProperty("App::PropertyStringList", "Text", "Base", _tip, locked=True) obj.Text = [] - def onDocumentRestored(self,obj): + def onDocumentRestored(self, obj): """Execute code when the document is restored.""" super().onDocumentRestored(obj) gui_utils.restore_view_object(obj, vp_module="view_text", vp_class="ViewProviderText") diff --git a/src/Mod/Draft/draftobjects/wire.py b/src/Mod/Draft/draftobjects/wire.py index e04fe8c3a1..e7e2745002 100644 --- a/src/Mod/Draft/draftobjects/wire.py +++ b/src/Mod/Draft/draftobjects/wire.py @@ -45,53 +45,45 @@ class Wire(DraftObject): def __init__(self, obj): super().__init__(obj, "Wire") - _tip = QT_TRANSLATE_NOOP("App::Property", - "The vertices of the wire") - obj.addProperty("App::PropertyVectorList","Points", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The vertices of the wire") + obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "If the wire is closed or not") - obj.addProperty("App::PropertyBool","Closed", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "If the wire is closed or not") + obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The base object is the wire, it's formed from 2 objects") - obj.addProperty("App::PropertyLink","Base", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The base object is the wire, it's formed from 2 objects" + ) + obj.addProperty("App::PropertyLink", "Base", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The tool object is the wire, it's formed from 2 objects") - obj.addProperty("App::PropertyLink","Tool", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The tool object is the wire, it's formed from 2 objects" + ) + obj.addProperty("App::PropertyLink", "Tool", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The start point of this line") - obj.addProperty("App::PropertyVectorDistance","Start", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The start point of this line") + obj.addProperty("App::PropertyVectorDistance", "Start", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The end point of this line") - obj.addProperty("App::PropertyVectorDistance","End", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The end point of this line") + obj.addProperty("App::PropertyVectorDistance", "End", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The length of this line") - obj.addProperty("App::PropertyLength","Length", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The length of this line") + obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Radius to use to fillet the corners") - obj.addProperty("App::PropertyLength","FilletRadius", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corners") + obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Size of the chamfer to give to the corners") - obj.addProperty("App::PropertyLength","ChamferSize", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Size of the chamfer to give to the corners") + obj.addProperty("App::PropertyLength", "ChamferSize", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "Create a face if this object is closed") - obj.addProperty("App::PropertyBool","MakeFace", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this object is closed") + obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The number of subdivisions of each edge") - obj.addProperty("App::PropertyInteger","Subdivisions", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The number of subdivisions of each edge") + obj.addProperty("App::PropertyInteger", "Subdivisions", "Draft", _tip, locked=True) - _tip = QT_TRANSLATE_NOOP("App::Property", - "The area of this object") - obj.addProperty("App::PropertyArea","Area", "Draft",_tip, locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object") + obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True) obj.MakeFace = params.get_param("MakeFaceMode") obj.Closed = False @@ -126,23 +118,26 @@ class Wire(DraftObject): _log("v1.1, " + obj.Name + ", migrated view properties") def execute(self, obj): - if self.props_changed_placement_only(obj): # Supplying obj is required because of `Base` and `Tool`. + if self.props_changed_placement_only( + obj + ): # Supplying obj is required because of `Base` and `Tool`. obj.positionBySupport() self.update_start_end(obj) self.props_changed_clear() return import Part + plm = obj.Placement if obj.Base and (not obj.Tool): if obj.Base.isDerivedFrom("Sketcher::SketchObject"): shape = obj.Base.Shape.copy() if obj.Base.Shape.isClosed(): - if getattr(obj,"MakeFace",True): + if getattr(obj, "MakeFace", True): shape = Part.Face(shape) obj.Shape = shape elif obj.Base and obj.Tool: - if hasattr(obj.Base,'Shape') and hasattr(obj.Tool,'Shape'): + if hasattr(obj.Base, "Shape") and hasattr(obj.Tool, "Shape"): if (not obj.Base.Shape.isNull()) and (not obj.Tool.Shape.isNull()): sh1 = obj.Base.Shape.copy() sh2 = obj.Tool.Shape.copy() @@ -151,41 +146,44 @@ class Wire(DraftObject): shape = DraftGeomUtils.concatenate(shape) obj.Shape = shape p = [] - for v in shape.Vertexes: p.append(v.Point) - if obj.Points != p: obj.Points = p + for v in shape.Vertexes: + p.append(v.Point) + if obj.Points != p: + obj.Points = p elif obj.Points: if obj.Points[0] == obj.Points[-1]: - if not obj.Closed: obj.Closed = True + if not obj.Closed: + obj.Closed = True obj.Points.pop() if obj.Closed and (len(obj.Points) > 2): pts = obj.Points - if getattr(obj,"Subdivisions",0) > 0: + if getattr(obj, "Subdivisions", 0) > 0: npts = [] for i in range(len(pts)): p1 = pts[i] npts.append(pts[i]) - if i == len(pts)-1: + if i == len(pts) - 1: p2 = pts[0] else: - p2 = pts[i+1] + p2 = pts[i + 1] v = p2.sub(p1) - v = DraftVecUtils.scaleTo(v,v.Length/(obj.Subdivisions+1)) + v = DraftVecUtils.scaleTo(v, v.Length / (obj.Subdivisions + 1)) for j in range(obj.Subdivisions): - npts.append(p1.add(App.Vector(v).multiply(j+1))) + npts.append(p1.add(App.Vector(v).multiply(j + 1))) pts = npts - shape = Part.makePolygon(pts+[pts[0]]) + shape = Part.makePolygon(pts + [pts[0]]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: - w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value,chamfer=True) + w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: - w = DraftGeomUtils.filletWire(shape,obj.FilletRadius.Value) + w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w try: - if getattr(obj,"MakeFace",True): + if getattr(obj, "MakeFace", True): shape = Part.Face(shape) except Part.OCCError: pass @@ -194,18 +192,18 @@ class Wire(DraftObject): pts = obj.Points[1:] lp = obj.Points[0] for p in pts: - if not DraftVecUtils.equals(lp,p): - if getattr(obj,"Subdivisions",0) > 0: + if not DraftVecUtils.equals(lp, p): + if getattr(obj, "Subdivisions", 0) > 0: npts = [] v = p.sub(lp) - v = DraftVecUtils.scaleTo(v,v.Length/(obj.Subdivisions+1)) - edges.append(Part.LineSegment(lp,lp.add(v)).toShape()) + v = DraftVecUtils.scaleTo(v, v.Length / (obj.Subdivisions + 1)) + edges.append(Part.LineSegment(lp, lp.add(v)).toShape()) lv = lp.add(v) for j in range(obj.Subdivisions): - edges.append(Part.LineSegment(lv,lv.add(v)).toShape()) + edges.append(Part.LineSegment(lv, lv.add(v)).toShape()) lv = lv.add(v) else: - edges.append(Part.LineSegment(lp,p).toShape()) + edges.append(Part.LineSegment(lp, p).toShape()) lp = p try: shape = Part.Wire(edges) @@ -214,19 +212,19 @@ class Wire(DraftObject): shape = None if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: - w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value,chamfer=True) + w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: - w = DraftGeomUtils.filletWire(shape,obj.FilletRadius.Value) + w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w if shape: obj.Shape = shape - if hasattr(obj,"Area") and hasattr(shape,"Area"): + if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area - if hasattr(obj,"Length"): + if hasattr(obj, "Length"): obj.Length = shape.Length obj.Placement = plm diff --git a/src/Mod/Draft/draftobjects/wpproxy.py b/src/Mod/Draft/draftobjects/wpproxy.py index 110da0b18b..3e1d5c5a1b 100644 --- a/src/Mod/Draft/draftobjects/wpproxy.py +++ b/src/Mod/Draft/draftobjects/wpproxy.py @@ -36,13 +36,13 @@ from draftutils import gui_utils class WorkingPlaneProxy: """The Draft working plane proxy object""" - def __init__(self,obj): + def __init__(self, obj): obj.Proxy = self _tip = QT_TRANSLATE_NOOP("App::Property", "The placement of this object") obj.addProperty("App::PropertyPlacement", "Placement", "Base", _tip, locked=True) - obj.addProperty("Part::PropertyPartShape","Shape","Base","", locked=True) + obj.addProperty("Part::PropertyPartShape", "Shape", "Base", "", locked=True) obj.addExtension("Part::AttachExtensionPython") obj.changeAttacherType("Attacher::AttachEnginePlane") @@ -54,33 +54,32 @@ class WorkingPlaneProxy: obj, vp_module="view_wpproxy", vp_class="ViewProviderWorkingPlaneProxy", format=False ) - def execute(self,obj): + def execute(self, obj): import Part + l = 1 if obj.ViewObject: - if hasattr(obj.ViewObject,"DisplaySize"): + if hasattr(obj.ViewObject, "DisplaySize"): l = obj.ViewObject.DisplaySize.Value - p = Part.makePlane(l, - l, - App.Vector(l/2, -l/2, 0), - App.Vector(0, 0, -1)) + p = Part.makePlane(l, l, App.Vector(l / 2, -l / 2, 0), App.Vector(0, 0, -1)) # make sure the normal direction is pointing outwards, you never know what OCC will decide... - if p.normalAt(0,0).getAngle(obj.Placement.Rotation.multVec(App.Vector(0,0,1))) > 1: + if p.normalAt(0, 0).getAngle(obj.Placement.Rotation.multVec(App.Vector(0, 0, 1))) > 1: p.reverse() p.Placement = obj.Placement obj.Shape = p - def onChanged(self,obj,prop): + def onChanged(self, obj, prop): pass - def getNormal(self,obj): - return obj.Shape.Faces[0].normalAt(0,0) + def getNormal(self, obj): + return obj.Shape.Faces[0].normalAt(0, 0) def dumps(self): return self.Type - def loads(self,state): + def loads(self, state): if state: self.Type = state + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_circulararray.py b/src/Mod/Draft/drafttaskpanels/task_circulararray.py index 7fcceb2957..09b6145d74 100644 --- a/src/Mod/Draft/drafttaskpanels/task_circulararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_circulararray.py @@ -96,11 +96,11 @@ class TaskPanelCircularArray: self.fuse = params.get_param("Draft_array_fuse") self.use_link = params.get_param("Draft_array_Link") - self.form.input_c_x.setProperty('rawValue', self.center.x) - self.form.input_c_y.setProperty('rawValue', self.center.y) - self.form.input_c_z.setProperty('rawValue', self.center.z) - self.form.spinbox_r_distance.setProperty('rawValue', self.r_distance) - self.form.spinbox_tan_distance.setProperty('rawValue', self.tan_distance) + self.form.input_c_x.setProperty("rawValue", self.center.x) + self.form.input_c_y.setProperty("rawValue", self.center.y) + self.form.input_c_z.setProperty("rawValue", self.center.z) + self.form.spinbox_r_distance.setProperty("rawValue", self.r_distance) + self.form.spinbox_tan_distance.setProperty("rawValue", self.tan_distance) self.form.spinbox_number.setValue(self.number) self.form.spinbox_symmetry.setValue(self.symmetry) self.form.checkbox_fuse.setChecked(self.fuse) @@ -129,75 +129,77 @@ class TaskPanelCircularArray: self.form.button_reset.clicked.connect(self.reset_point) # When the checkbox changes, change the internal value - if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 self.form.checkbox_fuse.checkStateChanged.connect(self.set_fuse) self.form.checkbox_link.checkStateChanged.connect(self.set_link) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.form.checkbox_fuse.stateChanged.connect(self.set_fuse) self.form.checkbox_link.stateChanged.connect(self.set_link) - def accept(self): """Execute when clicking the OK button or Enter key.""" self.selection = Gui.Selection.getSelection() - (self.r_distance, - self.tan_distance) = self.get_distances() + (self.r_distance, self.tan_distance) = self.get_distances() - (self.number, - self.symmetry) = self.get_number_symmetry() + (self.number, self.symmetry) = self.get_number_symmetry() self.axis = self.get_axis() self.center = self.get_center() - self.valid_input = self.validate_input(self.selection, - self.r_distance, - self.tan_distance, - self.number, - self.symmetry, - self.axis, - self.center) + self.valid_input = self.validate_input( + self.selection, + self.r_distance, + self.tan_distance, + self.number, + self.symmetry, + self.axis, + self.center, + ) if self.valid_input: self.create_object() # The internal function already displays messages self.finish() - def validate_input(self, selection, - r_distance, tan_distance, - number, symmetry, - axis, center): + def validate_input(self, selection, r_distance, tan_distance, number, symmetry, axis, center): """Check that the input is valid. Some values may not need to be checked because the interface may not allow one to input wrong data. """ if not selection: - _err(translate("draft","At least 1 element must be selected")) + _err(translate("draft", "At least 1 element must be selected")) return False if number < 2: - _err(translate("draft","Number of layers must be at least 2")) + _err(translate("draft", "Number of layers must be at least 2")) return False # TODO: this should handle multiple objects. # Each of the elements of the selection should be tested. obj = selection[0] if obj.isDerivedFrom("App::FeaturePython"): - _err(translate("draft","Selection is not suitable for array")) - _err(translate("draft","Object:") + " {}".format(selection[0].Label)) + _err(translate("draft", "Selection is not suitable for array")) + _err(translate("draft", "Object:") + " {}".format(selection[0].Label)) return False if r_distance == 0: - _wrn(translate("draft","Radial distance is zero. Resulting array may not look correct.")) + _wrn( + translate("draft", "Radial distance is zero. Resulting array may not look correct.") + ) elif r_distance < 0: - _wrn(translate("draft","Radial distance is negative. It is made positive to proceed.")) + _wrn(translate("draft", "Radial distance is negative. It is made positive to proceed.")) self.r_distance = abs(r_distance) if tan_distance == 0: - _err(translate("draft","Tangential distance cannot be 0")) + _err(translate("draft", "Tangential distance cannot be 0")) return False elif tan_distance < 0: - _wrn(translate("draft","Tangential distance is negative. It is made positive to proceed.")) + _wrn( + translate( + "draft", "Tangential distance is negative. It is made positive to proceed." + ) + ) self.tan_distance = abs(tan_distance) # The other arguments are not tested but they should be present. @@ -246,22 +248,23 @@ class TaskPanelCircularArray: _cmd += "use_link=" + str(self.use_link) _cmd += ")" - Gui.addModule('Draft') + Gui.addModule("Draft") - _cmd_list = ["_obj_ = " + _cmd, - "_obj_.Fuse = " + str(self.fuse), - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] + _cmd_list = [ + "_obj_ = " + _cmd, + "_obj_.Fuse = " + str(self.fuse), + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] # We commit the command list through the parent command - self.source_command.commit(translate("draft","Create Circular Array"), _cmd_list) + self.source_command.commit(translate("draft", "Create Circular Array"), _cmd_list) def get_distances(self): """Get the distance parameters from the widgets.""" r_d_str = self.form.spinbox_r_distance.text() tan_d_str = self.form.spinbox_tan_distance.text() - return (U.Quantity(r_d_str).Value, - U.Quantity(tan_d_str).Value) + return (U.Quantity(r_d_str).Value, U.Quantity(tan_d_str).Value) def get_number_symmetry(self): """Get the number and symmetry parameters from the widgets.""" @@ -274,9 +277,9 @@ class TaskPanelCircularArray: c_x_str = self.form.input_c_x.text() c_y_str = self.form.input_c_y.text() c_z_str = self.form.input_c_z.text() - center = App.Vector(U.Quantity(c_x_str).Value, - U.Quantity(c_y_str).Value, - U.Quantity(c_z_str).Value) + center = App.Vector( + U.Quantity(c_x_str).Value, U.Quantity(c_y_str).Value, U.Quantity(c_z_str).Value + ) return center def get_axis(self): @@ -289,9 +292,9 @@ class TaskPanelCircularArray: def reset_point(self): """Reset the center point to the original distance.""" - self.form.input_c_x.setProperty('rawValue', 0) - self.form.input_c_y.setProperty('rawValue', 0) - self.form.input_c_z.setProperty('rawValue', 0) + self.form.input_c_x.setProperty("rawValue", 0) + self.form.input_c_y.setProperty("rawValue", 0) + self.form.input_c_z.setProperty("rawValue", 0) self.center = self.get_center() @@ -301,7 +304,7 @@ class TaskPanelCircularArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Fuse:") + " {}".format(state)) + _msg(translate("draft", "Fuse:") + " {}".format(state)) def set_fuse(self): """Execute as a callback when the fuse checkbox changes.""" @@ -314,14 +317,13 @@ class TaskPanelCircularArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Create Link array:") + " {}".format(state)) + _msg(translate("draft", "Create Link array:") + " {}".format(state)) def set_link(self): """Execute as a callback when the link checkbox changes.""" self.use_link = self.form.checkbox_link.isChecked() params.set_param("Draft_array_Link", self.use_link) - def print_messages(self): """Print messages about the operation.""" if len(self.selection) == 1: @@ -331,15 +333,15 @@ class TaskPanelCircularArray: # For example, it could take the shapes of all objects, # make a compound and then use it as input for the array function. sel_obj = self.selection[0] - _msg(translate("draft","Object:") + " {}".format(sel_obj.Label)) - _msg(translate("draft","Radial distance:") + " {}".format(self.r_distance)) - _msg(translate("draft","Tangential distance:") + " {}".format(self.tan_distance)) - _msg(translate("draft","Number of concentric circles:") + " {}".format(self.number)) - _msg(translate("draft","Symmetry parameter:") + " {}".format(self.symmetry)) - _msg(translate("draft","Center of rotation:") - + " ({0}, {1}, {2})".format(self.center.x, - self.center.y, - self.center.z)) + _msg(translate("draft", "Object:") + " {}".format(sel_obj.Label)) + _msg(translate("draft", "Radial distance:") + " {}".format(self.r_distance)) + _msg(translate("draft", "Tangential distance:") + " {}".format(self.tan_distance)) + _msg(translate("draft", "Number of concentric circles:") + " {}".format(self.number)) + _msg(translate("draft", "Symmetry parameter:") + " {}".format(self.symmetry)) + _msg( + translate("draft", "Center of rotation:") + + " ({0}, {1}, {2})".format(self.center.x, self.center.y, self.center.z) + ) self.print_fuse_state(self.fuse) self.print_link_state(self.use_link) @@ -380,24 +382,24 @@ class TaskPanelCircularArray: # sby = self.form.spinbox_c_y # sbz = self.form.spinbox_c_z if d_p: - if self.mask in ('y', 'z'): + if self.mask in ("y", "z"): # sbx.setText(displayExternal(d_p.x, None, 'Length')) - self.form.input_c_x.setProperty('rawValue', d_p.x) + self.form.input_c_x.setProperty("rawValue", d_p.x) else: # sbx.setText(displayExternal(d_p.x, None, 'Length')) - self.form.input_c_x.setProperty('rawValue', d_p.x) - if self.mask in ('x', 'z'): + self.form.input_c_x.setProperty("rawValue", d_p.x) + if self.mask in ("x", "z"): # sby.setText(displayExternal(d_p.y, None, 'Length')) - self.form.input_c_y.setProperty('rawValue', d_p.y) + self.form.input_c_y.setProperty("rawValue", d_p.y) else: # sby.setText(displayExternal(d_p.y, None, 'Length')) - self.form.input_c_y.setProperty('rawValue', d_p.y) - if self.mask in ('x', 'y'): + self.form.input_c_y.setProperty("rawValue", d_p.y) + if self.mask in ("x", "y"): # sbz.setText(displayExternal(d_p.z, None, 'Length')) - self.form.input_c_z.setProperty('rawValue', d_p.z) + self.form.input_c_z.setProperty("rawValue", d_p.z) else: # sbz.setText(displayExternal(d_p.z, None, 'Length')) - self.form.input_c_z.setProperty('rawValue', d_p.z) + self.form.input_c_z.setProperty("rawValue", d_p.z) if plane: pass @@ -452,4 +454,5 @@ class TaskPanelCircularArray: # Runs the parent command to complete the call self.source_command.completed() + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_orthoarray.py b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py index 619c9f3f50..14cfba6bbf 100644 --- a/src/Mod/Draft/drafttaskpanels/task_orthoarray.py +++ b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py @@ -94,17 +94,17 @@ class TaskPanelOrthoArray: self.v_y = App.Vector(0, start_y, 0) self.v_z = App.Vector(0, 0, start_z) - self.form.input_X_x.setProperty('rawValue', self.v_x.x) - self.form.input_X_y.setProperty('rawValue', self.v_x.y) - self.form.input_X_z.setProperty('rawValue', self.v_x.z) + self.form.input_X_x.setProperty("rawValue", self.v_x.x) + self.form.input_X_y.setProperty("rawValue", self.v_x.y) + self.form.input_X_z.setProperty("rawValue", self.v_x.z) - self.form.input_Y_x.setProperty('rawValue', self.v_y.x) - self.form.input_Y_y.setProperty('rawValue', self.v_y.y) - self.form.input_Y_z.setProperty('rawValue', self.v_y.z) + self.form.input_Y_x.setProperty("rawValue", self.v_y.x) + self.form.input_Y_y.setProperty("rawValue", self.v_y.y) + self.form.input_Y_z.setProperty("rawValue", self.v_y.z) - self.form.input_Z_x.setProperty('rawValue', self.v_z.x) - self.form.input_Z_y.setProperty('rawValue', self.v_z.y) - self.form.input_Z_z.setProperty('rawValue', self.v_z.z) + self.form.input_Z_x.setProperty("rawValue", self.v_z.x) + self.form.input_Z_y.setProperty("rawValue", self.v_z.y) + self.form.input_Z_z.setProperty("rawValue", self.v_z.z) self.n_x = params.get_param("XNumOfElements", "Mod/Draft/OrthoArrayLinearMode") self.n_y = params.get_param("YNumOfElements", "Mod/Draft/OrthoArrayLinearMode") @@ -154,10 +154,10 @@ class TaskPanelOrthoArray: self.form.button_reset_Z.clicked.connect(lambda: self.reset_v("Z")) # When the checkbox changes, change the internal value - if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 self.form.checkbox_fuse.checkStateChanged.connect(self.set_fuse) self.form.checkbox_link.checkStateChanged.connect(self.set_link) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.form.checkbox_fuse.stateChanged.connect(self.set_fuse) self.form.checkbox_link.stateChanged.connect(self.set_link) @@ -167,71 +167,72 @@ class TaskPanelOrthoArray: self.form.radiobutton_y_axis.clicked.connect(lambda: self.set_active_axis("Y")) self.form.radiobutton_z_axis.clicked.connect(lambda: self.set_active_axis("Z")) - def accept(self): """Execute when clicking the OK button or Enter key.""" self.selection = Gui.Selection.getSelection() - (self.v_x, - self.v_y, - self.v_z) = self.get_intervals() + (self.v_x, self.v_y, self.v_z) = self.get_intervals() - (self.n_x, - self.n_y, - self.n_z) = self.get_numbers() + (self.n_x, self.n_y, self.n_z) = self.get_numbers() - self.valid_input = self.validate_input(self.selection, - self.v_x, self.v_y, self.v_z, - self.n_x, self.n_y, self.n_z) + self.valid_input = self.validate_input( + self.selection, self.v_x, self.v_y, self.v_z, self.n_x, self.n_y, self.n_z + ) if self.valid_input: axis_values = { - 'X': (self.v_x.x, self.n_x), - 'Y': (self.v_y.y, self.n_y), - 'Z': (self.v_z.z, self.n_z), + "X": (self.v_x.x, self.n_x), + "Y": (self.v_y.y, self.n_y), + "Z": (self.v_z.z, self.n_z), } values = axis_values.get(self.active_axis) if values is not None: interval, num_elements = values # Set interval - params.set_param(f"{self.active_axis}Interval", interval, "Mod/Draft/OrthoArrayLinearMode") + params.set_param( + f"{self.active_axis}Interval", interval, "Mod/Draft/OrthoArrayLinearMode" + ) # Set number of elements - params.set_param(f"{self.active_axis}NumOfElements", num_elements, "Mod/Draft/OrthoArrayLinearMode") + params.set_param( + f"{self.active_axis}NumOfElements", + num_elements, + "Mod/Draft/OrthoArrayLinearMode", + ) self.create_object() # The internal function already displays messages self.finish() - def validate_input(self, selection, - v_x, v_y, v_z, - n_x, n_y, n_z): + def validate_input(self, selection, v_x, v_y, v_z, n_x, n_y, n_z): """Check that the input is valid. Some values may not need to be checked because the interface may not allow one to input wrong data. """ if not selection: - _err(translate("draft","At least 1 element must be selected")) + _err(translate("draft", "At least 1 element must be selected")) return False if n_x < 1 or n_y < 1 or n_z < 1: - _err(translate("draft","Number of elements must be at least 1")) + _err(translate("draft", "Number of elements must be at least 1")) return False # TODO: this should handle multiple objects. # Each of the elements of the selection should be tested. obj = selection[0] if obj.isDerivedFrom("App::FeaturePython"): - _err(translate("draft","Selection is not suitable for array")) - _err(translate("draft","Object:") + " {0} ({1})".format(obj.Label, obj.TypeId)) + _err(translate("draft", "Selection is not suitable for array")) + _err(translate("draft", "Object:") + " {0} ({1})".format(obj.Label, obj.TypeId)) return False # we should not ever do this but maybe a sanity check here? if self.linear_mode: - if not (self.form.radiobutton_x_axis.isChecked() or - self.form.radiobutton_y_axis.isChecked() or - self.form.radiobutton_z_axis.isChecked()): - _err(translate("draft","In linear mode, at least 1 axis must be selected")) + if not ( + self.form.radiobutton_x_axis.isChecked() + or self.form.radiobutton_y_axis.isChecked() + or self.form.radiobutton_z_axis.isChecked() + ): + _err(translate("draft", "In linear mode, at least 1 axis must be selected")) return False # The other arguments are not tested but they should be present. @@ -293,44 +294,48 @@ class TaskPanelOrthoArray: _cmd += "use_link=" + str(self.use_link) _cmd += ")" - Gui.addModule('Draft') + Gui.addModule("Draft") - _cmd_list = ["_obj_ = " + _cmd, - "_obj_.Fuse = " + str(self.fuse), - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] + _cmd_list = [ + "_obj_ = " + _cmd, + "_obj_.Fuse = " + str(self.fuse), + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] # We commit the command list through the parent command - self.source_command.commit(translate("draft","Create Orthogonal Array"), _cmd_list) + self.source_command.commit(translate("draft", "Create Orthogonal Array"), _cmd_list) def get_numbers(self): """Get the number of elements from the widgets.""" - return (self.form.spinbox_n_X.value(), - self.form.spinbox_n_Y.value(), - self.form.spinbox_n_Z.value()) + return ( + self.form.spinbox_n_X.value(), + self.form.spinbox_n_Y.value(), + self.form.spinbox_n_Z.value(), + ) def get_intervals(self): """Get the interval vectors from the widgets.""" v_x_x_str = self.form.input_X_x.text() v_x_y_str = self.form.input_X_y.text() v_x_z_str = self.form.input_X_z.text() - v_x = App.Vector(U.Quantity(v_x_x_str).Value, - U.Quantity(v_x_y_str).Value, - U.Quantity(v_x_z_str).Value) + v_x = App.Vector( + U.Quantity(v_x_x_str).Value, U.Quantity(v_x_y_str).Value, U.Quantity(v_x_z_str).Value + ) v_y_x_str = self.form.input_Y_x.text() v_y_y_str = self.form.input_Y_y.text() v_y_z_str = self.form.input_Y_z.text() - v_y = App.Vector(U.Quantity(v_y_x_str).Value, - U.Quantity(v_y_y_str).Value, - U.Quantity(v_y_z_str).Value) + v_y = App.Vector( + U.Quantity(v_y_x_str).Value, U.Quantity(v_y_y_str).Value, U.Quantity(v_y_z_str).Value + ) v_z_x_str = self.form.input_Z_x.text() v_z_y_str = self.form.input_Z_y.text() v_z_z_str = self.form.input_Z_z.text() - v_z = App.Vector(U.Quantity(v_z_x_str).Value, - U.Quantity(v_z_y_str).Value, - U.Quantity(v_z_z_str).Value) + v_z = App.Vector( + U.Quantity(v_z_x_str).Value, U.Quantity(v_z_y_str).Value, U.Quantity(v_z_z_str).Value + ) return v_x, v_y, v_z def reset_v(self, interval): @@ -343,19 +348,19 @@ class TaskPanelOrthoArray: for that direction. """ if interval == "X": - self.form.input_X_x.setProperty('rawValue', 100) - self.form.input_X_y.setProperty('rawValue', 0) - self.form.input_X_z.setProperty('rawValue', 0) + self.form.input_X_x.setProperty("rawValue", 100) + self.form.input_X_y.setProperty("rawValue", 0) + self.form.input_X_z.setProperty("rawValue", 0) self.v_x, self.v_y, self.v_z = self.get_intervals() elif interval == "Y": - self.form.input_Y_x.setProperty('rawValue', 0) - self.form.input_Y_y.setProperty('rawValue', 100) - self.form.input_Y_z.setProperty('rawValue', 0) + self.form.input_Y_x.setProperty("rawValue", 0) + self.form.input_Y_y.setProperty("rawValue", 100) + self.form.input_Y_z.setProperty("rawValue", 0) self.v_x, self.v_y, self.v_z = self.get_intervals() elif interval == "Z": - self.form.input_Z_x.setProperty('rawValue', 0) - self.form.input_Z_y.setProperty('rawValue', 0) - self.form.input_Z_z.setProperty('rawValue', 100) + self.form.input_Z_x.setProperty("rawValue", 0) + self.form.input_Z_y.setProperty("rawValue", 0) + self.form.input_Z_z.setProperty("rawValue", 100) self.v_x, self.v_y, self.v_z = self.get_intervals() def print_fuse_state(self, fuse): @@ -364,7 +369,7 @@ class TaskPanelOrthoArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Fuse:") + " {}".format(state)) + _msg(translate("draft", "Fuse:") + " {}".format(state)) def set_fuse(self): """Execute as a callback when the fuse checkbox changes.""" @@ -377,7 +382,7 @@ class TaskPanelOrthoArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Create link array:") + " {}".format(state)) + _msg(translate("draft", "Create link array:") + " {}".format(state)) def set_link(self): """Execute as a callback when the link checkbox changes.""" @@ -393,23 +398,23 @@ class TaskPanelOrthoArray: # For example, it could take the shapes of all objects, # make a compound and then use it as input for the array function. sel_obj = self.selection[0] - _msg(translate("draft","Object:") + " {}".format(sel_obj.Label)) + _msg(translate("draft", "Object:") + " {}".format(sel_obj.Label)) - _msg(translate("draft","Number of X elements:") + " {}".format(self.n_x)) - _msg(translate("draft","Interval X:") - + " ({0}, {1}, {2})".format(self.v_x.x, - self.v_x.y, - self.v_x.z)) - _msg(translate("draft","Number of Y elements:") + " {}".format(self.n_y)) - _msg(translate("draft","Interval Y:") - + " ({0}, {1}, {2})".format(self.v_y.x, - self.v_y.y, - self.v_y.z)) - _msg(translate("draft","Number of Z elements:") + " {}".format(self.n_z)) - _msg(translate("draft","Interval Z:") - + " ({0}, {1}, {2})".format(self.v_z.x, - self.v_z.y, - self.v_z.z)) + _msg(translate("draft", "Number of X elements:") + " {}".format(self.n_x)) + _msg( + translate("draft", "Interval X:") + + " ({0}, {1}, {2})".format(self.v_x.x, self.v_x.y, self.v_x.z) + ) + _msg(translate("draft", "Number of Y elements:") + " {}".format(self.n_y)) + _msg( + translate("draft", "Interval Y:") + + " ({0}, {1}, {2})".format(self.v_y.x, self.v_y.y, self.v_y.z) + ) + _msg(translate("draft", "Number of Z elements:") + " {}".format(self.n_z)) + _msg( + translate("draft", "Interval Z:") + + " ({0}, {1}, {2})".format(self.v_z.x, self.v_z.y, self.v_z.z) + ) self.print_fuse_state(self.fuse) self.print_link_state(self.use_link) @@ -421,7 +426,7 @@ class TaskPanelOrthoArray: """Toggle between Linear mode and Orthogonal mode.""" self.linear_mode = self.form.button_linear_mode.isChecked() self.toggle_axis_radiobuttons(self.linear_mode) - params.set_param("LinearModeOn" , self.linear_mode, "Mod/Draft/OrthoArrayLinearMode") + params.set_param("LinearModeOn", self.linear_mode, "Mod/Draft/OrthoArrayLinearMode") if self.linear_mode: self.form.button_linear_mode.setText(translate("draft", "Switch to Ortho Mode")) @@ -446,7 +451,7 @@ class TaskPanelOrthoArray: case "Z": title = translate("draft", "Z-Axis") self.form.group_linearmode.setTitle(title) - else: # ortho mode + else: # ortho mode self.form.button_linear_mode.setText(translate("draft", "Switch to Linear Mode")) # For ortho mode we're showing back default groupboxes and we reparent everything @@ -458,9 +463,11 @@ class TaskPanelOrthoArray: def toggle_axis_radiobuttons(self, show): """Show or hide the axis radio buttons.""" - for radiobutton in [self.form.radiobutton_x_axis, - self.form.radiobutton_y_axis, - self.form.radiobutton_z_axis]: + for radiobutton in [ + self.form.radiobutton_x_axis, + self.form.radiobutton_y_axis, + self.form.radiobutton_z_axis, + ]: radiobutton.setVisible(show) def set_active_axis(self, axis): @@ -483,7 +490,6 @@ class TaskPanelOrthoArray: title = translate("draft", "Z-Axis") self.form.group_linearmode.setTitle(title) - def update_axis_ui(self): """Update the UI to reflect the current axis selection.""" # Make sure only one axis is selected @@ -494,9 +500,9 @@ class TaskPanelOrthoArray: def _get_axis_widgets(self, axis): """Get all widgets for a specific axis.""" return { - 'spinbox_elements': getattr(self.form, f"spinbox_n_{axis}", None), - 'spinbox_interval': getattr(self.form, f"input_{axis}_{axis.lower()}", None), - 'button_reset': getattr(self.form, f"button_reset_{axis}", None) + "spinbox_elements": getattr(self.form, f"spinbox_n_{axis}", None), + "spinbox_interval": getattr(self.form, f"input_{axis}_{axis.lower()}", None), + "button_reset": getattr(self.form, f"button_reset_{axis}", None), } def _clear_linear_mode_layout(self): @@ -525,8 +531,8 @@ class TaskPanelOrthoArray: # Add widgets to layout widget_pairs = [ - (label_elements, widgets['spinbox_elements']), - (label_interval, widgets['spinbox_interval']) + (label_elements, widgets["spinbox_elements"]), + (label_interval, widgets["spinbox_interval"]), ] for row_index, (label, widget) in enumerate(widget_pairs): @@ -536,8 +542,8 @@ class TaskPanelOrthoArray: group_layout.addWidget(widget, row_index, 1) # Add reset button spanning both columns - widgets['button_reset'].setParent(self.form.group_linearmode) - group_layout.addWidget(widgets['button_reset'], 2, 0, 1, 2) + widgets["button_reset"].setParent(self.form.group_linearmode) + group_layout.addWidget(widgets["button_reset"], 2, 0, 1, 2) def _restore_axis_to_ortho_layout(self, axis, row_index): """Restore widgets for a specific axis back to their original Ortho layout positions.""" @@ -545,16 +551,16 @@ class TaskPanelOrthoArray: # Restore spinbox elements to grid layout grid_number_layout = self.form.findChild(QtWidgets.QGridLayout, "grid_number") - grid_number_layout.addWidget(widgets['spinbox_elements'], row_index, 1) + grid_number_layout.addWidget(widgets["spinbox_elements"], row_index, 1) # Restore interval input to its axis-specific inner grid layout inner_grid_layout = self.form.findChild(QtWidgets.QGridLayout, f"grid_{axis}") - inner_grid_layout.addWidget(widgets['spinbox_interval'], row_index, 1) + inner_grid_layout.addWidget(widgets["spinbox_interval"], row_index, 1) # Restore reset button to its axis group group_box = self.form.findChild(QtWidgets.QGroupBox, f"group_{axis}") group_axis_layout = group_box.layout() - group_axis_layout.addWidget(widgets['button_reset'], 1, 0) + group_axis_layout.addWidget(widgets["button_reset"], 1, 0) def _setup_ortho_mode_layout(self): """Restore all widgets back to their original Ortho mode layout positions.""" @@ -592,4 +598,5 @@ class TaskPanelOrthoArray: # Runs the parent command to complete the call self.source_command.completed() + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_polararray.py b/src/Mod/Draft/drafttaskpanels/task_polararray.py index 7952741409..0c426d0b2d 100644 --- a/src/Mod/Draft/drafttaskpanels/task_polararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_polararray.py @@ -91,10 +91,10 @@ class TaskPanelPolarArray: self.fuse = params.get_param("Draft_array_fuse") self.use_link = params.get_param("Draft_array_Link") - self.form.input_c_x.setProperty('rawValue', self.center.x) - self.form.input_c_y.setProperty('rawValue', self.center.y) - self.form.input_c_z.setProperty('rawValue', self.center.z) - self.form.spinbox_angle.setProperty('rawValue', self.angle) + self.form.input_c_x.setProperty("rawValue", self.center.x) + self.form.input_c_y.setProperty("rawValue", self.center.y) + self.form.input_c_z.setProperty("rawValue", self.center.z) + self.form.spinbox_angle.setProperty("rawValue", self.angle) self.form.spinbox_number.setValue(self.number) self.form.checkbox_fuse.setChecked(self.fuse) self.form.checkbox_link.setChecked(self.use_link) @@ -122,61 +122,63 @@ class TaskPanelPolarArray: self.form.button_reset.clicked.connect(self.reset_point) # When the checkbox changes, change the internal value - if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.form.checkbox_fuse, "checkStateChanged"): # Qt version >= 6.7.0 self.form.checkbox_fuse.checkStateChanged.connect(self.set_fuse) self.form.checkbox_link.checkStateChanged.connect(self.set_link) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.form.checkbox_fuse.stateChanged.connect(self.set_fuse) self.form.checkbox_link.stateChanged.connect(self.set_link) - def accept(self): """Execute when clicking the OK button or Enter key.""" self.selection = Gui.Selection.getSelection() - (self.number, - self.angle) = self.get_number_angle() + (self.number, self.angle) = self.get_number_angle() self.center = self.get_center() - self.valid_input = self.validate_input(self.selection, - self.number, - self.angle, - self.center) + self.valid_input = self.validate_input(self.selection, self.number, self.angle, self.center) if self.valid_input: self.create_object() # The internal function already displays messages # self.print_messages() self.finish() - def validate_input(self, selection, - number, angle, center): + def validate_input(self, selection, number, angle, center): """Check that the input is valid. Some values may not need to be checked because the interface may not allow one to input wrong data. """ if not selection: - _err(translate("draft","At least 1 element must be selected")) + _err(translate("draft", "At least 1 element must be selected")) return False # TODO: this should handle multiple objects. # Each of the elements of the selection should be tested. obj = selection[0] if obj.isDerivedFrom("App::FeaturePython"): - _err(translate("draft","Selection is not suitable for array")) - _err(translate("draft","Object:") + " {}".format(selection[0].Label)) + _err(translate("draft", "Selection is not suitable for array")) + _err(translate("draft", "Object:") + " {}".format(selection[0].Label)) return False if number < 2: - _err(translate("draft","Number of elements must be at least 2")) + _err(translate("draft", "Number of elements must be at least 2")) return False if angle > 360: - _wrn(translate("draft","The angle is above 360 degrees. It is set to this value to proceed.")) + _wrn( + translate( + "draft", "The angle is above 360 degrees. It is set to this value to proceed." + ) + ) self.angle = 360 elif angle < -360: - _wrn(translate("draft","The angle is below -360 degrees. It is set to this value to proceed.")) + _wrn( + translate( + "draft", "The angle is below -360 degrees. It is set to this value to proceed." + ) + ) self.angle = -360 # The other arguments are not tested but they should be present. @@ -220,15 +222,17 @@ class TaskPanelPolarArray: _cmd += "use_link=" + str(self.use_link) _cmd += ")" - Gui.addModule('Draft') + Gui.addModule("Draft") - _cmd_list = ["_obj_ = " + _cmd, - "_obj_.Fuse = " + str(self.fuse), - "Draft.autogroup(_obj_)", - "App.ActiveDocument.recompute()"] + _cmd_list = [ + "_obj_ = " + _cmd, + "_obj_.Fuse = " + str(self.fuse), + "Draft.autogroup(_obj_)", + "App.ActiveDocument.recompute()", + ] # We commit the command list through the parent command - self.source_command.commit(translate("draft","Create Polar Array"), _cmd_list) + self.source_command.commit(translate("draft", "Create Polar Array"), _cmd_list) def get_number_angle(self): """Get the number and angle parameters from the widgets.""" @@ -243,16 +247,16 @@ class TaskPanelPolarArray: c_x_str = self.form.input_c_x.text() c_y_str = self.form.input_c_y.text() c_z_str = self.form.input_c_z.text() - center = App.Vector(U.Quantity(c_x_str).Value, - U.Quantity(c_y_str).Value, - U.Quantity(c_z_str).Value) + center = App.Vector( + U.Quantity(c_x_str).Value, U.Quantity(c_y_str).Value, U.Quantity(c_z_str).Value + ) return center def reset_point(self): """Reset the center point to the original distance.""" - self.form.input_c_x.setProperty('rawValue', 0) - self.form.input_c_y.setProperty('rawValue', 0) - self.form.input_c_z.setProperty('rawValue', 0) + self.form.input_c_x.setProperty("rawValue", 0) + self.form.input_c_y.setProperty("rawValue", 0) + self.form.input_c_z.setProperty("rawValue", 0) self.center = self.get_center() @@ -262,7 +266,7 @@ class TaskPanelPolarArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Fuse:") + " {}".format(state)) + _msg(translate("draft", "Fuse:") + " {}".format(state)) def set_fuse(self): """Execute as a callback when the fuse checkbox changes.""" @@ -275,7 +279,7 @@ class TaskPanelPolarArray: state = self.tr_true else: state = self.tr_false - _msg(translate("draft","Create link array:") + " {}".format(state)) + _msg(translate("draft", "Create link array:") + " {}".format(state)) def set_link(self): """Execute as a callback when the link checkbox changes.""" @@ -291,13 +295,13 @@ class TaskPanelPolarArray: # For example, it could take the shapes of all objects, # make a compound and then use it as input for the array function. sel_obj = self.selection[0] - _msg(translate("draft","Object:") + " {}".format(sel_obj.Label)) - _msg(translate("draft","Number of elements:") + " {}".format(self.number)) - _msg(translate("draft","Polar angle:") + " {}".format(self.angle)) - _msg(translate("draft","Center of rotation:") - + " ({0}, {1}, {2})".format(self.center.x, - self.center.y, - self.center.z)) + _msg(translate("draft", "Object:") + " {}".format(sel_obj.Label)) + _msg(translate("draft", "Number of elements:") + " {}".format(self.number)) + _msg(translate("draft", "Polar angle:") + " {}".format(self.angle)) + _msg( + translate("draft", "Center of rotation:") + + " ({0}, {1}, {2})".format(self.center.x, self.center.y, self.center.z) + ) self.print_fuse_state(self.fuse) self.print_link_state(self.use_link) @@ -338,24 +342,24 @@ class TaskPanelPolarArray: # sby = self.form.spinbox_c_y # sbz = self.form.spinbox_c_z if dp: - if self.mask in ('y', 'z'): + if self.mask in ("y", "z"): # sbx.setText(displayExternal(dp.x, None, 'Length')) - self.form.input_c_x.setProperty('rawValue', dp.x) + self.form.input_c_x.setProperty("rawValue", dp.x) else: # sbx.setText(displayExternal(dp.x, None, 'Length')) - self.form.input_c_x.setProperty('rawValue', dp.x) - if self.mask in ('x', 'z'): + self.form.input_c_x.setProperty("rawValue", dp.x) + if self.mask in ("x", "z"): # sby.setText(displayExternal(dp.y, None, 'Length')) - self.form.input_c_y.setProperty('rawValue', dp.y) + self.form.input_c_y.setProperty("rawValue", dp.y) else: # sby.setText(displayExternal(dp.y, None, 'Length')) - self.form.input_c_y.setProperty('rawValue', dp.y) - if self.mask in ('x', 'y'): + self.form.input_c_y.setProperty("rawValue", dp.y) + if self.mask in ("x", "y"): # sbz.setText(displayExternal(dp.z, None, 'Length')) - self.form.input_c_z.setProperty('rawValue', dp.z) + self.form.input_c_z.setProperty("rawValue", dp.z) else: # sbz.setText(displayExternal(dp.z, None, 'Length')) - self.form.input_c_z.setProperty('rawValue', dp.z) + self.form.input_c_z.setProperty("rawValue", dp.z) if plane: pass @@ -410,4 +414,5 @@ class TaskPanelPolarArray: # Runs the parent command to complete the call self.source_command.completed() + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_scale.py b/src/Mod/Draft/drafttaskpanels/task_scale.py index 89c6159ab1..d92efb9b1c 100644 --- a/src/Mod/Draft/drafttaskpanels/task_scale.py +++ b/src/Mod/Draft/drafttaskpanels/task_scale.py @@ -57,32 +57,32 @@ class ScaleTaskPanel: self.xValue.setRange(-1000000.0, 1000000.0) self.xValue.setDecimals(decimals) self.xValue.setValue(1) - layout.addWidget(self.xValue,0,1,1,1) + layout.addWidget(self.xValue, 0, 1, 1, 1) self.yLabel = QtWidgets.QLabel() self.yLabel.setText(translate("Draft", "Y-factor")) - layout.addWidget(self.yLabel,1,0,1,1) + layout.addWidget(self.yLabel, 1, 0, 1, 1) self.yValue = QtWidgets.QDoubleSpinBox() self.yValue.setRange(-1000000.0, 1000000.0) self.yValue.setDecimals(decimals) self.yValue.setValue(1) - layout.addWidget(self.yValue,1,1,1,1) + layout.addWidget(self.yValue, 1, 1, 1, 1) self.zLabel = QtWidgets.QLabel() self.zLabel.setText(translate("Draft", "Z-factor")) - layout.addWidget(self.zLabel,2,0,1,1) + layout.addWidget(self.zLabel, 2, 0, 1, 1) self.zValue = QtWidgets.QDoubleSpinBox() self.zValue.setRange(-1000000.0, 1000000.0) self.zValue.setDecimals(decimals) self.zValue.setValue(1) - layout.addWidget(self.zValue,2,1,1,1) + layout.addWidget(self.zValue, 2, 1, 1, 1) self.lock = QtWidgets.QCheckBox() self.lock.setText(translate("Draft", "Uniform scaling")) self.lock.setChecked(params.get_param("ScaleUniform")) - layout.addWidget(self.lock,3,0,1,2) + layout.addWidget(self.lock, 3, 0, 1, 2) - QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) - QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) - QtCore.QObject.connect(self.lock,QtCore.SIGNAL("toggled(bool)"),self.setLock) + QtCore.QObject.connect(self.xValue, QtCore.SIGNAL("valueChanged(double)"), self.setValue) + QtCore.QObject.connect(self.yValue, QtCore.SIGNAL("valueChanged(double)"), self.setValue) + QtCore.QObject.connect(self.zValue, QtCore.SIGNAL("valueChanged(double)"), self.setValue) + QtCore.QObject.connect(self.lock, QtCore.SIGNAL("toggled(bool)"), self.setLock) if self.__class__.__name__ != "ScaleTaskPanelEdit": # ScaleRelative option removed in v1.1 as it does not work properly: @@ -93,24 +93,26 @@ class ScaleTaskPanel: self.isCopy = QtWidgets.QCheckBox() self.isCopy.setText(translate("Draft", "Copy")) self.isCopy.setChecked(params.get_param("ScaleCopy")) - layout.addWidget(self.isCopy,5,0,1,2) + layout.addWidget(self.isCopy, 5, 0, 1, 2) self.isSubelementMode = QtWidgets.QCheckBox() self.isSubelementMode.setText(translate("Draft", "Modify subelements")) self.isSubelementMode.setChecked(params.get_param("SubelementMode")) - layout.addWidget(self.isSubelementMode,6,0,1,2) + layout.addWidget(self.isSubelementMode, 6, 0, 1, 2) self.isClone = QtWidgets.QCheckBox() self.isClone.setText(translate("Draft", "Create a clone")) self.isClone.setChecked(params.get_param("ScaleClone")) - layout.addWidget(self.isClone,7,0,1,2) + layout.addWidget(self.isClone, 7, 0, 1, 2) self.pickrefButton = QtWidgets.QPushButton() self.pickrefButton.setText(translate("Draft", "Pick From/To Points")) - layout.addWidget(self.pickrefButton,8,0,1,2) + layout.addWidget(self.pickrefButton, 8, 0, 1, 2) # QtCore.QObject.connect(self.relative,QtCore.SIGNAL("toggled(bool)"),self.setRelative) - QtCore.QObject.connect(self.isCopy,QtCore.SIGNAL("toggled(bool)"),self.setCopy) - QtCore.QObject.connect(self.isSubelementMode,QtCore.SIGNAL("toggled(bool)"),self.setSubelementMode) - QtCore.QObject.connect(self.isClone,QtCore.SIGNAL("toggled(bool)"),self.setClone) - QtCore.QObject.connect(self.pickrefButton,QtCore.SIGNAL("clicked()"),self.pickRef) + QtCore.QObject.connect(self.isCopy, QtCore.SIGNAL("toggled(bool)"), self.setCopy) + QtCore.QObject.connect( + self.isSubelementMode, QtCore.SIGNAL("toggled(bool)"), self.setSubelementMode + ) + QtCore.QObject.connect(self.isClone, QtCore.SIGNAL("toggled(bool)"), self.setClone) + QtCore.QObject.connect(self.pickrefButton, QtCore.SIGNAL("clicked()"), self.pickRef) def setValue(self, val=None): """Set the value of the scale factors.""" @@ -226,7 +228,7 @@ class ScaleTaskPanelEdit(ScaleTaskPanel): mtx = mtx * self.global_place.Matrix.inverse() delta = self.global_place.inverse().Rotation.multVec(self.global_place.Base) - delta = -App.Vector(delta.x*x, delta.y*y, delta.z*z) + delta = -App.Vector(delta.x * x, delta.y * y, delta.z * z) delta = self.global_place.multVec(delta) self.ghost.setMatrix(mtx) @@ -266,4 +268,5 @@ class ScaleTaskPanelEdit(ScaleTaskPanel): Gui.Control.closeDialog() return None + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_selectplane.py b/src/Mod/Draft/drafttaskpanels/task_selectplane.py index a841572cb4..d391d951b9 100644 --- a/src/Mod/Draft/drafttaskpanels/task_selectplane.py +++ b/src/Mod/Draft/drafttaskpanels/task_selectplane.py @@ -53,4 +53,5 @@ class SelectPlaneTaskPanel: """Execute to set the standard buttons.""" return QtWidgets.QDialogButtonBox.Close + ## @} diff --git a/src/Mod/Draft/drafttaskpanels/task_shapestring.py b/src/Mod/Draft/drafttaskpanels/task_shapestring.py index 30384656a8..d8ed5d9cc1 100644 --- a/src/Mod/Draft/drafttaskpanels/task_shapestring.py +++ b/src/Mod/Draft/drafttaskpanels/task_shapestring.py @@ -86,9 +86,9 @@ class ShapeStringTaskPanel: self.form.sbX.valueChanged.connect(self.set_point_x) self.form.sbY.valueChanged.connect(self.set_point_y) self.form.sbZ.valueChanged.connect(self.set_point_z) - if hasattr(self.form.cbGlobalMode, "checkStateChanged"): # Qt version >= 6.7.0 + if hasattr(self.form.cbGlobalMode, "checkStateChanged"): # Qt version >= 6.7.0 self.form.cbGlobalMode.checkStateChanged.connect(self.set_global_mode) - else: # Qt version < 6.7.0 + else: # Qt version < 6.7.0 self.form.cbGlobalMode.stateChanged.connect(self.set_global_mode) self.form.pbReset.clicked.connect(self.reset_point) self.form.sbHeight.valueChanged.connect(self.set_height) @@ -132,7 +132,7 @@ class ShapeStringTaskPanel: self.display_point_active = False def escape_string(self, string): - return string.replace("\\", "\\\\").replace("\"", "\\\"") + return string.replace("\\", "\\\\").replace('"', '\\"') def platform_win_dialog(self, flag): """Handle the type of dialog depending on the platform.""" @@ -207,10 +207,7 @@ class ShapeStringTaskPanel: Gui.HintManager.hide() else: Gui.HintManager.show( - Gui.InputHint( - translate("draft", "%1 pick point"), - Gui.UserInput.MouseLeft - ) + Gui.InputHint(translate("draft", "%1 pick point"), Gui.UserInput.MouseLeft) ) @@ -232,20 +229,22 @@ class ShapeStringTaskPanelCmd(ShapeStringTaskPanel): Gui.addModule("Draft") Gui.addModule("WorkingPlane") cmd = "Draft.make_shapestring(" - cmd += "String=\"" + self.escape_string(self.text) + "\", " - cmd += "FontFile=\"" + self.escape_string(self.font_file) + "\", " + cmd += 'String="' + self.escape_string(self.text) + '", ' + cmd += 'FontFile="' + self.escape_string(self.font_file) + '", ' cmd += "Size=" + str(self.height) + ", " cmd += "Tracking=0.0" cmd += ")" self.sourceCmd.commit( translate("draft", "Create ShapeString"), - ["ss = " + cmd, - "pl = FreeCAD.Placement()", - "pl.Base = " + toString(self.point), - "pl.Rotation = WorkingPlane.get_working_plane().get_placement().Rotation", - "ss.Placement = pl", - "Draft.autogroup(ss)", - "FreeCAD.ActiveDocument.recompute()"] + [ + "ss = " + cmd, + "pl = FreeCAD.Placement()", + "pl.Base = " + toString(self.point), + "pl.Rotation = WorkingPlane.get_working_plane().get_placement().Rotation", + "ss.Placement = pl", + "Draft.autogroup(ss)", + "FreeCAD.ActiveDocument.recompute()", + ], ) def reject(self): @@ -269,9 +268,9 @@ class ShapeStringTaskPanelEdit(ShapeStringTaskPanel): def accept(self): - Gui.doCommand("ss = FreeCAD.ActiveDocument.getObject(\"" + self.obj.Name + "\")") - Gui.doCommand("ss.String=\"" + self.escape_string(self.text) + "\"") - Gui.doCommand("ss.FontFile=\"" + self.escape_string(self.font_file) + "\"") + Gui.doCommand('ss = FreeCAD.ActiveDocument.getObject("' + self.obj.Name + '")') + Gui.doCommand('ss.String="' + self.escape_string(self.text) + '"') + Gui.doCommand('ss.FontFile="' + self.escape_string(self.font_file) + '"') Gui.doCommand("ss.Size=" + str(self.height)) Gui.doCommand("ss.Placement.Base=" + toString(self.point)) Gui.doCommand("FreeCAD.ActiveDocument.recompute()") diff --git a/src/Mod/Draft/drafttests/auxiliary.py b/src/Mod/Draft/drafttests/auxiliary.py index e058007857..de9d40607b 100644 --- a/src/Mod/Draft/drafttests/auxiliary.py +++ b/src/Mod/Draft/drafttests/auxiliary.py @@ -39,7 +39,7 @@ from draftutils.messages import _msg def draw_header(): """Draw a header for the tests.""" _msg("") - _msg(78*"-") + _msg(78 * "-") def import_test(module): @@ -56,18 +56,22 @@ def import_test(module): def no_gui(module): """Print a message that there is no user interface.""" - _msg(" #-----------------------------------------------------#\n" - " # No GUI; cannot test for '{}'\n" - " #-----------------------------------------------------#\n" - " Automatic PASS".format(module)) + _msg( + " #-----------------------------------------------------#\n" + " # No GUI; cannot test for '{}'\n" + " #-----------------------------------------------------#\n" + " Automatic PASS".format(module) + ) def no_test(): """Print a message that the test is not currently implemented.""" - _msg(" #-----------------------------------------------------#\n" - " # This test is not implemented currently\n" - " #-----------------------------------------------------#\n" - " Automatic PASS") + _msg( + " #-----------------------------------------------------#\n" + " # This test is not implemented currently\n" + " #-----------------------------------------------------#\n" + " Automatic PASS" + ) def fake_function(p1=None, p2=None, p3=None, p4=None, p5=None): @@ -79,4 +83,5 @@ def fake_function(p1=None, p2=None, p3=None, p4=None, p5=None): no_test() return True + ## @} diff --git a/src/Mod/Draft/drafttests/draft_test_objects.py b/src/Mod/Draft/drafttests/draft_test_objects.py index 3283a657f1..d0fa073a7d 100644 --- a/src/Mod/Draft/drafttests/draft_test_objects.py +++ b/src/Mod/Draft/drafttests/draft_test_objects.py @@ -78,12 +78,14 @@ def _create_frame(doc=None): version = App.Version() now = datetime.datetime.now().strftime("%Y/%m/%dT%H:%M:%S") - _text = ["Draft test file", - "Created: {}".format(now), - "\n", - "Version: " + ".".join(version[0:3]), - "Release: " + " ".join(version[3:5]), - "Branch: " + " ".join(version[5:])] + _text = [ + "Draft test file", + "Created: {}".format(now), + "\n", + "Version: " + ".".join(version[0:3]), + "Release: " + " ".join(version[3:5]), + "Branch: " + " ".join(version[5:]), + ] record = doc.addObject("App::Annotation", "Description") record.LabelText = _text @@ -104,10 +106,7 @@ def _create_frame(doc=None): frame.Shape = poly -def _create_objects(doc=None, - font_file=None, - hatch_file=None, - hatch_name=None): +def _create_objects(doc=None, font_file=None, hatch_file=None, hatch_name=None): """Create the objects of the test file.""" if not doc: doc = App.activeDocument() @@ -125,9 +124,7 @@ def _create_objects(doc=None, # Wire _msg(16 * "-") _msg("Wire") - Draft.make_wire([Vector(1000, 0, 0), - Vector(1500, 250, 0), - Vector(1500, 500, 0)]) + Draft.make_wire([Vector(1000, 0, 0), Vector(1500, 250, 0), Vector(1500, 500, 0)]) _set_text(["Wire"], Vector(1000, -200, 0)) # Fillet @@ -152,9 +149,7 @@ def _create_objects(doc=None, # Circular arc 3 points _msg(16 * "-") _msg("Circular arc 3 points") - Draft.make_arc_3points([Vector(4250, 0, 0), - Vector(4000, 250, 0), - Vector(4250, 500, 0)]) + Draft.make_arc_3points([Vector(4250, 0, 0), Vector(4000, 250, 0), Vector(4250, 500, 0)]) _set_text(["Circular arc 3 points"], Vector(4000, -200, 0)) # Circle @@ -188,29 +183,32 @@ def _create_objects(doc=None, # BSpline _msg(16 * "-") _msg("BSpline") - Draft.make_bspline([Vector(9000, 0, 0), - Vector(9100, 200, 0), - Vector(9400, 300, 0), - Vector(9500, 500, 0)]) + Draft.make_bspline( + [Vector(9000, 0, 0), Vector(9100, 200, 0), Vector(9400, 300, 0), Vector(9500, 500, 0)] + ) _set_text(["BSpline"], Vector(9000, -200, 0)) # Cubic bezier _msg(16 * "-") _msg("Cubic bezier") - Draft.make_bezcurve([Vector(10000, 0, 0), - Vector(10000, 500, 0), - Vector(10500, 0, 0), - Vector(10500, 500, 0)], degree=3) + Draft.make_bezcurve( + [Vector(10000, 0, 0), Vector(10000, 500, 0), Vector(10500, 0, 0), Vector(10500, 500, 0)], + degree=3, + ) _set_text(["Cubic bezier"], Vector(10000, -200, 0)) # N-degree bezier _msg(16 * "-") _msg("N-degree bezier") - Draft.make_bezcurve([Vector (11000, 0, 0), - Vector (11100, 400, 0), - Vector (11250, 250, 0), - Vector (11400, 100, 0), - Vector (11500, 500, 0)]) + Draft.make_bezcurve( + [ + Vector(11000, 0, 0), + Vector(11100, 400, 0), + Vector(11250, 250, 0), + Vector(11400, 100, 0), + Vector(11500, 500, 0), + ] + ) _set_text(["N-degree bezier"], Vector(11000, -200, 0)) # Point @@ -239,9 +237,7 @@ def _create_objects(doc=None, _msg(16 * "-") _msg("Shapestring") try: - shape_string = Draft.make_shapestring("Testing", - font_file, - 100) + shape_string = Draft.make_shapestring("Testing", font_file, 100) shape_string.Placement.Base = Vector(14000, 0) except Exception: _wrn("Shapestring could not be created") @@ -259,11 +255,7 @@ def _create_objects(doc=None, rectangle.ViewObject.Visibility = False doc.recompute() try: - Draft.make_hatch(rectangle, - hatch_file, - hatch_name, - scale=10, - rotation=45) + Draft.make_hatch(rectangle, hatch_file, hatch_name, scale=10, rotation=45) except Exception: _wrn("Hatch could not be created") _wrn("Possible cause: the hatch file may not exist") @@ -283,9 +275,9 @@ def _create_objects(doc=None, # Linear dimension _msg(16 * "-") _msg("Linear dimension") - dimension = Draft.make_linear_dimension(Vector(1500, 2000, 0), - Vector(1500, 2400, 0), - Vector(1000, 2200, 0)) + dimension = Draft.make_linear_dimension( + Vector(1500, 2000, 0), Vector(1500, 2400, 0), Vector(1000, 2200, 0) + ) if App.GuiUp: dimension.ViewObject.ArrowSizeStart = 15 dimension.ViewObject.ArrowSizeEnd = 15 @@ -296,11 +288,9 @@ def _create_objects(doc=None, dimension.ViewObject.Decimals = 1 dimension.ViewObject.ShowUnit = False - line = Draft.make_wire([Vector(1500, 2600, 0), - Vector(1500, 3000, 0)]) + line = Draft.make_wire([Vector(1500, 2600, 0), Vector(1500, 3000, 0)]) doc.recompute() - dimension = Draft.make_linear_dimension_obj(line, 1, 2, - Vector(1000, 2800, 0)) + dimension = Draft.make_linear_dimension_obj(line, 1, 2, Vector(1000, 2800, 0)) if App.GuiUp: dimension.ViewObject.ArrowSizeStart = 15 dimension.ViewObject.ArrowSizeEnd = 15 @@ -322,10 +312,7 @@ def _create_objects(doc=None, circle.Placement.Base = Vector(2200, 2200, 0) circle.MakeFace = False doc.recompute() - dimension = Draft.make_radial_dimension_obj(circle, - 1, - "radius", - Vector(2300, 2300, 0)) + dimension = Draft.make_radial_dimension_obj(circle, 1, "radius", Vector(2300, 2300, 0)) if App.GuiUp: dimension.ViewObject.ArrowSizeStart = 15 dimension.ViewObject.ArrowSizeEnd = 15 @@ -337,27 +324,21 @@ def _create_objects(doc=None, circle.Placement.Base = Vector(2200, 2800, 0) circle.MakeFace = False doc.recompute() - dimension = Draft.make_radial_dimension_obj(circle, - 1, - "diameter", - Vector(2300, 2900, 0)) + dimension = Draft.make_radial_dimension_obj(circle, 1, "diameter", Vector(2300, 2900, 0)) if App.GuiUp: dimension.ViewObject.ArrowSizeStart = 15 dimension.ViewObject.ArrowSizeEnd = 15 dimension.ViewObject.FontSize = 50 dimension.ViewObject.Decimals = 1 dimension.ViewObject.ShowUnit = False - _set_text(["Radius dimension", - "Diameter dimension"], Vector(2000, 1800, 0)) + _set_text(["Radius dimension", "Diameter dimension"], Vector(2000, 1800, 0)) # Angular dimension _msg(16 * "-") _msg("Angular dimension") Draft.make_line(Vector(3000, 2000, 0), Vector(3500, 2000, 0)) Draft.make_line(Vector(3000, 2000, 0), Vector(3500, 2500, 0)) - dimension = Draft.make_angular_dimension(Vector(3000, 2000, 0), - [0, 45], - Vector(3250, 2250, 0)) + dimension = Draft.make_angular_dimension(Vector(3000, 2000, 0), [0, 45], Vector(3250, 2250, 0)) if App.GuiUp: dimension.ViewObject.ArrowSizeStart = 15 dimension.ViewObject.ArrowSizeEnd = 15 @@ -369,10 +350,12 @@ def _create_objects(doc=None, _msg(16 * "-") _msg("Label") place = App.Placement(Vector(4250, 2250, 0), App.Rotation()) - label = Draft.make_label(target_point=Vector(4000, 2000, 0), - placement=place, - custom_text="Example label", - distance=-100) + label = Draft.make_label( + target_point=Vector(4000, 2000, 0), + placement=place, + custom_text="Example label", + distance=-100, + ) label.Text = "Testing" if App.GuiUp: label.ViewObject.ArrowSizeStart = 15 @@ -389,14 +372,9 @@ def _create_objects(doc=None, if App.GuiUp: rectangle.ViewObject.Visibility = False doc.recompute() - Draft.make_ortho_array(rectangle, - Vector(200, 0, 0), - Vector(0, 150, 0), - Vector(0, 0, 0), - 3, - 2, - 1, - use_link=False) + Draft.make_ortho_array( + rectangle, Vector(200, 0, 0), Vector(0, 150, 0), Vector(0, 0, 0), 3, 2, 1, use_link=False + ) _set_text(["Orthogonal array"], Vector(0, 3800, 0)) # Orthogonal link array @@ -407,46 +385,29 @@ def _create_objects(doc=None, if App.GuiUp: rectangle.ViewObject.Visibility = False doc.recompute() - Draft.make_ortho_array(rectangle, - Vector(200, 0, 0), - Vector(0, 150, 0), - Vector(0, 0, 0), - 3, - 2, - 1, - use_link=True) + Draft.make_ortho_array( + rectangle, Vector(200, 0, 0), Vector(0, 150, 0), Vector(0, 0, 0), 3, 2, 1, use_link=True + ) _set_text(["Orthogonal link array"], Vector(1000, 3800, 0)) # Polar array _msg(16 * "-") _msg("Polar array") - wire = Draft.make_wire([Vector(2000, 4050, 0), - Vector(2000, 4000, 0), - Vector(2100, 4000, 0)]) + wire = Draft.make_wire([Vector(2000, 4050, 0), Vector(2000, 4000, 0), Vector(2100, 4000, 0)]) if App.GuiUp: wire.ViewObject.Visibility = False doc.recompute() - Draft.make_polar_array(wire, - 4, - 90, - Vector(2000, 4250, 0), - use_link=False) + Draft.make_polar_array(wire, 4, 90, Vector(2000, 4250, 0), use_link=False) _set_text(["Polar array"], Vector(2000, 3800, 0)) # Polar link array _msg(16 * "-") _msg("Polar link array") - wire = Draft.make_wire([Vector(3000, 4050, 0), - Vector(3000, 4000, 0), - Vector(3050, 4000, 0)]) + wire = Draft.make_wire([Vector(3000, 4050, 0), Vector(3000, 4000, 0), Vector(3050, 4000, 0)]) if App.GuiUp: wire.ViewObject.Visibility = False doc.recompute() - Draft.make_polar_array(wire, - 4, - 90, - Vector(3000, 4250, 0), - use_link=True) + Draft.make_polar_array(wire, 4, 90, Vector(3000, 4250, 0), use_link=True) _set_text(["Polar link array"], Vector(3000, 3800, 0)) # Circular array @@ -457,14 +418,9 @@ def _create_objects(doc=None, if App.GuiUp: polygon.ViewObject.Visibility = False doc.recompute() - Draft.make_circular_array(polygon, - 110, - 100, - 3, - 1, - Vector(0, 0, 1), - Vector(4250, 4250, 0), - use_link=False) + Draft.make_circular_array( + polygon, 110, 100, 3, 1, Vector(0, 0, 1), Vector(4250, 4250, 0), use_link=False + ) _set_text(["Circular array"], Vector(4000, 3800, 0)) # Circular link array @@ -475,14 +431,9 @@ def _create_objects(doc=None, if App.GuiUp: polygon.ViewObject.Visibility = False doc.recompute() - Draft.make_circular_array(polygon, - 110, - 100, - 3, - 1, - Vector(0, 0, 1), - Vector(5250, 4250, 0), - use_link=True) + Draft.make_circular_array( + polygon, 110, 100, 3, 1, Vector(0, 0, 1), Vector(5250, 4250, 0), use_link=True + ) _set_text(["Circular link array"], Vector(5000, 3800, 0)) # Path array @@ -492,10 +443,9 @@ def _create_objects(doc=None, polygon.Placement.Base = Vector(6000, 4000, 0) if App.GuiUp: polygon.ViewObject.Visibility = False - spline = Draft.make_bspline([Vector(6000, 4000, 0), - Vector(6100, 4200, 0), - Vector(6400, 4300, 0), - Vector(6500, 4500, 0)]) + spline = Draft.make_bspline( + [Vector(6000, 4000, 0), Vector(6100, 4200, 0), Vector(6400, 4300, 0), Vector(6500, 4500, 0)] + ) doc.recompute() Draft.make_path_array(polygon, spline, 5, use_link=False) _set_text(["Path array"], Vector(6000, 3800, 0)) @@ -507,10 +457,9 @@ def _create_objects(doc=None, polygon.Placement.Base = Vector(7000, 4000, 0) if App.GuiUp: polygon.ViewObject.Visibility = False - spline = Draft.make_bspline([Vector(7000, 4000, 0), - Vector(7100, 4200, 0), - Vector(7400, 4300, 0), - Vector(7500, 4500, 0)]) + spline = Draft.make_bspline( + [Vector(7000, 4000, 0), Vector(7100, 4200, 0), Vector(7400, 4300, 0), Vector(7500, 4500, 0)] + ) doc.recompute() Draft.make_path_array(polygon, spline, 5, use_link=True) _set_text(["Path link array"], Vector(7000, 3800, 0)) @@ -524,8 +473,7 @@ def _create_objects(doc=None, point_2 = Draft.make_point(8030, 4250, 0) point_3 = Draft.make_point(8470, 4250, 0) point_4 = Draft.make_point(8470, 4470, 0) - add_list, delete_list = Draft.upgrade([point_1, point_2, - point_3, point_4]) + add_list, delete_list = Draft.upgrade([point_1, point_2, point_3, point_4]) compound = add_list[0] if App.GuiUp: compound.ViewObject.PointSize = 5 @@ -542,8 +490,7 @@ def _create_objects(doc=None, point_2 = Draft.make_point(9030, 4250, 0) point_3 = Draft.make_point(9470, 4250, 0) point_4 = Draft.make_point(9470, 4470, 0) - add_list, delete_list = Draft.upgrade([point_1, point_2, - point_3, point_4]) + add_list, delete_list = Draft.upgrade([point_1, point_2, point_3, point_4]) compound = add_list[0] if App.GuiUp: compound.ViewObject.PointSize = 5 @@ -556,28 +503,21 @@ def _create_objects(doc=None, # Mirror _msg(16 * "-") _msg("Mirror") - wire = Draft.make_wire([Vector(0, 6000, 0), - Vector(150, 6200, 0), - Vector(500, 6000, 0)]) - Draft.mirror(wire, - Vector(0, 6250, 0), - Vector(500, 6250, 0)) + wire = Draft.make_wire([Vector(0, 6000, 0), Vector(150, 6200, 0), Vector(500, 6000, 0)]) + Draft.mirror(wire, Vector(0, 6250, 0), Vector(500, 6250, 0)) _set_text(["Mirror"], Vector(0, 5800, 0)) # Clone _msg(16 * "-") _msg("Clone") - wire = Draft.make_wire([Vector(1000, 6000, 0), - Vector(1150, 6200, 0), - Vector(1500, 6000, 0)]) + wire = Draft.make_wire([Vector(1000, 6000, 0), Vector(1150, 6200, 0), Vector(1500, 6000, 0)]) Draft.make_clone(wire, Vector(0, 300, 0)) _set_text(["Clone"], Vector(1000, 5800, 0)) # Shape2DView _msg(16 * "-") _msg("Shape2DView") - place = App.Placement(Vector(2000, 6000, 0), - App.Rotation(Vector(0, 0, 1), Vector(1, 2, 3))) + place = App.Placement(Vector(2000, 6000, 0), App.Rotation(Vector(0, 0, 1), Vector(1, 2, 3))) box = doc.addObject("Part::Box", "Box") box.Length = 200 box.Width = 500 @@ -601,12 +541,14 @@ def _create_objects(doc=None, # Layer _msg(16 * "-") _msg("Layer") - layer = Draft.make_layer("Custom layer", - line_color=(0.33, 0.0, 0.49), - shape_color=(0.56, 0.89, 0.56), - line_width=4, - draw_style="Solid", - transparency=50) + layer = Draft.make_layer( + "Custom layer", + line_color=(0.33, 0.0, 0.49), + shape_color=(0.56, 0.89, 0.56), + line_width=4, + draw_style="Solid", + transparency=50, + ) box = doc.addObject("Part::Box", "Box") box.Length = 200 box.Width = 500 @@ -622,9 +564,11 @@ def _create_objects(doc=None, doc.recompute() -def create_test_file(font_file=App.getResourceDir()+"Mod/TechDraw/Resources/fonts/osifont-lgpl3fe.ttf", - hatch_file=App.getResourceDir()+"Mod/TechDraw/PAT/FCPAT.pat", - hatch_name="Horizontal5"): +def create_test_file( + font_file=App.getResourceDir() + "Mod/TechDraw/Resources/fonts/osifont-lgpl3fe.ttf", + hatch_file=App.getResourceDir() + "Mod/TechDraw/PAT/FCPAT.pat", + hatch_name="Horizontal5", +): """Create a complete test file of Draft objects. It draws a frame with information on the software used to create @@ -664,6 +608,7 @@ def create_test_file(font_file=App.getResourceDir()+"Mod/TechDraw/Resources/font return doc + ## @} diff --git a/src/Mod/Draft/drafttests/test_airfoildat.py b/src/Mod/Draft/drafttests/test_airfoildat.py index eaf409c3df..b1e6e166ed 100644 --- a/src/Mod/Draft/drafttests/test_airfoildat.py +++ b/src/Mod/Draft/drafttests/test_airfoildat.py @@ -71,4 +71,5 @@ class DraftAirfoilDAT(test_base.DraftTestCaseDoc): obj = aux.fake_function(out_file) self.assertTrue(obj, "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_array.py b/src/Mod/Draft/drafttests/test_array.py index 1e49cb4d66..016b002348 100644 --- a/src/Mod/Draft/drafttests/test_array.py +++ b/src/Mod/Draft/drafttests/test_array.py @@ -43,10 +43,16 @@ class DraftArray(test_base.DraftTestCaseDoc): box.Label = "Box" self.doc.recompute() - array = Draft.make_ortho_array(box, v_x=Vector(100.0, 0.0, 0.0), - v_y=Vector(0.0, 100.0, 0.0), - v_z=Vector(0.0, 0.0, 100.0), - n_x=12, n_y=1, n_z=1, use_link=True) + array = Draft.make_ortho_array( + box, + v_x=Vector(100.0, 0.0, 0.0), + v_y=Vector(0.0, 100.0, 0.0), + v_z=Vector(0.0, 0.0, 100.0), + n_x=12, + n_y=1, + n_z=1, + use_link=True, + ) Draft.autogroup(array) array.ExpandArray = True @@ -64,4 +70,5 @@ class DraftArray(test_base.DraftTestCaseDoc): self.doc.recompute(None, True, True) self.assertEqual(array.Count, array.NumberX) + ## @} diff --git a/src/Mod/Draft/drafttests/test_creation.py b/src/Mod/Draft/drafttests/test_creation.py index 0a224a8dd8..2fcbbfbf6f 100644 --- a/src/Mod/Draft/drafttests/test_creation.py +++ b/src/Mod/Draft/drafttests/test_creation.py @@ -103,10 +103,8 @@ class DraftCreation(test_base.DraftTestCaseDoc): start_angle = 0 end_angle = 90 _msg(" radius={}".format(radius)) - _msg(" startangle={0}, endangle={1}".format(start_angle, - end_angle)) - obj = Draft.make_circle(radius, - startangle=start_angle, endangle=end_angle) + _msg(" startangle={0}, endangle={1}".format(start_angle, end_angle)) + obj = Draft.make_circle(radius, startangle=start_angle, endangle=end_angle) self.assertTrue(obj, "'{}' failed".format(operation)) def test_arc_3points(self): @@ -185,9 +183,7 @@ class DraftCreation(test_base.DraftTestCaseDoc): line = Draft.make_line(a, b) self.doc.recompute() - obj = Draft.make_linear_dimension_obj(line, - i1=1, i2=2, - dim_line=Vector(5, 3, 0)) + obj = Draft.make_linear_dimension_obj(line, i1=1, i2=2, dim_line=Vector(5, 3, 0)) self.assertTrue(obj, "'{}' failed".format(operation)) def test_dimension_radial_obj(self): @@ -198,18 +194,16 @@ class DraftCreation(test_base.DraftTestCaseDoc): start_angle = 0 end_angle = 90 _msg(" radius={}".format(radius)) - _msg(" startangle={0}, endangle={1}".format(start_angle, - end_angle)) - circ = Draft.make_circle(radius, - startangle=start_angle, endangle=end_angle) + _msg(" startangle={0}, endangle={1}".format(start_angle, end_angle)) + circ = Draft.make_circle(radius, startangle=start_angle, endangle=end_angle) self.doc.recompute() - obj1 = Draft.make_radial_dimension_obj(circ, index=1, - mode="radius", - dim_line=Vector(1, 1, 0)) - obj2 = Draft.make_radial_dimension_obj(circ, index=1, - mode="diameter", - dim_line=Vector(3, 1, 0)) + obj1 = Draft.make_radial_dimension_obj( + circ, index=1, mode="radius", dim_line=Vector(1, 1, 0) + ) + obj2 = Draft.make_radial_dimension_obj( + circ, index=1, mode="diameter", dim_line=Vector(3, 1, 0) + ) self.assertTrue(obj1 and obj2, "'{}' failed".format(operation)) def test_dimension_angular(self): @@ -322,12 +316,9 @@ class DraftCreation(test_base.DraftTestCaseDoc): target_point = Vector(0, 0, 0) distance = -25 placement = App.Placement(Vector(50, 50, 0), App.Rotation()) - _msg(" target_point={0}, " - "distance={1}".format(target_point, distance)) + _msg(" target_point={0}, " "distance={1}".format(target_point, distance)) _msg(" placement={}".format(placement)) - obj = Draft.make_label(target_point=target_point, - distance=distance, - placement=placement) + obj = Draft.make_label(target_point=target_point, distance=distance, placement=placement) self.doc.recompute() self.assertTrue(obj, "'{}' failed".format(operation)) @@ -374,9 +365,12 @@ class DraftCreation(test_base.DraftTestCaseDoc): box = obj.Shape.BoundBox # A rather high tolerance is required. - obj_is_ok = (box.Center.isEqual(Vector(length/2, width/2, 0), 1e-6) - and math.isclose(box.XLength, length, rel_tol=0, abs_tol=1e-6) - and math.isclose(box.YLength, width, rel_tol=0, abs_tol=1e-6)) + obj_is_ok = ( + box.Center.isEqual(Vector(length / 2, width / 2, 0), 1e-6) + and math.isclose(box.XLength, length, rel_tol=0, abs_tol=1e-6) + and math.isclose(box.YLength, width, rel_tol=0, abs_tol=1e-6) + ) self.assertTrue(obj_is_ok, "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_draftgeomutils.py b/src/Mod/Draft/drafttests/test_draftgeomutils.py index 3523ba086a..4960a5d491 100644 --- a/src/Mod/Draft/drafttests/test_draftgeomutils.py +++ b/src/Mod/Draft/drafttests/test_draftgeomutils.py @@ -43,18 +43,38 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): try: extended = DraftGeomUtils.get_extended_wire(wire, offset_start, offset_end) # Test that the extended wire's length is correctly changed - self.assertAlmostEqual(extended.Length, wire.Length + offset_start + offset_end, - DraftGeomUtils.precision(), "'start={0}, end={1}' failed".format(offset_start, offset_end)) + self.assertAlmostEqual( + extended.Length, + wire.Length + offset_start + offset_end, + DraftGeomUtils.precision(), + "'start={0}, end={1}' failed".format(offset_start, offset_end), + ) if offset_start == 0.0: # If offset_start is 0.0, check that the wire's start point is unchanged - self.assertAlmostEqual(extended.OrderedVertexes[0].Point.distanceToPoint(wire.OrderedVertexes[0].Point), 0.0, - DraftGeomUtils.precision(), "'start={0}, end={1}' failed".format(offset_start, offset_end)) + self.assertAlmostEqual( + extended.OrderedVertexes[0].Point.distanceToPoint( + wire.OrderedVertexes[0].Point + ), + 0.0, + DraftGeomUtils.precision(), + "'start={0}, end={1}' failed".format(offset_start, offset_end), + ) if offset_end == 0.0: # If offset_end is 0.0, check that the wire's end point is unchanged - self.assertAlmostEqual(extended.OrderedVertexes[-1].Point.distanceToPoint(wire.OrderedVertexes[-1].Point), 0.0, - DraftGeomUtils.precision(), "'start={0}, end={1}' failed".format(offset_start, offset_end)) + self.assertAlmostEqual( + extended.OrderedVertexes[-1].Point.distanceToPoint( + wire.OrderedVertexes[-1].Point + ), + 0.0, + DraftGeomUtils.precision(), + "'start={0}, end={1}' failed".format(offset_start, offset_end), + ) except Exception as exc: - print ("get_extended_wire failed for 'start={0}, end={1}'".format(offset_start, offset_end)) + print( + "get_extended_wire failed for 'start={0}, end={1}'".format( + offset_start, offset_end + ) + ) raise exc def test_get_extended_wire1(self): @@ -63,10 +83,12 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with straight edges and various combination of Orientation: the wires 1-4 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 2500.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 2500.0), + ] edges = [] for start, end in zip(points[:-1], points[1:]): @@ -81,10 +103,12 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with straight edges and various combination of Orientation: the wires 1-4 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 2500.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 2500.0), + ] edges = [] for start, end in zip(points[:-1], points[1:]): @@ -100,10 +124,12 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with straight edges and various combination of Orientation: the wires 1-4 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 2500.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 2500.0), + ] edges = [] for start, end in zip(points[:-1], points[1:]): @@ -120,10 +146,12 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with straight edges and various combination of Orientation: the wires 1-4 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 0.0), - Vector(4500.0, 2000.0, 2500.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 0.0), + Vector(4500.0, 2000.0, 2500.0), + ] edges = [] for start, end in zip(points[:-1], points[1:]): @@ -139,11 +167,13 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with arcs and various combination of Orientation: the wires 5-8 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1000.0, 1000.0, 0.0), - Vector(2000.0, 0.0, 0.0), - Vector(3000.0, 0.0, 1000.0), - Vector(4000.0, 0.0, 0.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1000.0, 1000.0, 0.0), + Vector(2000.0, 0.0, 0.0), + Vector(3000.0, 0.0, 1000.0), + Vector(4000.0, 0.0, 0.0), + ] edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): @@ -158,11 +188,13 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with arcs and various combination of Orientation: the wires 5-8 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1000.0, 1000.0, 0.0), - Vector(2000.0, 0.0, 0.0), - Vector(3000.0, 0.0, 1000.0), - Vector(4000.0, 0.0, 0.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1000.0, 1000.0, 0.0), + Vector(2000.0, 0.0, 0.0), + Vector(3000.0, 0.0, 1000.0), + Vector(4000.0, 0.0, 0.0), + ] edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): @@ -178,11 +210,13 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with arcs and various combination of Orientation: the wires 5-8 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1000.0, 1000.0, 0.0), - Vector(2000.0, 0.0, 0.0), - Vector(3000.0, 0.0, 1000.0), - Vector(4000.0, 0.0, 0.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1000.0, 1000.0, 0.0), + Vector(2000.0, 0.0, 0.0), + Vector(3000.0, 0.0, 1000.0), + Vector(4000.0, 0.0, 0.0), + ] edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): @@ -199,11 +233,13 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): _msg(" Test '{}'".format(operation)) # Build wires made with arcs and various combination of Orientation: the wires 5-8 are all equivalent - points = [Vector(0.0, 0.0, 0.0), - Vector(1000.0, 1000.0, 0.0), - Vector(2000.0, 0.0, 0.0), - Vector(3000.0, 0.0, 1000.0), - Vector(4000.0, 0.0, 0.0)] + points = [ + Vector(0.0, 0.0, 0.0), + Vector(1000.0, 1000.0, 0.0), + Vector(2000.0, 0.0, 0.0), + Vector(3000.0, 0.0, 1000.0), + Vector(4000.0, 0.0, 0.0), + ] edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): @@ -213,5 +249,6 @@ class TestDraftGeomUtils(test_base.DraftTestCaseNoDoc): wire.Orientation = "Reversed" self.check_wire(wire) + # suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestDraftGeomUtils) # unittest.TextTestRunner().run(suite) diff --git a/src/Mod/Draft/drafttests/test_dwg.py b/src/Mod/Draft/drafttests/test_dwg.py index b77293a395..2af415ab9d 100644 --- a/src/Mod/Draft/drafttests/test_dwg.py +++ b/src/Mod/Draft/drafttests/test_dwg.py @@ -70,4 +70,5 @@ class DraftDWG(test_base.DraftTestCaseDoc): obj = aux.fake_function(out_file) self.assertTrue(obj, "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_dxf.py b/src/Mod/Draft/drafttests/test_dxf.py index e29f28606b..cdf70f1565 100644 --- a/src/Mod/Draft/drafttests/test_dxf.py +++ b/src/Mod/Draft/drafttests/test_dxf.py @@ -71,4 +71,5 @@ class DraftDXF(test_base.DraftTestCaseDoc): obj = aux.fake_function(out_file) self.assertTrue(obj, "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_import.py b/src/Mod/Draft/drafttests/test_import.py index 9a5007295f..d60ceb351b 100644 --- a/src/Mod/Draft/drafttests/test_import.py +++ b/src/Mod/Draft/drafttests/test_import.py @@ -63,4 +63,5 @@ class DraftImport(test_base.DraftTestCaseNoDoc): imported = aux.import_test(module) self.assertTrue(imported, "Problem importing '{}'".format(module)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_import_gui.py b/src/Mod/Draft/drafttests/test_import_gui.py index eb686eb702..2e40a2a571 100644 --- a/src/Mod/Draft/drafttests/test_import_gui.py +++ b/src/Mod/Draft/drafttests/test_import_gui.py @@ -63,4 +63,5 @@ class DraftGuiImport(test_base.DraftTestCaseNoDoc): imported = aux.import_test(module) self.assertTrue(imported, "Problem importing '{}'".format(module)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_import_tools.py b/src/Mod/Draft/drafttests/test_import_tools.py index 757bacc583..449f4e2e71 100644 --- a/src/Mod/Draft/drafttests/test_import_tools.py +++ b/src/Mod/Draft/drafttests/test_import_tools.py @@ -56,4 +56,5 @@ class DraftImportTools(test_base.DraftTestCaseNoDoc): imported = aux.import_test(module) self.assertTrue(imported, "Problem importing '{}'".format(module)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_modification.py b/src/Mod/Draft/drafttests/test_modification.py index 105cba52d0..bdebbfc2ea 100644 --- a/src/Mod/Draft/drafttests/test_modification.py +++ b/src/Mod/Draft/drafttests/test_modification.py @@ -60,8 +60,7 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" c={}".format(c)) Draft.move(obj, c) self.doc.recompute() - self.assertTrue(obj.Start.isEqual(Vector(3, 3, 0), 1e-6), - "'{}' failed".format(operation)) + self.assertTrue(obj.Start.isEqual(Vector(3, 3, 0), 1e-6), "'{}' failed".format(operation)) def test_copy(self): """Create a line, then copy and move it.""" @@ -96,8 +95,7 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" angle={} degrees".format(rot)) Draft.rotate(obj, rot) self.doc.recompute() - self.assertTrue(obj.Start.isEqual(c, 1e-6), - "'{}' failed".format(operation)) + self.assertTrue(obj.Start.isEqual(c, 1e-6), "'{}' failed".format(operation)) def test_offset_open(self): """Create an open wire, then produce an offset copy.""" @@ -129,10 +127,7 @@ class DraftModification(test_base.DraftTestCaseDoc): b = Vector(10, 0, 0) c = Vector(10, 4, 0) d = Vector(0, 4, 0) - edges = [Part.makeLine(a, b), - Part.makeLine(b, c), - Part.makeLine(c, d), - Part.makeLine(a, d)] + edges = [Part.makeLine(a, b), Part.makeLine(b, c), Part.makeLine(c, d), Part.makeLine(a, d)] wire = Part.Wire(edges) obj = self.doc.addObject("Part::Feature") obj.Shape = wire @@ -160,9 +155,9 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" vector={}".format(offset)) obj = Draft.offset(rect, offset, copy=True) self.doc.recompute() - obj_is_ok = (obj.Shape.CenterOfGravity == Vector(5, 2, 0) - and obj.Length == 12 - and obj.Height == 6) + obj_is_ok = ( + obj.Shape.CenterOfGravity == Vector(5, 2, 0) and obj.Length == 12 and obj.Height == 6 + ) self.assertTrue(obj_is_ok, "'{}' failed".format(operation)) def test_trim(self): @@ -335,8 +330,7 @@ class DraftModification(test_base.DraftTestCaseDoc): obj3 = Draft.downgrade(obj2[0], delete=True) self.doc.recompute() s3 = obj3[0][0] - _msg(" 3: Result 3 x '{0}' ({1})".format(s3.Shape.ShapeType, - s3.TypeId)) + _msg(" 3: Result 3 x '{0}' ({1})".format(s3.Shape.ShapeType, s3.TypeId)) self.assertTrue(len(obj3[0]) == 3, "'{}' failed".format(operation)) # edges cannot be downgraded @@ -376,7 +370,7 @@ class DraftModification(test_base.DraftTestCaseDoc): prism.Polygon = 5 # Rotate the prism 45 degrees around the Y axis prism.Placement.Rotation.Axis = Vector(0, 1, 0) - prism.Placement.Rotation.Angle = 45 * (3.14159/180) + prism.Placement.Rotation.Angle = 45 * (3.14159 / 180) _msg(" Prism") _msg(" n_sides={}".format(prism.Polygon)) _msg(" placement={}".format(prism.Placement)) @@ -402,14 +396,12 @@ class DraftModification(test_base.DraftTestCaseDoc): obj = Draft.make_sketch(wire, autoconstraints=True) self.doc.recompute() - _msg(" 1: Result '{0}' ({1})".format(obj.Shape.ShapeType, - obj.TypeId)) + _msg(" 1: Result '{0}' ({1})".format(obj.Shape.ShapeType, obj.TypeId)) self.assertTrue(obj, "'{}' failed".format(operation)) obj2 = Draft.draftify(obj, delete=False) self.doc.recompute() - _msg(" 2: Result '{0}' ({1})".format(obj2.Proxy.Type, - obj2.TypeId)) + _msg(" 2: Result '{0}' ({1})".format(obj2.Proxy.Type, obj2.TypeId)) self.assertTrue(obj2, "'{}' failed".format(operation)) def test_rectangular_array(self): @@ -433,12 +425,8 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" direction_x={}".format(dir_x)) _msg(" direction_y={}".format(dir_y)) _msg(" direction_z={}".format(dir_z)) - _msg(" number_x={0}, number_y={1}, number_z={2}".format(number_x, - number_y, - number_z)) - obj = Draft.make_ortho_array(rect, - dir_x, dir_y, dir_z, - number_x, number_y, number_z) + _msg(" number_x={0}, number_y={1}, number_z={2}".format(number_x, number_y, number_z)) + obj = Draft.make_ortho_array(rect, dir_x, dir_y, dir_z, number_x, number_y, number_z) self.assertTrue(obj, "'{}' failed".format(operation)) def test_polar_array(self): @@ -458,8 +446,7 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Array") _msg(" number={0}, polar_angle={1}".format(number, angle)) _msg(" center={}".format(center)) - obj = Draft.make_polar_array(rect, - number, angle, center) + obj = Draft.make_polar_array(rect, number, angle, center) self.assertTrue(obj, "'{}' failed".format(operation)) def test_circular_array(self): @@ -480,15 +467,13 @@ class DraftModification(test_base.DraftTestCaseDoc): number = 3 symmetry = 1 _msg(" Array") - _msg(" radial_distance={0}, " - "tangential_distance={1}".format(rad_distance, tan_distance)) + _msg(" radial_distance={0}, " "tangential_distance={1}".format(rad_distance, tan_distance)) _msg(" number={0}, symmetry={1}".format(number, symmetry)) _msg(" axis={}".format(axis)) _msg(" center={}".format(center)) - obj = Draft.make_circular_array(rect, - rad_distance, tan_distance, - number, symmetry, - axis, center) + obj = Draft.make_circular_array( + rect, rad_distance, tan_distance, number, symmetry, axis, center + ) self.assertTrue(obj, "'{}' failed".format(operation)) def test_path_array(self): @@ -517,8 +502,7 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Path Array") _msg(" number={}, translation={}".format(number, translation)) _msg(" subelements={}, align={}".format(subelements, align)) - obj = Draft.make_path_array(poly, wire, number, - translation, subelements, align) + obj = Draft.make_path_array(poly, wire, number, translation, subelements, align) self.assertTrue(obj, "'{}' failed".format(operation)) def test_point_array(self): @@ -532,10 +516,12 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Points") _msg(" a={0}, b={1}".format(a, b)) _msg(" c={0}, d={1}".format(c, d)) - points = [Draft.make_point(a), - Draft.make_point(b), - Draft.make_point(c), - Draft.make_point(d)] + points = [ + Draft.make_point(a), + Draft.make_point(b), + Draft.make_point(c), + Draft.make_point(d), + ] _msg(" Upgrade") add, delete = Draft.upgrade(points) @@ -565,8 +551,7 @@ class DraftModification(test_base.DraftTestCaseDoc): obj = Draft.make_clone(box) _msg(" clone: '{0}' ({1})".format(obj.Proxy.Type, obj.TypeId)) self.assertTrue(obj, "'{}' failed".format(operation)) - self.assertTrue(obj.hasExtension("Part::AttachExtension"), - "'{}' failed".format(operation)) + self.assertTrue(obj.hasExtension("Part::AttachExtension"), "'{}' failed".format(operation)) def test_attached_clone_behavior(self): """Check if an attached clone behaves correctly. @@ -599,7 +584,7 @@ class DraftModification(test_base.DraftTestCaseDoc): prism.Polygon = 5 # Rotate the prism 45 degrees around the Y axis prism.Placement.Rotation.Axis = Vector(0, 1, 0) - prism.Placement.Rotation.Angle = 45 * (3.14159/180) + prism.Placement.Rotation.Angle = 45 * (3.14159 / 180) _msg(" Prism") _msg(" n_sides={}".format(prism.Polygon)) _msg(" placement={}".format(prism.Placement)) @@ -607,8 +592,9 @@ class DraftModification(test_base.DraftTestCaseDoc): page = self.doc.addObject("TechDraw::DrawPage") _msg(" page={}".format(page.TypeId)) template = self.doc.addObject("TechDraw::DrawSVGTemplate") - template.Template = App.getResourceDir() \ - + "Mod/TechDraw/Templates/ISO/A3_Landscape_blank.svg" + template.Template = ( + App.getResourceDir() + "Mod/TechDraw/Templates/ISO/A3_Landscape_blank.svg" + ) page.Template = template _msg(" template={}".format(template.TypeId)) view = self.doc.addObject("TechDraw::DrawViewDraft") @@ -659,21 +645,29 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Test '{}'".format(operation)) base = Vector(3.5, 2.5, 0.0) - cen = Vector(2.0, 1.0, 0.0) # center for scaling + cen = Vector(2.0, 1.0, 0.0) # center for scaling sca = Vector(2.0, 3.0, 1.0) - ends = [Vector(0.0, 0.0, 0.0), - Vector(4.0, 0.0, 0.0), - Vector(4.0, 3.0, 0.0), - Vector(0.0, 3.0, 0.0)] - mids = [Vector( 2.0, -0.5, 0.0), - Vector( 4.5, 1.5, 0.0), - Vector( 2.0, 3.5, 0.0), - Vector(-0.5, 1.5, 0.0)] # arc midpoints + ends = [ + Vector(0.0, 0.0, 0.0), + Vector(4.0, 0.0, 0.0), + Vector(4.0, 3.0, 0.0), + Vector(0.0, 3.0, 0.0), + ] + mids = [ + Vector(2.0, -0.5, 0.0), + Vector(4.5, 1.5, 0.0), + Vector(2.0, 3.5, 0.0), + Vector(-0.5, 1.5, 0.0), + ] # arc midpoints - shp = Part.Shape([Part.Arc(ends[0], mids[0], ends[1]), - Part.Arc(ends[1], mids[1], ends[2]), - Part.Arc(ends[2], mids[2], ends[3]), - Part.Arc(ends[3], mids[3], ends[0])]) + shp = Part.Shape( + [ + Part.Arc(ends[0], mids[0], ends[1]), + Part.Arc(ends[1], mids[1], ends[2]), + Part.Arc(ends[2], mids[2], ends[3]), + Part.Arc(ends[3], mids[3], ends[0]), + ] + ) obj = self.doc.addObject("Part::Feature") obj.Shape = shp obj.Placement.Base = base @@ -682,24 +676,30 @@ class DraftModification(test_base.DraftTestCaseDoc): self.doc.recompute() # check endpoints of arcs: - newEnds = [Vector( 5.0, 5.5, 0.0), - Vector(13.0, 5.5, 0.0), - Vector(13.0, 14.5, 0.0), - Vector( 5.0, 14.5, 0.0)] + newEnds = [ + Vector(5.0, 5.5, 0.0), + Vector(13.0, 5.5, 0.0), + Vector(13.0, 14.5, 0.0), + Vector(5.0, 14.5, 0.0), + ] vrts = obj.Shape.Vertexes for i in range(4): - self.assertTrue(vrts[i].Point.isEqual(newEnds[i], 1e-6), - "'{}' failed".format(operation)) + self.assertTrue( + vrts[i].Point.isEqual(newEnds[i], 1e-6), "'{}' failed".format(operation) + ) # check midpoints of arcs: - newMids = [Vector( 9.0, 4.0, 0.0), - Vector(14.0, 10.0, 0.0), - Vector( 9.0, 16.0, 0.0), - Vector( 4.0, 10.0, 0.0)] + newMids = [ + Vector(9.0, 4.0, 0.0), + Vector(14.0, 10.0, 0.0), + Vector(9.0, 16.0, 0.0), + Vector(4.0, 10.0, 0.0), + ] for i in range(4): edge = obj.Shape.Edges[i] par = (edge.LastParameter - edge.FirstParameter) / 2.0 - self.assertTrue(edge.valueAt(par).isEqual(newMids[i], 1e-6), - "'{}' failed".format(operation)) + self.assertTrue( + edge.valueAt(par).isEqual(newMids[i], 1e-6), "'{}' failed".format(operation) + ) def test_scale_part_feature_lines(self): """Create and scale a part feature (lines).""" @@ -707,17 +707,23 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Test '{}'".format(operation)) base = Vector(3.5, 2.5, 0.0) - cen = Vector(2.0, 1.0, 0.0) # center for scaling + cen = Vector(2.0, 1.0, 0.0) # center for scaling sca = Vector(2.0, 3.0, 1.0) - pts = [Vector(0.0, 0.0, 0.0), - Vector(4.0, 0.0, 0.0), - Vector(4.0, 3.0, 0.0), - Vector(0.0, 3.0, 0.0)] + pts = [ + Vector(0.0, 0.0, 0.0), + Vector(4.0, 0.0, 0.0), + Vector(4.0, 3.0, 0.0), + Vector(0.0, 3.0, 0.0), + ] - shp = Part.Shape([Part.LineSegment(pts[0], pts[1]), - Part.LineSegment(pts[1], pts[2]), - Part.LineSegment(pts[2], pts[3]), - Part.LineSegment(pts[3], pts[0])]) + shp = Part.Shape( + [ + Part.LineSegment(pts[0], pts[1]), + Part.LineSegment(pts[1], pts[2]), + Part.LineSegment(pts[2], pts[3]), + Part.LineSegment(pts[3], pts[0]), + ] + ) obj = self.doc.addObject("Part::Feature") obj.Shape = shp obj.Placement.Base = base @@ -725,14 +731,15 @@ class DraftModification(test_base.DraftTestCaseDoc): obj = Draft.scale(obj, sca, cen, False) self.doc.recompute() - newPts = [Vector( 5.0, 5.5, 0.0), - Vector(13.0, 5.5, 0.0), - Vector(13.0, 14.5, 0.0), - Vector( 5.0, 14.5, 0.0)] + newPts = [ + Vector(5.0, 5.5, 0.0), + Vector(13.0, 5.5, 0.0), + Vector(13.0, 14.5, 0.0), + Vector(5.0, 14.5, 0.0), + ] vrts = obj.Shape.Vertexes for i in range(4): - self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), - "'{}' failed".format(operation)) + self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), "'{}' failed".format(operation)) def test_scale_rectangle(self): """Create and scale a rectangle.""" @@ -740,7 +747,7 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Test '{}'".format(operation)) base = Vector(3.5, 2.5, 0.0) - cen = Vector(2.0, 1.0, 0.0) # center for scaling + cen = Vector(2.0, 1.0, 0.0) # center for scaling sca = Vector(2.0, 3.0, 1.0) len = 4.0 hgt = 3.0 @@ -754,16 +761,9 @@ class DraftModification(test_base.DraftTestCaseDoc): newBase = Vector(5.0, 5.5, 0.0) newLen = 8.0 newHgt = 9.0 - self.assertTrue(obj.Placement.Base.isEqual(newBase, 1e-6), - "'{}' failed".format(operation)) - self.assertAlmostEqual(obj.Length, - newLen, - delta = 1e-6, - msg = "'{}' failed".format(operation)) - self.assertAlmostEqual(obj.Height, - newHgt, - delta = 1e-6, - msg = "'{}' failed".format(operation)) + self.assertTrue(obj.Placement.Base.isEqual(newBase, 1e-6), "'{}' failed".format(operation)) + self.assertAlmostEqual(obj.Length, newLen, delta=1e-6, msg="'{}' failed".format(operation)) + self.assertAlmostEqual(obj.Height, newHgt, delta=1e-6, msg="'{}' failed".format(operation)) def test_scale_spline(self): """Create and scale a spline.""" @@ -771,11 +771,9 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Test '{}'".format(operation)) base = Vector(3.5, 2.5, 0.0) - cen = Vector(2.0, 1.0, 0.0) # center for scaling + cen = Vector(2.0, 1.0, 0.0) # center for scaling sca = Vector(2.0, 3.0, 1.0) - pts = [Vector(0.0, 0.0, 0.0), - Vector(2.0, 3.0, 0.0), - Vector(4.0, 0.0, 0.0)] + pts = [Vector(0.0, 0.0, 0.0), Vector(2.0, 3.0, 0.0), Vector(4.0, 0.0, 0.0)] obj = Draft.make_bspline(pts, False) obj.Placement.Base = base @@ -784,12 +782,11 @@ class DraftModification(test_base.DraftTestCaseDoc): self.doc.recompute() pla = obj.Placement - newPts = [Vector( 5.0, 5.5, 0.0), - Vector( 9.0, 14.5, 0.0), - Vector(13.0, 5.5, 0.0)] + newPts = [Vector(5.0, 5.5, 0.0), Vector(9.0, 14.5, 0.0), Vector(13.0, 5.5, 0.0)] for i in range(3): - self.assertTrue(pla.multVec(obj.Points[i]).isEqual(newPts[i], 1e-6), - "'{}' failed".format(operation)) + self.assertTrue( + pla.multVec(obj.Points[i]).isEqual(newPts[i], 1e-6), "'{}' failed".format(operation) + ) def test_scale_wire(self): """Create and scale a wire.""" @@ -797,12 +794,14 @@ class DraftModification(test_base.DraftTestCaseDoc): _msg(" Test '{}'".format(operation)) base = Vector(3.5, 2.5, 0.0) - cen = Vector(2.0, 1.0, 0.0) # center for scaling + cen = Vector(2.0, 1.0, 0.0) # center for scaling sca = Vector(2.0, 3.0, 1.0) - pts = [Vector(0.0, 0.0, 0.0), - Vector(4.0, 0.0, 0.0), - Vector(4.0, 3.0, 0.0), - Vector(0.0, 3.0, 0.0)] + pts = [ + Vector(0.0, 0.0, 0.0), + Vector(4.0, 0.0, 0.0), + Vector(4.0, 3.0, 0.0), + Vector(0.0, 3.0, 0.0), + ] obj = Draft.make_wire(pts, True) obj.Placement.Base = base @@ -810,13 +809,15 @@ class DraftModification(test_base.DraftTestCaseDoc): obj = Draft.scale(obj, sca, cen, False) self.doc.recompute() - newPts = [Vector( 5.0, 5.5, 0.0), - Vector(13.0, 5.5, 0.0), - Vector(13.0, 14.5, 0.0), - Vector( 5.0, 14.5, 0.0)] + newPts = [ + Vector(5.0, 5.5, 0.0), + Vector(13.0, 5.5, 0.0), + Vector(13.0, 14.5, 0.0), + Vector(5.0, 14.5, 0.0), + ] vrts = obj.Shape.Vertexes for i in range(4): - self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), - "'{}' failed".format(operation)) + self.assertTrue(vrts[i].Point.isEqual(newPts[i], 1e-6), "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_oca.py b/src/Mod/Draft/drafttests/test_oca.py index 4595e9e306..1964e44d39 100644 --- a/src/Mod/Draft/drafttests/test_oca.py +++ b/src/Mod/Draft/drafttests/test_oca.py @@ -71,4 +71,5 @@ class DraftOCA(test_base.DraftTestCaseDoc): obj = aux.fake_function(out_file) self.assertTrue(obj, "'{}' failed".format(operation)) + ## @} diff --git a/src/Mod/Draft/drafttests/test_pivy.py b/src/Mod/Draft/drafttests/test_pivy.py index 8adcf3bd10..1b9f89c0d1 100644 --- a/src/Mod/Draft/drafttests/test_pivy.py +++ b/src/Mod/Draft/drafttests/test_pivy.py @@ -50,10 +50,12 @@ class DraftPivy(test_base.DraftTestCaseDoc): def test_pivy_draw(self): """Use Coin (pivy.coin) to draw a cube on the active view.""" import pivy.coin as coin + cube = coin.SoCube() _msg(" Draw cube") Gui.getDocument(self.doc).ActiveView.getSceneGraph().addChild(cube) _msg(" Adding cube to the active view scene") self.assertTrue(cube, "Pivy is not working properly.") + ## @} diff --git a/src/Mod/Draft/drafttests/test_svg.py b/src/Mod/Draft/drafttests/test_svg.py index 49c890315a..c8e218b509 100644 --- a/src/Mod/Draft/drafttests/test_svg.py +++ b/src/Mod/Draft/drafttests/test_svg.py @@ -100,4 +100,5 @@ class DraftSVG(test_base.DraftTestCaseDoc): else: self.fail("no exception thrown") + ## @} diff --git a/src/Mod/Draft/draftutils/grid_observer.py b/src/Mod/Draft/draftutils/grid_observer.py index b873810393..5a55ec3b99 100644 --- a/src/Mod/Draft/draftutils/grid_observer.py +++ b/src/Mod/Draft/draftutils/grid_observer.py @@ -20,8 +20,7 @@ # * USA * # * * # *************************************************************************** -"""Provide the grid observer for the Draft and BIM workbenches. -""" +"""Provide the grid observer for the Draft and BIM workbenches.""" import FreeCAD diff --git a/src/Mod/Draft/draftutils/groups.py b/src/Mod/Draft/draftutils/groups.py index 38615ab813..2393bd4e3b 100644 --- a/src/Mod/Draft/draftutils/groups.py +++ b/src/Mod/Draft/draftutils/groups.py @@ -63,10 +63,14 @@ def is_group(obj): Otherwise returns `False`. """ typ = utils.get_type(obj) - return ((obj.isDerivedFrom("App::DocumentObjectGroup") - and typ != "LayerContainer") - or typ in ("Project", "Site", "Building", - "Floor", "BuildingPart", "Space")) + return (obj.isDerivedFrom("App::DocumentObjectGroup") and typ != "LayerContainer") or typ in ( + "Project", + "Site", + "Building", + "Floor", + "BuildingPart", + "Space", + ) def get_group_names(doc=None): @@ -171,26 +175,23 @@ def get_windows(obj): for o in obj.OutList: out.extend(get_windows(o)) for i in obj.InList: - if (utils.get_type(i.getLinkedObject()) == "Window" - or utils.is_clone(obj, "Window")): + if utils.get_type(i.getLinkedObject()) == "Window" or utils.is_clone(obj, "Window"): if hasattr(i, "Hosts"): if obj in i.Hosts: out.append(i) - elif (utils.get_type(i) == "Rebar" - or utils.is_clone(obj, "Rebar")): + elif utils.get_type(i) == "Rebar" or utils.is_clone(obj, "Rebar"): if hasattr(i, "Host"): if obj == i.Host: out.append(i) - elif (utils.get_type(obj.getLinkedObject()) in ("Window", "Rebar") - or utils.is_clone(obj, ["Window", "Rebar"])): + elif utils.get_type(obj.getLinkedObject()) in ("Window", "Rebar") or utils.is_clone( + obj, ["Window", "Rebar"] + ): out.append(obj) return out -def get_group_contents(objectslist, - walls=False, addgroups=False, - spaces=False, noarchchild=False): +def get_group_contents(objectslist, walls=False, addgroups=False, spaces=False, noarchchild=False): """Return a list of objects from expanding the input groups. The function accepts any type of object, although it is most useful @@ -239,15 +240,12 @@ def get_group_contents(objectslist, for obj in objectslist: if obj: if is_group(obj): - if addgroups or (spaces - and utils.get_type(obj) == "Space"): + if addgroups or (spaces and utils.get_type(obj) == "Space"): newlist.append(obj) - if not (noarchchild - and utils.get_type(obj) in ("Building", - "BuildingPart")): - newlist.extend(get_group_contents(obj.Group, - walls, addgroups, - spaces, noarchchild)) + if not (noarchchild and utils.get_type(obj) in ("Building", "BuildingPart")): + newlist.extend( + get_group_contents(obj.Group, walls, addgroups, spaces, noarchchild) + ) else: # print("adding ", obj.Name) newlist.append(obj) @@ -263,15 +261,11 @@ def get_group_contents(objectslist, return cleanlist -def getGroupContents(objectslist, - walls=False, addgroups=False, - spaces=False, noarchchild=False): +def getGroupContents(objectslist, walls=False, addgroups=False, spaces=False, noarchchild=False): """Return a list of objects from groups. DEPRECATED.""" utils.use_instead("get_group_contents") - return get_group_contents(objectslist, - walls, addgroups, - spaces, noarchchild) + return get_group_contents(objectslist, walls, addgroups, spaces, noarchchild) def get_movable_children(objectslist, recursive=True, _donelist=[]): @@ -313,19 +307,28 @@ def get_movable_children(objectslist, recursive=True, _donelist=[]): _donelist.append(obj.Name) # Skips some objects that should never move their children - if utils.get_type(obj) not in ("App::Part", "PartDesign::Body", - "Clone", "SectionPlane", - "Facebinder", "BuildingPart", "App::Link"): + if utils.get_type(obj) not in ( + "App::Part", + "PartDesign::Body", + "Clone", + "SectionPlane", + "Facebinder", + "BuildingPart", + "App::Link", + ): children = obj.OutList - if (hasattr(obj, "Proxy") and obj.Proxy - and hasattr(obj.Proxy, "getSiblings") - and utils.get_type(obj) != "Window"): + if ( + hasattr(obj, "Proxy") + and obj.Proxy + and hasattr(obj.Proxy, "getSiblings") + and utils.get_type(obj) != "Window" + ): # children.extend(obj.Proxy.getSiblings(obj)) pass for child in children: if hasattr(child, "MoveWithHost") and child.MoveWithHost: - if hasattr(obj, "CloneOf") and obj.CloneOf: + if hasattr(obj, "CloneOf") and obj.CloneOf: if obj.CloneOf.Name != child.Name: added.append(child) else: @@ -342,4 +345,5 @@ def getMovableChildren(objectslist, recursive=True): utils.use_instead("get_movable_children") return get_movable_children(objectslist, recursive) + ## @} diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index 34137815fb..6c0c13b897 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -51,6 +51,7 @@ if App.GuiUp: from pivy import coin from PySide import QtCore from PySide import QtGui + # from PySide import QtSvg # for load_texture @@ -105,9 +106,9 @@ def autogroup(obj): # check for required conditions for autogroup to work if not App.GuiUp: return - if not hasattr(Gui,"draftToolBar"): + if not hasattr(Gui, "draftToolBar"): return - if not hasattr(Gui.draftToolBar,"autogroup"): + if not hasattr(Gui.draftToolBar, "autogroup"): return if Gui.draftToolBar.isConstructionMode(): return @@ -115,8 +116,8 @@ def autogroup(obj): # check first for objects that do autogroup themselves # at the moment only Arch_BuildingPart, which is an App::GeometryPython for par in App.ActiveDocument.findObjects(Type="App::GeometryPython"): - if hasattr(par.Proxy,"autogroup"): - if par.Proxy.autogroup(par,obj): + if hasattr(par.Proxy, "autogroup"): + if par.Proxy.autogroup(par, obj): return # autogroup code @@ -135,6 +136,7 @@ def autogroup(obj): # NativeIFC handling try: from nativeifc import ifc_tools + parent = Gui.ActiveDocument.ActiveView.getActiveObject("NativeIFC") ifc_tools.aggregate(obj, parent) except: @@ -158,13 +160,11 @@ def autogroup(obj): return matrix = parent.getSubObject(sub, retType=4) if matrix.hasScale() == App.ScaleType.Uniform: - err = translate("draft", - "Unable to insert new object into " - "a scaled part") + err = translate("draft", "Unable to insert new object into " "a scaled part") App.Console.PrintMessage(err) return inverse_placement = App.Placement(matrix.inverse()) - if utils.get_type(obj) == 'Point': + if utils.get_type(obj) == "Point": point_vector = App.Vector(obj.X, obj.Y, obj.Z) real_point = inverse_placement.multVec(point_vector) obj.X = real_point.x @@ -179,7 +179,7 @@ def autogroup(obj): elif utils.get_type(obj) in ["Label"]: obj.Placement = App.Placement(inverse_placement.multiply(obj.Placement)) obj.TargetPoint = inverse_placement.multVec(obj.TargetPoint) - elif hasattr(obj,"Placement"): + elif hasattr(obj, "Placement"): # every object that have a placement is processed here obj.Placement = App.Placement(inverse_placement.multiply(obj.Placement)) @@ -244,9 +244,9 @@ def dim_symbol(symbol=None, invert=False): t.translation.setValue((0, -2, 0)) t.center.setValue((0, 2, 0)) if invert: - t.rotation.setValue(coin.SbVec3f((0, 0, 1)), -math.pi/2) + t.rotation.setValue(coin.SbVec3f((0, 0, 1)), -math.pi / 2) else: - t.rotation.setValue(coin.SbVec3f((0, 0, 1)), math.pi/2) + t.rotation.setValue(coin.SbVec3f((0, 0, 1)), math.pi / 2) c = coin.SoCone() c.height.setValue(4) marker.addChild(t) @@ -258,8 +258,7 @@ def dim_symbol(symbol=None, invert=False): h = coin.SoShapeHints() h.vertexOrdering = h.COUNTERCLOCKWISE c = coin.SoCoordinate3() - c.point.setValues([(-1, -2, 0), (0, 2, 0), - (1, 2, 0), (0, -2, 0)]) + c.point.setValues([(-1, -2, 0), (0, 2, 0), (1, 2, 0), (0, -2, 0)]) f = coin.SoFaceSet() marker.addChild(h) marker.addChild(c) @@ -359,6 +358,7 @@ def get_diffuse_color(objs): list of tuples The list will be empty if no valid object is found. """ + def _get_color(obj): if hasattr(obj, "ColoredElements"): if hasattr(obj, "Count") or hasattr(obj, "ElementCount"): @@ -376,7 +376,9 @@ def get_diffuse_color(objs): return cols face_num = len(base.Shape.Faces) for elm, override in zip(obj.ColoredElements[1], obj.ViewObject.OverrideColorList): - if "Face" in elm: # Examples: "Face3" and "1.Face6". Int before "." is zero-based, other int is 1-based. + if ( + "Face" in elm + ): # Examples: "Face3" and "1.Face6". Int before "." is zero-based, other int is 1-based. if "." in elm: elm0, elm1 = elm.split(".") i = (int(elm0) * face_num) + int(elm1[4:]) - 1 @@ -394,9 +396,11 @@ def get_diffuse_color(objs): if obj.ColoredElements is None: cols += sub_cols else: - for elm, override in zip(obj.ColoredElements[1], obj.ViewObject.OverrideColorList): + for elm, override in zip( + obj.ColoredElements[1], obj.ViewObject.OverrideColorList + ): if sub.Name + ".Face" in elm: - i = int(elm[(len(sub.Name) + 5):]) - 1 + i = int(elm[(len(sub.Name) + 5) :]) - 1 sub_cols[i] = override cols += sub_cols return cols @@ -420,10 +424,14 @@ def get_diffuse_color(objs): if not isinstance(objs, list): # Quick check to avoid processing a single object: obj = objs - if not hasattr(obj, "ColoredElements") \ - and hasattr(obj.ViewObject, "DiffuseColor") \ - and (len(obj.ViewObject.DiffuseColor) == 1 \ - or len(obj.ViewObject.DiffuseColor) == len(obj.Shape.Faces)): + if ( + not hasattr(obj, "ColoredElements") + and hasattr(obj.ViewObject, "DiffuseColor") + and ( + len(obj.ViewObject.DiffuseColor) == 1 + or len(obj.ViewObject.DiffuseColor) == len(obj.Shape.Faces) + ) + ): return obj.ViewObject.DiffuseColor # Create a list for further processing: objs = [objs] @@ -454,7 +462,7 @@ def apply_current_style(objs): anno_style = utils.get_default_annotation_style() shape_style = utils.get_default_shape_style() for obj in objs: - if not hasattr(obj, 'ViewObject'): + if not hasattr(obj, "ViewObject"): continue vobj = obj.ViewObject props = vobj.PropertiesList @@ -554,7 +562,7 @@ def format_object(target, origin=None, ignore_construction=False): val = getattr(matchrep, p) if isinstance(val, tuple): if len(val) != len_faces: - val = (val[0], ) + val = (val[0],) elif hasattr(val, "Value"): val = val.Value try: @@ -778,11 +786,14 @@ def load_texture(filename, size=None, gui=App.GuiUp): _wrn("load_texture: " + translate("draft", "image is Null")) if not os.path.exists(filename): - raise FileNotFoundError(-1, - translate("draft", "filename does not exist " - "on the system or " - "in the resource file"), - filename) + raise FileNotFoundError( + -1, + translate( + "draft", + "filename does not exist " "on the system or " "in the resource file", + ), + filename, + ) # This is buggy so it was de-activated. # @@ -835,8 +846,7 @@ def load_texture(filename, size=None, gui=App.GuiUp): _bytes = bytes(byteList) img.setValue(size, numcomponents, _bytes) except FileNotFoundError as exc: - _wrn("load_texture: {0}, {1}".format(exc.strerror, - exc.filename)) + _wrn("load_texture: {0}, {1}".format(exc.strerror, exc.filename)) return None except Exception as exc: _wrn(str(exc)) @@ -902,9 +912,11 @@ def get_bbox(obj, debug=False): _err(translate("draft", "Wrong input: object {} not in document.").format(obj_str)) return None - if (not hasattr(obj, "ViewObject") - or not obj.ViewObject - or not hasattr(obj.ViewObject, "RootNode")): + if ( + not hasattr(obj, "ViewObject") + or not obj.ViewObject + or not hasattr(obj.ViewObject, "RootNode") + ): _err(translate("draft", "Does not have 'ViewObject.RootNode'.")) # For Draft Dimensions @@ -941,21 +953,27 @@ def end_all_events(): if view is None: return if view.getNavigationType() in ( - "Gui::GestureNavigationStyle", "Gui::MayaGestureNavigationStyle" + "Gui::GestureNavigationStyle", + "Gui::MayaGestureNavigationStyle", ): return class DelayEnder: def __init__(self): self.delay_is_done = False + def stop(self): self.delay_is_done = True + ender = DelayEnder() timer = QtCore.QTimer() timer.timeout.connect(ender.stop) timer.setSingleShot(True) - timer.start(100) # 100ms (50ms is too short) timer guarantees the loop below runs at least that long + timer.start( + 100 + ) # 100ms (50ms is too short) timer guarantees the loop below runs at least that long while not ender.delay_is_done: QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) + ## @} diff --git a/src/Mod/Draft/draftutils/init_draft_statusbar.py b/src/Mod/Draft/draftutils/init_draft_statusbar.py index a7c0c85e17..79a47e760b 100644 --- a/src/Mod/Draft/draftutils/init_draft_statusbar.py +++ b/src/Mod/Draft/draftutils/init_draft_statusbar.py @@ -41,32 +41,61 @@ from draftutils import params from draftutils.init_tools import get_draft_snap_commands from draftutils.translate import translate -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # SCALE WIDGET FUNCTIONS -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- -draft_scales_metrics = ["1:1000", "1:500", "1:250", "1:200", "1:100", - "1:50", "1:25","1:20", "1:10", "1:5","1:2", - "1:1", - "2:1", "5:1", "10:1", "20:1", - translate("draft", "Custom"), - ] +draft_scales_metrics = [ + "1:1000", + "1:500", + "1:250", + "1:200", + "1:100", + "1:50", + "1:25", + "1:20", + "1:10", + "1:5", + "1:2", + "1:1", + "2:1", + "5:1", + "10:1", + "20:1", + translate("draft", "Custom"), +] -draft_scales_arch_imperial = ["1/16in=1ft", "3/32in=1ft", "1/8in=1ft", - "3/16in=1ft", "1/4in=1ft","3/8in=1ft", - "1/2in=1ft", "3/4in=1ft", "1in=1ft", - "1.5in=1ft", "3in=1ft", - translate("draft", "Custom"), - ] +draft_scales_arch_imperial = [ + "1/16in=1ft", + "3/32in=1ft", + "1/8in=1ft", + "3/16in=1ft", + "1/4in=1ft", + "3/8in=1ft", + "1/2in=1ft", + "3/4in=1ft", + "1in=1ft", + "1.5in=1ft", + "3in=1ft", + translate("draft", "Custom"), +] -draft_scales_eng_imperial = ["1in=10ft", "1in=20ft", "1in=30ft", - "1in=40ft", "1in=50ft", "1in=60ft", - "1in=70ft", "1in=80ft", "1in=90ft", - "1in=100ft", - translate("draft", "Custom"), - ] +draft_scales_eng_imperial = [ + "1in=10ft", + "1in=20ft", + "1in=30ft", + "1in=40ft", + "1in=50ft", + "1in=60ft", + "1in=70ft", + "1in=80ft", + "1in=90ft", + "1in=100ft", + translate("draft", "Custom"), +] -def get_scales(unit_system = 0): + +def get_scales(unit_system=0): """ returns the list of preset scales according to unit system. @@ -107,17 +136,18 @@ def scale_to_label(scale): if f[1] == 1: return str(f[0]) + ":1" return str(scale) - f = round(1/scale, 2) + f = round(1 / scale, 2) f = f.as_integer_ratio() if f[1] == 1: return "1:" + str(f[0]) return str(scale) + def label_to_scale(label): """ transform a scale string into scale factor as float """ - try : + try: scale = float(label) return scale except Exception: @@ -131,14 +161,14 @@ def label_to_scale(label): try: num = App.Units.Quantity(f[0]).Value den = App.Units.Quantity(f[1]).Value - scale = num/den + scale = num / den return scale except Exception: - err = translate("draft", - "Unable to convert input into a scale factor") + err = translate("draft", "Unable to convert input into a scale factor") App.Console.PrintWarning(err) return None + def _set_scale(action): """ triggered by scale pushbutton, set DefaultAnnoScaleMultiplier in preferences @@ -146,12 +176,11 @@ def _set_scale(action): mw = Gui.getMainWindow() sb = mw.statusBar() - scale_widget = sb.findChild(QtWidgets.QToolBar,"draft_scale_widget") + scale_widget = sb.findChild(QtWidgets.QToolBar, "draft_scale_widget") if action.text() == translate("draft", "Custom"): title_text = translate("draft", "Set Custom Scale") - dialog_text = translate("draft", - "Set custom annotation scale in format x:x, x=x") + dialog_text = translate("draft", "Set custom annotation scale in format x:x, x=x") custom_scale = QtWidgets.QInputDialog.getText(None, title_text, dialog_text) if custom_scale[1]: print(custom_scale[0]) @@ -169,9 +198,11 @@ def _set_scale(action): scale = label_to_scale(text_scale) params.set_param("DefaultAnnoScaleMultiplier", 1 / scale) -#---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- # MAIN DRAFT STATUSBAR FUNCTIONS -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + def init_draft_statusbar_scale(): """ @@ -184,8 +215,11 @@ def init_draft_statusbar_scale(): # prevent the widget from showing up in the toolbar area context menu: scale_widget.toggleViewAction().setVisible(False) scale_widget.setObjectName("draft_scale_widget") - text = translate("draft", "Draft Scale Widget", - "A context menu action used to show or hide this toolbar widget") + text = translate( + "draft", + "Draft Scale Widget", + "A context menu action used to show or hide this toolbar widget", + ) scale_widget.setWindowTitle(text) # get scales list according to system units @@ -210,8 +244,7 @@ def init_draft_statusbar_scale(): gUnits.triggered.connect(_set_scale) scale_label = scale_to_label(annotation_scale) scaleLabel.setText(scale_label) - scaleLabel.setToolTip(translate("draft", - "Set the scale used by Draft annotation tools")) + scaleLabel.setToolTip(translate("draft", "Set the scale used by Draft annotation tools")) scale_widget.addWidget(scaleLabel) scale_widget.scaleLabel = scaleLabel @@ -246,8 +279,11 @@ def init_draft_statusbar_snap(): # prevent the widget from showing up in the toolbar area context menu: snap_widget.toggleViewAction().setVisible(False) snap_widget.setObjectName("draft_snap_widget") - text = translate("draft", "Draft Snap Widget", - "A context menu action used to show or hide this toolbar widget") + text = translate( + "draft", + "Draft Snap Widget", + "A context menu action used to show or hide this toolbar widget", + ) snap_widget.setWindowTitle(text) snap_widget.setOrientation(QtCore.Qt.Orientation.Horizontal) snap_widget.setIconSize(QtCore.QSize(16, 16)) @@ -261,7 +297,7 @@ def init_draft_statusbar_snap(): # lock button: snap_widget.addAction(Gui.Command.get("Draft_Snap_Lock").getAction()[0]) snap_action = snap_widget.children()[-1] - snap_action.setFixedWidth(40) # Widen the button. + snap_action.setFixedWidth(40) # Widen the button. snap_widget.addWidget(_spacer()) @@ -280,12 +316,14 @@ def init_draft_statusbar_snap(): # menu for lock button: for cmd in get_draft_snap_commands(): - if cmd not in ["Separator", - "Draft_ToggleGrid", - "Draft_Snap_Lock", # Is automatically added to the menu anyway. - "Draft_Snap_Dimensions", - "Draft_Snap_Ortho", - "Draft_Snap_WorkingPlane"]: + if cmd not in [ + "Separator", + "Draft_ToggleGrid", + "Draft_Snap_Lock", # Is automatically added to the menu anyway. + "Draft_Snap_Dimensions", + "Draft_Snap_Ortho", + "Draft_Snap_WorkingPlane", + ]: snap_action.addAction(Gui.Command.get(cmd).getAction()[0]) @@ -352,11 +390,11 @@ def hide_draft_statusbar_snap(): mw = Gui.getMainWindow() sb = mw.statusBar() - snap_widget = sb.findChild(QtWidgets.QToolBar,"draft_snap_widget") + snap_widget = sb.findChild(QtWidgets.QToolBar, "draft_snap_widget") if snap_widget is None: # when switching workbenches, the toolbar sometimes "jumps" # out of the status bar to any other dock area... - snap_widget = mw.findChild(QtWidgets.QToolBar,"draft_snap_widget") + snap_widget = mw.findChild(QtWidgets.QToolBar, "draft_snap_widget") if snap_widget: snap_widget.hide() @@ -380,4 +418,5 @@ def hide_draft_statusbar(): QtCore.QTimer().singleShot(500, hide_draft_statusbar_scale) QtCore.QTimer().singleShot(500, hide_draft_statusbar_snap) + ## @} diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 62762e6f5b..bb24bb595a 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -41,150 +41,164 @@ def get_draft_drawing_commands(): """Return the drawing commands list.""" from draftguitools import gui_arcs from draftguitools import gui_beziers + arc_group = gui_arcs.ArcGroup bez_group = gui_beziers.BezierGroup - return ["Draft_Line", - "Draft_Wire", - "Draft_Fillet", - ([QT_TRANSLATE_NOOP("Workbench", "Arc Tools")], - list(arc_group.GetCommands(arc_group))), # tuple len=2: submenu - ("Draft_ArcTools", ), # tuple len=1: toolbar flyout - "Draft_Circle", - "Draft_Ellipse", - "Draft_Rectangle", - "Draft_Polygon", - "Draft_BSpline", - ([QT_TRANSLATE_NOOP("Workbench", "Bézier Tools")], - list(bez_group.GetCommands(bez_group))), - ("Draft_BezierTools", ), - "Draft_Point", - "Draft_Facebinder", - "Draft_ShapeString", - "Draft_Hatch"] + return [ + "Draft_Line", + "Draft_Wire", + "Draft_Fillet", + ( + [QT_TRANSLATE_NOOP("Workbench", "Arc Tools")], + list(arc_group.GetCommands(arc_group)), + ), # tuple len=2: submenu + ("Draft_ArcTools",), # tuple len=1: toolbar flyout + "Draft_Circle", + "Draft_Ellipse", + "Draft_Rectangle", + "Draft_Polygon", + "Draft_BSpline", + ([QT_TRANSLATE_NOOP("Workbench", "Bézier Tools")], list(bez_group.GetCommands(bez_group))), + ("Draft_BezierTools",), + "Draft_Point", + "Draft_Facebinder", + "Draft_ShapeString", + "Draft_Hatch", + ] def get_draft_annotation_commands(): """Return the annotation commands list.""" - return ["Draft_Text", - "Draft_Dimension", - "Draft_Label", - "Draft_AnnotationStyleEditor"] + return ["Draft_Text", "Draft_Dimension", "Draft_Label", "Draft_AnnotationStyleEditor"] def get_draft_modification_commands(): """Return the modification commands list.""" from draftguitools import gui_arrays + arr_group = gui_arrays.ArrayGroup - return ["Draft_Move", - "Draft_Rotate", - "Draft_Scale", - "Draft_Mirror", - "Draft_Offset", - "Draft_Trimex", - "Draft_Stretch", - "Separator", - "Draft_Clone", - ([QT_TRANSLATE_NOOP("Workbench", "Array Tools")], - list(arr_group.GetCommands(arr_group))), # tuple len=2: submenu - ("Draft_ArrayTools", ), # tuple len=1: toolbar flyout - "Separator", - "Draft_Edit", - "Draft_SubelementHighlight", - "Separator", - "Draft_Join", - "Draft_Split", - "Draft_Upgrade", - "Draft_Downgrade", - "Separator", - "Draft_WireToBSpline", - "Draft_Draft2Sketch", - "Draft_Slope", - "Draft_FlipDimension", - "Separator", - "Draft_Shape2DView"] + return [ + "Draft_Move", + "Draft_Rotate", + "Draft_Scale", + "Draft_Mirror", + "Draft_Offset", + "Draft_Trimex", + "Draft_Stretch", + "Separator", + "Draft_Clone", + ( + [QT_TRANSLATE_NOOP("Workbench", "Array Tools")], + list(arr_group.GetCommands(arr_group)), + ), # tuple len=2: submenu + ("Draft_ArrayTools",), # tuple len=1: toolbar flyout + "Separator", + "Draft_Edit", + "Draft_SubelementHighlight", + "Separator", + "Draft_Join", + "Draft_Split", + "Draft_Upgrade", + "Draft_Downgrade", + "Separator", + "Draft_WireToBSpline", + "Draft_Draft2Sketch", + "Draft_Slope", + "Draft_FlipDimension", + "Separator", + "Draft_Shape2DView", + ] def get_draft_utility_commands_menu(): """Return the utility commands list for the menu.""" - return ["Draft_SetStyle", - "Draft_ApplyStyle", - "Separator", - "Draft_Layer", - "Draft_LayerManager", - "Draft_AddNamedGroup", - "Draft_SelectGroup", - "Draft_ToggleConstructionMode", - "Separator", - "Draft_AddToLayer", - "Draft_AddToGroup", - "Draft_AddConstruction", - "Separator", - "Draft_ToggleDisplayMode", - "Draft_ToggleGrid", - "Draft_SelectPlane", - "Draft_WorkingPlaneProxy", - "Separator", - "Draft_Heal", - "Draft_ShowSnapBar"] + return [ + "Draft_SetStyle", + "Draft_ApplyStyle", + "Separator", + "Draft_Layer", + "Draft_LayerManager", + "Draft_AddNamedGroup", + "Draft_SelectGroup", + "Draft_ToggleConstructionMode", + "Separator", + "Draft_AddToLayer", + "Draft_AddToGroup", + "Draft_AddConstruction", + "Separator", + "Draft_ToggleDisplayMode", + "Draft_ToggleGrid", + "Draft_SelectPlane", + "Draft_WorkingPlaneProxy", + "Separator", + "Draft_Heal", + "Draft_ShowSnapBar", + ] def get_draft_utility_commands_toolbar(): """Return the utility commands list for the toolbar.""" - return ["Draft_LayerManager", - "Draft_AddNamedGroup", - "Draft_SelectGroup", - "Draft_AddToLayer", - "Draft_AddToGroup", - "Draft_AddConstruction", - "Draft_ToggleDisplayMode", - "Draft_WorkingPlaneProxy"] + return [ + "Draft_LayerManager", + "Draft_AddNamedGroup", + "Draft_SelectGroup", + "Draft_AddToLayer", + "Draft_AddToGroup", + "Draft_AddConstruction", + "Draft_ToggleDisplayMode", + "Draft_WorkingPlaneProxy", + ] def get_draft_snap_commands(): """Return the snapping commands list.""" - return ["Draft_Snap_Lock", - "Draft_Snap_Endpoint", - "Draft_Snap_Midpoint", - "Draft_Snap_Center", - "Draft_Snap_Angle", - "Draft_Snap_Intersection", - "Draft_Snap_Perpendicular", - "Draft_Snap_Extension", - "Draft_Snap_Parallel", - "Draft_Snap_Special", - "Draft_Snap_Near", - "Draft_Snap_Ortho", - "Draft_Snap_Grid", - "Draft_Snap_WorkingPlane", - "Draft_Snap_Dimensions", - # "Separator", # Removed: if the Python generated BIM snap toolbar - # is displayed in the Draft WB the separator appears - # after the last button. Can be reinstated when the - # BIM WB has a `normal` snap toolbar as well. - "Draft_ToggleGrid"] + return [ + "Draft_Snap_Lock", + "Draft_Snap_Endpoint", + "Draft_Snap_Midpoint", + "Draft_Snap_Center", + "Draft_Snap_Angle", + "Draft_Snap_Intersection", + "Draft_Snap_Perpendicular", + "Draft_Snap_Extension", + "Draft_Snap_Parallel", + "Draft_Snap_Special", + "Draft_Snap_Near", + "Draft_Snap_Ortho", + "Draft_Snap_Grid", + "Draft_Snap_WorkingPlane", + "Draft_Snap_Dimensions", + # "Separator", # Removed: if the Python generated BIM snap toolbar + # is displayed in the Draft WB the separator appears + # after the last button. Can be reinstated when the + # BIM WB has a `normal` snap toolbar as well. + "Draft_ToggleGrid", + ] def get_draft_context_commands(): """Return the context menu commands list.""" - return ["Draft_SetStyle", - "Draft_ApplyStyle", - "Separator", - "Draft_Layer", - "Draft_LayerManager", - "Draft_AddNamedGroup", - "Draft_SelectGroup", - "Draft_ToggleConstructionMode", - "Separator", - "Draft_AddToLayer", - "Draft_AddToGroup", - "Draft_AddConstruction", - "Separator", - "Draft_ToggleDisplayMode", - "Draft_ToggleGrid", - "Draft_SelectPlane", - "Draft_WorkingPlaneProxy"] + return [ + "Draft_SetStyle", + "Draft_ApplyStyle", + "Separator", + "Draft_Layer", + "Draft_LayerManager", + "Draft_AddNamedGroup", + "Draft_SelectGroup", + "Draft_ToggleConstructionMode", + "Separator", + "Draft_AddToLayer", + "Draft_AddToGroup", + "Draft_AddConstruction", + "Separator", + "Draft_ToggleDisplayMode", + "Draft_ToggleGrid", + "Draft_SelectPlane", + "Draft_WorkingPlaneProxy", + ] def init_toolbar(workbench, toolbar, cmd_list): @@ -231,4 +245,5 @@ def init_menu(workbench, menu_list, cmd_list): else: workbench.appendMenu(menu_list, [cmd]) + ## @} diff --git a/src/Mod/Draft/draftutils/messages.py b/src/Mod/Draft/draftutils/messages.py index 37faa86bca..d0ce58be8c 100644 --- a/src/Mod/Draft/draftutils/messages.py +++ b/src/Mod/Draft/draftutils/messages.py @@ -56,10 +56,12 @@ def _log(text, end="\n"): """Write messages to the log file including the line ending.""" App.Console.PrintLog(text + end) + def _toolmsg(text, end="\n"): """Write messages to the console including the line ending, only if ToolMessages pref setting is True""" if params.get_param("ToolMessages"): App.Console.PrintMessage(text + end) + ## @} diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index cb5978f12f..208e895915 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a parameter observer class and parameter related functions.""" +"""Contains a parameter observer class and parameter related functions.""" import os import PySide.QtCore as QtCore @@ -29,6 +29,7 @@ import xml.etree.ElementTree as ET import FreeCAD as App import Draft_rc + try: import Arch_rc except ModuleNotFoundError: @@ -40,14 +41,23 @@ if App.GuiUp: import FreeCADGui as Gui from PySide import QtWidgets + class ParamObserverDraft: def slotParamChanged(self, param_grp, typ, entry, value): if entry == "textheight": _param_observer_callback_tray() return - if entry in ("gridBorder", "gridShowHuman", "coloredGridAxes", "gridEvery", - "gridSpacing", "gridSize", "gridTransparency", "gridColor"): + if entry in ( + "gridBorder", + "gridShowHuman", + "coloredGridAxes", + "gridEvery", + "gridSpacing", + "gridSize", + "gridTransparency", + "gridColor", + ): _param_observer_callback_grid() return if entry == "DefaultAnnoScaleMultiplier": @@ -83,6 +93,7 @@ class ParamObserverView: _param_observer_callback_snaptextsize() return + def _param_observer_callback_tray(): if not hasattr(Gui, "draftToolBar"): return @@ -96,6 +107,7 @@ def _param_observer_callback_scalemultiplier(value): # value is a string. # import has to happen here to avoid circular imports from draftutils import init_draft_statusbar + if not value: return value = float(value) @@ -103,7 +115,7 @@ def _param_observer_callback_scalemultiplier(value): return mw = Gui.getMainWindow() sb = mw.statusBar() - scale_widget = sb.findChild(QtWidgets.QToolBar,"draft_scale_widget") + scale_widget = sb.findChild(QtWidgets.QToolBar, "draft_scale_widget") if scale_widget is not None: scale_label = init_draft_statusbar.scale_to_label(1 / value) scale_widget.scaleLabel.setText(scale_label) @@ -138,6 +150,7 @@ def _param_observer_callback_snapbar(value): def _param_observer_callback_snapwidget(): # import has to happen here to avoid circular imports from draftutils import init_draft_statusbar + if Gui.activeWorkbench().name() == "DraftWorkbench": init_draft_statusbar.hide_draft_statusbar() init_draft_statusbar.show_draft_statusbar() @@ -146,6 +159,7 @@ def _param_observer_callback_snapwidget(): def _param_observer_callback_scalewidget(): # import has to happen here to avoid circular imports from draftutils import init_draft_statusbar + if Gui.activeWorkbench().name() == "DraftWorkbench": init_draft_statusbar.hide_draft_statusbar() init_draft_statusbar.show_draft_statusbar() @@ -176,6 +190,7 @@ def _param_observer_callback_svg_pattern(): # imports have to happen here to avoid circular imports from draftutils import utils from draftviewproviders import view_base + utils.load_svg_patterns() if App.ActiveDocument is None: return @@ -190,22 +205,30 @@ def _param_observer_callback_svg_pattern(): for obj in doc.Objects: if hasattr(obj, "ViewObject"): vobj = obj.ViewObject - if hasattr(vobj, "Pattern") \ - and hasattr(vobj, "Proxy") \ - and isinstance(vobj.Proxy, view_base.ViewProviderDraft) \ - and vobj.getEnumerationsOfProperty("Pattern") != pats: + if ( + hasattr(vobj, "Pattern") + and hasattr(vobj, "Proxy") + and isinstance(vobj.Proxy, view_base.ViewProviderDraft) + and vobj.getEnumerationsOfProperty("Pattern") != pats + ): vobjs.append(vobj) if vobjs: data.append([doc, vobjs]) if not data: return - msg = translate("draft", -"""Do you want to update the SVG pattern options -of existing objects in all opened documents?""") - res = QtWidgets.QMessageBox.question(None, "Update SVG patterns", msg, - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No) + msg = translate( + "draft", + """Do you want to update the SVG pattern options +of existing objects in all opened documents?""", + ) + res = QtWidgets.QMessageBox.question( + None, + "Update SVG patterns", + msg, + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, + QtWidgets.QMessageBox.No, + ) if res == QtWidgets.QMessageBox.No: return @@ -229,11 +252,13 @@ def _param_observer_start(): _param_observer_start_view() -def _param_observer_start_draft(param_grp = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")): +def _param_observer_start_draft( + param_grp=App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft"), +): param_grp.AttachManager(ParamObserverDraft()) -def _param_observer_start_view(param_grp = App.ParamGet("User parameter:BaseApp/Preferences/View")): +def _param_observer_start_view(param_grp=App.ParamGet("User parameter:BaseApp/Preferences/View")): param_grp.AttachManager(ParamObserverView()) @@ -350,7 +375,7 @@ def _param_from_PrefLineEdit(widget): for elem in list(widget): if "name" in elem.keys(): att_name = elem.attrib["name"] - if att_name == "text": # Can be missing. + if att_name == "text": # Can be missing. value = elem.find("string").text # If text is missing value will be None here. elif att_name == "prefEntry": entry = elem.find("cstring").text @@ -376,6 +401,7 @@ def _param_from_PrefFileChooser(widget): def _param_from_PrefFontBox(widget): if App.GuiUp: from PySide import QtGui + font = QtGui.QFont() font.setStyleHint(QtGui.QFont.StyleHint.SansSerif) value = font.defaultFamily() @@ -403,12 +429,12 @@ def _get_shape_string_font_file(): # Mac fonts: "geneva" and "helvetica" # Linux fonts: "dejavusans" and "freesans" favorite_names = ("arial", "geneva", "helvetica", "dejavusans", "freesans") - font_file_sans = None # Font with name containing "sans". 1st fallback. + font_file_sans = None # Font with name containing "sans". 1st fallback. font_file_alpha = None # Font with name starting with a letter. 2nd fallback. # Reverse the order of the paths so that user related paths come last: for path in QtCore.QStandardPaths.standardLocations(QtCore.QStandardPaths.FontsLocation)[::-1]: # We don't use os.path.join as dir_path has forward slashes even on Windows. - for (dir_path, dir_names, file_names) in os.walk(path): + for dir_path, dir_names, file_names in os.walk(path): for file_name in file_names: base_name, ext = [s.lower() for s in os.path.splitext(file_name)] if not ext in (".ttc", ".ttf"): @@ -432,8 +458,9 @@ def _get_param_dictionary(): param_dict = {} - hatch_pattern_file = App.getResourceDir().replace("\\", "/").rstrip("/") \ - + "/Mod/TechDraw/PAT/FCPAT.pat" + hatch_pattern_file = ( + App.getResourceDir().replace("\\", "/").rstrip("/") + "/Mod/TechDraw/PAT/FCPAT.pat" + ) # Draft parameters that are not in the preferences: # fmt: off @@ -633,26 +660,27 @@ def _get_param_dictionary(): } # fmt: on - # Preferences ui files are stored in resource files. # For the Draft Workbench: /Mod/Draft/Draft_rc.py # For the Arch Workbench: /Mod/Arch/Arch_rc.py - for fnm in (":/ui/preferences-draft.ui", - ":/ui/preferences-draftinterface.ui", - ":/ui/preferences-draftsnap.ui", - ":/ui/preferences-drafttexts.ui", - ":/ui/preferences-draftvisual.ui", - ":/ui/preferences-dwg.ui", - ":/ui/preferences-dxf.ui", - ":/ui/preferences-oca.ui", - ":/ui/preferences-svg.ui", - ":/ui/preferences-arch.ui", - ":/ui/preferences-archdefaults.ui", - ":/ui/preferences-dae.ui", - ":/ui/preferences-ifc.ui", - ":/ui/preferences-ifc-export.ui", - ":/ui/preferences-sh3d-import.ui", - ":/ui/preferences-webgl.ui",): + for fnm in ( + ":/ui/preferences-draft.ui", + ":/ui/preferences-draftinterface.ui", + ":/ui/preferences-draftsnap.ui", + ":/ui/preferences-drafttexts.ui", + ":/ui/preferences-draftvisual.ui", + ":/ui/preferences-dwg.ui", + ":/ui/preferences-dxf.ui", + ":/ui/preferences-oca.ui", + ":/ui/preferences-svg.ui", + ":/ui/preferences-arch.ui", + ":/ui/preferences-archdefaults.ui", + ":/ui/preferences-dae.ui", + ":/ui/preferences-ifc.ui", + ":/ui/preferences-ifc-export.ui", + ":/ui/preferences-sh3d-import.ui", + ":/ui/preferences-webgl.ui", + ): # https://stackoverflow.com/questions/14750997/load-txt-file-from-resources-in-python fd = QtCore.QFile(fnm) diff --git a/src/Mod/Draft/draftutils/todo.py b/src/Mod/Draft/draftutils/todo.py index 373860d0bb..20624fee04 100644 --- a/src/Mod/Draft/draftutils/todo.py +++ b/src/Mod/Draft/draftutils/todo.py @@ -122,18 +122,17 @@ class ToDo: The lists are `itinerary`, `commitlist` and `afteritinerary`. """ if _DEBUG: - _msg("Debug: doing delayed tasks.\n" - "itinerary: {0}\n" - "commitlist: {1}\n" - "afteritinerary: {2}\n".format(todo.itinerary, - todo.commitlist, - todo.afteritinerary)) + _msg( + "Debug: doing delayed tasks.\n" + "itinerary: {0}\n" + "commitlist: {1}\n" + "afteritinerary: {2}\n".format(todo.itinerary, todo.commitlist, todo.afteritinerary) + ) try: for f, arg in ToDo.itinerary: try: if _DEBUG_inner: - _msg("Debug: executing.\n" - "function: {}\n".format(f)) + _msg("Debug: executing.\n" "function: {}\n".format(f)) if arg or (arg is False): f(arg) else: @@ -141,13 +140,14 @@ class ToDo: except Exception: _log(traceback.format_exc()) _err(traceback.format_exc()) - wrn = ("ToDo.doTasks, Unexpected error:\n" - "{0}\n" - "in {1}({2})".format(sys.exc_info()[0], f, arg)) + wrn = ( + "ToDo.doTasks, Unexpected error:\n" + "{0}\n" + "in {1}({2})".format(sys.exc_info()[0], f, arg) + ) _wrn(wrn) except ReferenceError: - _wrn("Debug: ToDo.doTasks: " - "queue contains a deleted object, skipping") + _wrn("Debug: ToDo.doTasks: " "queue contains a deleted object, skipping") ToDo.itinerary = [] if ToDo.commitlist: @@ -155,8 +155,7 @@ class ToDo: ToDo.commitlist = [] # Reset immediately to avoid race condition. for name, func in commit_list: if _DEBUG_inner: - _msg("Debug: committing.\n" - "name: {}\n".format(name)) + _msg("Debug: committing.\n" "name: {}\n".format(name)) try: name = str(name) App.activeDocument().openTransaction(name) @@ -169,20 +168,20 @@ class ToDo: except Exception: _log(traceback.format_exc()) _err(traceback.format_exc()) - wrn = ("ToDo.doTasks, Unexpected error:\n" - "{0}\n" - "in {1}".format(sys.exc_info()[0], func)) + wrn = ( + "ToDo.doTasks, Unexpected error:\n" + "{0}\n" + "in {1}".format(sys.exc_info()[0], func) + ) _wrn(wrn) # Restack Draft screen widgets after creation if hasattr(Gui, "Snapper"): Gui.Snapper.restack() - for f, arg in ToDo.afteritinerary: try: if _DEBUG_inner: - _msg("Debug: executing after.\n" - "function: {}\n".format(f)) + _msg("Debug: executing after.\n" "function: {}\n".format(f)) if arg: f(arg) else: @@ -190,9 +189,11 @@ class ToDo: except Exception: _log(traceback.format_exc()) _err(traceback.format_exc()) - wrn = ("ToDo.doTasks, Unexpected error:\n" - "{0}\n" - "in {1}({2})".format(sys.exc_info()[0], f, arg)) + wrn = ( + "ToDo.doTasks, Unexpected error:\n" + "{0}\n" + "in {1}({2})".format(sys.exc_info()[0], f, arg) + ) _wrn(wrn) ToDo.afteritinerary = [] @@ -224,8 +225,7 @@ class ToDo: f(arg) """ if _DEBUG: - _msg("Debug: delaying.\n" - "function: {}\n".format(f)) + _msg("Debug: delaying.\n" "function: {}\n".format(f)) if ToDo.itinerary == []: QtCore.QTimer.singleShot(0, ToDo.doTasks) ToDo.itinerary.append((f, arg)) @@ -254,8 +254,7 @@ class ToDo: See the attributes of the `ToDo` class for more information. """ if _DEBUG: - _msg("Debug: delaying commit.\n" - "commitlist: {}\n".format(cl)) + _msg("Debug: delaying commit.\n" "commitlist: {}\n".format(cl)) QtCore.QTimer.singleShot(0, ToDo.doTasks) ToDo.commitlist = cl @@ -276,8 +275,7 @@ class ToDo: and append it to the `afteritinerary` list. """ if _DEBUG: - _msg("Debug: delaying after.\n" - "function: {}\n".format(f)) + _msg("Debug: delaying after.\n" "function: {}\n".format(f)) if ToDo.afteritinerary == []: QtCore.QTimer.singleShot(0, ToDo.doTasks) ToDo.afteritinerary.append((f, arg)) diff --git a/src/Mod/Draft/draftutils/units.py b/src/Mod/Draft/draftutils/units.py index d7ff899ebc..197e639207 100644 --- a/src/Mod/Draft/draftutils/units.py +++ b/src/Mod/Draft/draftutils/units.py @@ -38,10 +38,10 @@ def get_default_unit(dim): It is based on the user preferences. """ - if dim == 'Length': + if dim == "Length": qty = App.Units.Quantity(1.0, App.Units.Length) uom = qty.getUserPreferred()[2] - elif dim == 'Angle': + elif dim == "Angle": qty = App.Units.Quantity(1.0, App.Units.Angle) uom = qty.getUserPreferred()[2] else: @@ -52,15 +52,15 @@ def get_default_unit(dim): getDefaultUnit = get_default_unit -def make_format_spec(decimals=4, dim='Length'): +def make_format_spec(decimals=4, dim="Length"): """Return a string format specifier with decimals for a dimension. It is based on the user preferences. """ - if dim == 'Length': - fmt_spec = "%." + str(decimals) + "f " + get_default_unit('Length') - elif dim == 'Angle': - fmt_spec = "%." + str(decimals) + "f " + get_default_unit('Angle') + if dim == "Length": + fmt_spec = "%." + str(decimals) + "f " + get_default_unit("Length") + elif dim == "Angle": + fmt_spec = "%." + str(decimals) + "f " + get_default_unit("Angle") else: fmt_spec = "%." + str(decimals) + "f " + "??" return fmt_spec @@ -69,8 +69,7 @@ def make_format_spec(decimals=4, dim='Length'): makeFormatSpec = make_format_spec -def display_external(internal_value, - decimals=None, dim='Length', showUnit=True, unit=None): +def display_external(internal_value, decimals=None, dim="Length", showUnit=True, unit=None): """Return a converted value for display, according to the unit schema. Parameters @@ -92,7 +91,7 @@ def display_external(internal_value, A unit string such as `'mm'`, `'cm'`, `'m'`, `'in'`, `'ft'`, in which to express the returned value. """ - if dim == 'Length': + if dim == "Length": q = App.Units.Quantity(internal_value, App.Units.Length) if not unit: if decimals is None and showUnit: @@ -101,7 +100,7 @@ def display_external(internal_value, conversion = q.getUserPreferred()[1] uom = q.getUserPreferred()[2] elif unit.lower() == "arch": - return App.Units.schemaTranslate(q,5)[0].replace("+"," ") + return App.Units.schemaTranslate(q, 5)[0].replace("+", " ") else: try: uom = unit @@ -110,7 +109,7 @@ def display_external(internal_value, except Exception: conversion = q.getUserPreferred()[1] uom = q.getUserPreferred()[2] - elif dim == 'Angle': + elif dim == "Angle": q = App.Units.Quantity(internal_value, App.Units.Angle) if decimals is None: return q.UserString diff --git a/src/Mod/Draft/draftutils/utils.py b/src/Mod/Draft/draftutils/utils.py index 69a11eed53..b075800473 100644 --- a/src/Mod/Draft/draftutils/utils.py +++ b/src/Mod/Draft/draftutils/utils.py @@ -65,25 +65,25 @@ def get_default_annotation_style(): arrow_start_type_index = params.get_param("dimsymbolstart") arrow_end_type_index = params.get_param("dimsymbolend") return { - "ArrowSizeStart": ("float", params.get_param("arrowsizestart")), - "ArrowSizeEnd": ("float", params.get_param("arrowsizeend")), - "ArrowTypeStart": ("index", arrow_start_type_index, ARROW_TYPES[arrow_start_type_index]), - "ArrowTypeEnd": ("index", arrow_end_type_index, ARROW_TYPES[arrow_end_type_index]), - "Decimals": ("int", params.get_param("dimPrecision")), - "DimOvershoot": ("float", params.get_param("dimovershoot")), - "ExtLines": ("float", params.get_param("extlines")), - "ExtOvershoot": ("float", params.get_param("extovershoot")), - "FontName": ("font", params.get_param("textfont")), - "FontSize": ("float", params.get_param("textheight")), - "LineColor": ("color", params.get_param("DefaultAnnoLineColor") | 0x000000FF), - "LineSpacing": ("float", params.get_param("LineSpacing")), - "LineWidth": ("int", params.get_param("DefaultAnnoLineWidth")), + "ArrowSizeStart": ("float", params.get_param("arrowsizestart")), + "ArrowSizeEnd": ("float", params.get_param("arrowsizeend")), + "ArrowTypeStart": ("index", arrow_start_type_index, ARROW_TYPES[arrow_start_type_index]), + "ArrowTypeEnd": ("index", arrow_end_type_index, ARROW_TYPES[arrow_end_type_index]), + "Decimals": ("int", params.get_param("dimPrecision")), + "DimOvershoot": ("float", params.get_param("dimovershoot")), + "ExtLines": ("float", params.get_param("extlines")), + "ExtOvershoot": ("float", params.get_param("extovershoot")), + "FontName": ("font", params.get_param("textfont")), + "FontSize": ("float", params.get_param("textheight")), + "LineColor": ("color", params.get_param("DefaultAnnoLineColor") | 0x000000FF), + "LineSpacing": ("float", params.get_param("LineSpacing")), + "LineWidth": ("int", params.get_param("DefaultAnnoLineWidth")), "ScaleMultiplier": ("float", params.get_param("DefaultAnnoScaleMultiplier")), - "ShowLine": ("bool", params.get_param("DimShowLine")), - "ShowUnit": ("bool", params.get_param("showUnit")), - "TextColor": ("color", params.get_param("DefaultTextColor") | 0x000000FF), - "TextSpacing": ("float", params.get_param("dimspacing")), - "UnitOverride": ("str", params.get_param("overrideUnit")) + "ShowLine": ("bool", params.get_param("DimShowLine")), + "ShowUnit": ("bool", params.get_param("showUnit")), + "TextColor": ("color", params.get_param("DefaultTextColor") | 0x000000FF), + "TextSpacing": ("float", params.get_param("dimspacing")), + "UnitOverride": ("str", params.get_param("overrideUnit")), } @@ -99,9 +99,11 @@ def repair_annotation_style(style): ArrowType has been replaced by ArrowTypeStart and ArrowTypeEnd. """ for key in ("ArrowSize", "ArrowType"): - if style.get(key) is not None \ - and style.get(key + "Start") is None \ - and style.get(key + "End") is None: + if ( + style.get(key) is not None + and style.get(key + "Start") is None + and style.get(key + "End") is None + ): style[key + "Start"] = style[key] style[key + "End"] = style[key] default = get_default_annotation_style() @@ -123,25 +125,25 @@ def get_default_shape_style(): display_mode_index = params.get_param("DefaultDisplayMode") draw_style_index = params.get_param("DefaultDrawStyle") return { - "DisplayMode": ("index", display_mode_index, DISPLAY_MODES[display_mode_index]), - "DrawStyle": ("index", draw_style_index, DRAW_STYLES[draw_style_index]), - "LineColor": ("color", params.get_param_view("DefaultShapeLineColor") | 0x000000FF), - "LineWidth": ("int", params.get_param_view("DefaultShapeLineWidth")), - "PointColor": ("color", params.get_param_view("DefaultShapeVertexColor") | 0x000000FF), - "PointSize": ("int", params.get_param_view("DefaultShapePointSize")), - "ShapeAppearance": ("material", (get_view_material(), )) + "DisplayMode": ("index", display_mode_index, DISPLAY_MODES[display_mode_index]), + "DrawStyle": ("index", draw_style_index, DRAW_STYLES[draw_style_index]), + "LineColor": ("color", params.get_param_view("DefaultShapeLineColor") | 0x000000FF), + "LineWidth": ("int", params.get_param_view("DefaultShapeLineWidth")), + "PointColor": ("color", params.get_param_view("DefaultShapeVertexColor") | 0x000000FF), + "PointSize": ("int", params.get_param_view("DefaultShapePointSize")), + "ShapeAppearance": ("material", (get_view_material(),)), } def get_view_material(): """Return a ShapeAppearance material with properties based on the preferences.""" material = App.Material() - material.AmbientColor = params.get_param_view("DefaultAmbientColor") | 0x000000FF - material.DiffuseColor = params.get_param_view("DefaultShapeColor") | 0x000000FF + material.AmbientColor = params.get_param_view("DefaultAmbientColor") | 0x000000FF + material.DiffuseColor = params.get_param_view("DefaultShapeColor") | 0x000000FF material.EmissiveColor = params.get_param_view("DefaultEmissiveColor") | 0x000000FF - material.Shininess = params.get_param_view("DefaultShapeShininess") / 100 + material.Shininess = params.get_param_view("DefaultShapeShininess") / 100 material.SpecularColor = params.get_param_view("DefaultSpecularColor") | 0x000000FF - material.Transparency = params.get_param_view("DefaultShapeTransparency") / 100 + material.Transparency = params.get_param_view("DefaultShapeTransparency") / 100 return material @@ -162,13 +164,14 @@ def string_encode_coin(ustr): """ try: from pivy import coin + coin4 = coin.COIN_MAJOR_VERSION >= 4 except (ImportError, AttributeError): coin4 = False if coin4: - return ustr.encode('utf-8') + return ustr.encode("utf-8") else: - return ustr.encode('latin1') + return ustr.encode("latin1") stringencodecoin = string_encode_coin @@ -297,8 +300,8 @@ def get_real_name(name): at least one letter. """ for i in range(1, len(name) + 1): - if name[-i] not in '1234567890': - return name[:len(name) - (i - 1)] + if name[-i] not in "1234567890": + return name[: len(name) - (i - 1)] return name @@ -327,15 +330,16 @@ def get_type(obj): or `None` if `obj` is `None`. """ import Part + if not obj: return None if isinstance(obj, Part.Shape): return "Shape" if hasattr(obj, "Class") and "Ifc" in str(obj.Class): return obj.Class - if hasattr(obj, 'Proxy') and hasattr(obj.Proxy, "Type"): + if hasattr(obj, "Proxy") and hasattr(obj.Proxy, "Type"): return obj.Proxy.Type - if hasattr(obj, 'TypeId'): + if hasattr(obj, "TypeId"): return obj.TypeId return "Unknown" @@ -536,6 +540,7 @@ def shapify(obj, delete=True): name = "Wire" elif len(shape.Edges) == 1: import DraftGeomUtils + if DraftGeomUtils.geomType(shape.Edges[0]) == "Line": name = "Line" else: @@ -602,13 +607,19 @@ def compare_objects(obj1, obj2): Any type of scripted object. """ if obj1.TypeId != obj2.TypeId: - _msg("'{0}' ({1}), '{2}' ({3}): ".format(obj1.Name, obj1.TypeId, - obj2.Name, obj2.TypeId) - + translate("draft", "different types") + " (TypeId)") + _msg( + "'{0}' ({1}), '{2}' ({3}): ".format(obj1.Name, obj1.TypeId, obj2.Name, obj2.TypeId) + + translate("draft", "different types") + + " (TypeId)" + ) elif getType(obj1) != getType(obj2): - _msg("'{0}' ({1}), '{2}' ({3}): ".format(obj1.Name, get_type(obj1), - obj2.Name, get_type(obj2)) - + translate("draft", "different types") + " (Proxy.Type)") + _msg( + "'{0}' ({1}), '{2}' ({3}): ".format( + obj1.Name, get_type(obj1), obj2.Name, get_type(obj2) + ) + + translate("draft", "different types") + + " (Proxy.Type)" + ) else: for p in obj1.PropertiesList: if p in obj2.PropertiesList: @@ -616,15 +627,17 @@ def compare_objects(obj1, obj2): pass elif p == "Placement": delta = obj1.Placement.Base.sub(obj2.Placement.Base) - text = translate("draft", "Objects have different placements. " - "Distance between the two base points:") + text = translate( + "draft", + "Objects have different placements. " + "Distance between the two base points:", + ) _msg(text + " " + str(delta.Length)) else: if getattr(obj1, p) != getattr(obj2, p): _msg("'{}' ".format(p) + translate("draft", "has a different value")) else: - _msg("{} ".format(p) - + translate("draft", "doesn't exist in one of the objects")) + _msg("{} ".format(p) + translate("draft", "doesn't exist in one of the objects")) compareObjects = compare_objects @@ -637,6 +650,7 @@ def load_svg_patterns(): attribute. """ import importSVG + App.svgpatterns = {} # Get default patterns in the resource file @@ -645,7 +659,7 @@ def load_svg_patterns(): file = ":/patterns/" + str(fn) f = QtCore.QFile(file) f.open(QtCore.QIODevice.ReadOnly) - p = importSVG.getContents(str(f.readAll()), 'pattern', True) + p = importSVG.getContents(str(f.readAll()), "pattern", True) if p: for k in p: p[k] = [p[k], file] @@ -657,25 +671,25 @@ def load_svg_patterns(): for f in os.listdir(altpat): if f[-4:].upper() == ".SVG": file = os.path.join(altpat, f) - p = importSVG.getContents(file, 'pattern') + p = importSVG.getContents(file, "pattern") if p: for k in p: p[k] = [p[k], file] App.svgpatterns.update(p) # Get TechDraw patterns - altpat = os.path.join(App.getResourceDir(),"Mod","TechDraw","Patterns") + altpat = os.path.join(App.getResourceDir(), "Mod", "TechDraw", "Patterns") if os.path.isdir(altpat): for f in os.listdir(altpat): if f[-4:].upper() == ".SVG": file = os.path.join(altpat, f) - p = importSVG.getContents(file, 'pattern') + p = importSVG.getContents(file, "pattern") if p: for k in p: p[k] = [p[k], file] else: # some TD pattern files have no definition but can still be used by Draft - p = {f[:-4]:["",file]} + p = {f[:-4]: ["", file]} App.svgpatterns.update(p) @@ -714,10 +728,10 @@ def get_rgb(color, testbw=True): testwb : bool (default = True) Pure white will be converted into pure black. """ - r = str(hex(int(color[0]*255)))[2:].zfill(2) - g = str(hex(int(color[1]*255)))[2:].zfill(2) - b = str(hex(int(color[2]*255)))[2:].zfill(2) - col = "#"+r+g+b + r = str(hex(int(color[0] * 255)))[2:].zfill(2) + g = str(hex(int(color[1] * 255)))[2:].zfill(2) + b = str(hex(int(color[2] * 255)))[2:].zfill(2) + col = "#" + r + g + b if testbw: if col == "#ffffff": # print(params.get_param("SvgLinesBlack")) @@ -757,8 +771,7 @@ def argb_to_rgba(color): def rgba_to_argb(color): - """Change byte order of a 4 byte color int from RGBA (FreeCAD) to ARGB (Qt). - """ + """Change byte order of a 4 byte color int from RGBA (FreeCAD) to ARGB (Qt).""" return ((color & 0xFFFFFF00) >> 8) + ((color & 0xFF) << 24) @@ -773,10 +786,7 @@ def get_rgba_tuple(color, typ=1.0): If float the values in the returned tuple are in the 0.0-1.0 range. Else the values are in the 0-255 range. """ - color = ((color >> 24) & 0xFF, - (color >> 16) & 0xFF, - (color >> 8) & 0xFF, - color & 0xFF) + color = ((color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF) if type(typ) == float: return tuple([x / 255.0 for x in color]) else: @@ -837,6 +847,7 @@ def _modifiers_process_selection(sels, copy, scale=False, add_movable_children=F def _modifiers_get_group_contents(obj): from draftutils import groups + return groups.get_group_contents(obj, addgroups=True, spaces=True, noarchchild=True) @@ -871,14 +882,20 @@ def _modifiers_filter_objects(objs, copy, scale=False): if parent.isDerivedFrom("Part::Feature"): parents.append(parent.Name) if len(parents) > 1: - message = translate("draft", "%s shares a base with %d other objects. Please check if you want to modify this.") % (obj.Name,len(parents) - 1) + message = translate( + "draft", + "%s shares a base with %d other objects. Please check if you want to modify this.", + ) % (obj.Name, len(parents) - 1) _err(message) if not scale or utils.get_type(obj.Base) == "Wire": result.append(obj.Base) - elif not copy \ - and hasattr(obj, "Placement") \ - and "ReadOnly" in obj.getEditorMode("Placement"): - _err(translate("draft", "%s cannot be modified because its placement is readonly") % obj.Name) + elif ( + not copy and hasattr(obj, "Placement") and "ReadOnly" in obj.getEditorMode("Placement") + ): + _err( + translate("draft", "%s cannot be modified because its placement is readonly") + % obj.Name + ) elif not scale or is_scalable(obj): result.append(obj) return result @@ -1091,16 +1108,34 @@ def use_instead(function, version=""): then we should not give a version. """ if version: - _wrn(translate("draft", "This function will be deprecated in {}. Please use '{}'.") .format(version, function)) + _wrn( + translate("draft", "This function will be deprecated in {}. Please use '{}'.").format( + version, function + ) + ) else: - _wrn(translate("draft", "This function will be deprecated. Please use '{}'.") .format(function)) + _wrn( + translate("draft", "This function will be deprecated. Please use '{}'.").format( + function + ) + ) -def pyopen(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): +def pyopen( + file, + mode="r", + buffering=-1, + encoding=None, + errors=None, + newline=None, + closefd=True, + opener=None, +): if encoding is None: - encoding = 'utf-8' + encoding = "utf-8" return open(file, mode, buffering, encoding, errors, newline, closefd, opener) + def toggle_working_plane(obj, action=None, restore=False, dialog=None): """Toggle the active state of a working plane object. @@ -1136,8 +1171,8 @@ def toggle_working_plane(obj, action=None, restore=False, dialog=None): context = "NativeIFC" # Check if the object is already active in its context - is_active_arch = (FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch") == obj) - is_active_ifc = (FreeCADGui.ActiveDocument.ActiveView.getActiveObject("NativeIFC") == obj) + is_active_arch = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch") == obj + is_active_ifc = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("NativeIFC") == obj is_active = is_active_arch or is_active_ifc if is_active: # Deactivate the object @@ -1146,8 +1181,11 @@ def toggle_working_plane(obj, action=None, restore=False, dialog=None): if is_active_ifc: FreeCADGui.ActiveDocument.ActiveView.setActiveObject("NativeIFC", None) - if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "Proxy") and \ - hasattr(obj.ViewObject.Proxy, "setWorkingPlane"): + if ( + hasattr(obj, "ViewObject") + and hasattr(obj.ViewObject, "Proxy") + and hasattr(obj.ViewObject.Proxy, "setWorkingPlane") + ): obj.ViewObject.Proxy.setWorkingPlane(restore=True) if action: action.setChecked(False) @@ -1157,8 +1195,11 @@ def toggle_working_plane(obj, action=None, restore=False, dialog=None): else: # Activate the object FreeCADGui.ActiveDocument.ActiveView.setActiveObject(context, obj) - if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "Proxy") and \ - hasattr(obj.ViewObject.Proxy, "setWorkingPlane"): + if ( + hasattr(obj, "ViewObject") + and hasattr(obj.ViewObject, "Proxy") + and hasattr(obj.ViewObject.Proxy, "setWorkingPlane") + ): obj.ViewObject.Proxy.setWorkingPlane() if action: action.setChecked(True) @@ -1166,4 +1207,5 @@ def toggle_working_plane(obj, action=None, restore=False, dialog=None): dialog.buttonActive.setChecked(True) return True + ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_array.py b/src/Mod/Draft/draftviewproviders/view_array.py index 0a3a1810d8..94b83b0d07 100644 --- a/src/Mod/Draft/draftviewproviders/view_array.py +++ b/src/Mod/Draft/draftviewproviders/view_array.py @@ -34,16 +34,16 @@ from draftutils import gui_utils class ViewProviderDraftArray(ViewProviderDraft): """a view provider that displays a Array icon instead of a Draft icon""" - def __init__(self,vobj): + def __init__(self, vobj): super(ViewProviderDraftArray, self).__init__(vobj) def getIcon(self): if hasattr(self.Object, "ArrayType"): - if self.Object.ArrayType == 'ortho': + if self.Object.ArrayType == "ortho": return ":/icons/Draft_Array.svg" - elif self.Object.ArrayType == 'polar': + elif self.Object.ArrayType == "polar": return ":/icons/Draft_PolarArray.svg" - elif self.Object.ArrayType == 'circular': + elif self.Object.ArrayType == "circular": return ":/icons/Draft_CircularArray.svg" elif hasattr(self.Object, "PointObject"): return ":/icons/Draft_PointArray.svg" @@ -65,7 +65,7 @@ class ViewProviderDraftArray(ViewProviderDraft): n = obj.NumberX * obj.NumberY * obj.NumberZ elif obj.ArrayType == "polar": n = obj.NumberPolar - else: # "circular" + else: # "circular" n = obj.Count elif hasattr(obj, "Count"): n = obj.Count diff --git a/src/Mod/Draft/draftviewproviders/view_base.py b/src/Mod/Draft/draftviewproviders/view_base.py index 1a832cf3dd..249e2081c4 100644 --- a/src/Mod/Draft/draftviewproviders/view_base.py +++ b/src/Mod/Draft/draftviewproviders/view_base.py @@ -44,6 +44,7 @@ if App.GuiUp: from pivy import coin import FreeCADGui as Gui import Draft_rc + # The module is used to prevent complaints from code checkers (flake8) bool(Draft_rc.__name__) @@ -102,23 +103,25 @@ class ViewProviderDraft(object): def _set_properties(self, vobj): """Set the properties of objects if they don't exist.""" if not hasattr(vobj, "Pattern"): - vobj.addProperty("App::PropertyEnumeration", - "Pattern", - "Draft", - QT_TRANSLATE_NOOP("App::Property", - "Defines an SVG pattern."), - locked=True) + vobj.addProperty( + "App::PropertyEnumeration", + "Pattern", + "Draft", + QT_TRANSLATE_NOOP("App::Property", "Defines an SVG pattern."), + locked=True, + ) patterns = list(utils.svg_patterns()) patterns.sort() vobj.Pattern = ["None"] + patterns if not hasattr(vobj, "PatternSize"): - vobj.addProperty("App::PropertyFloat", - "PatternSize", - "Draft", - QT_TRANSLATE_NOOP("App::Property", - "Defines the size of the SVG pattern."), - locked=True) + vobj.addProperty( + "App::PropertyFloat", + "PatternSize", + "Draft", + QT_TRANSLATE_NOOP("App::Property", "Defines the size of the SVG pattern."), + locked=True, + ) vobj.PatternSize = params.get_param("HatchPatternSize") def dumps(self): @@ -295,8 +298,8 @@ class ViewProviderDraft(object): if switch is not None: if switch.getChildren().getLength() > 0: innodes = switch.getChild(0).getChildren().getLength() - if innodes > 2: - r = switch.getChild(0).getChild(innodes-1) + if innodes > 2: + r = switch.getChild(0).getChild(innodes - 1) i = QtCore.QFileInfo(path) if self.texture: r.removeChild(self.texture) @@ -401,8 +404,15 @@ class ViewProviderDraft(object): # Facebinder, ShapeString, PanelSheet and Profile objects have their own # setEdit and unsetEdit. - if utils.get_type(vobj.Object) in ("Wire", "Circle", "Ellipse", "Rectangle", "Polygon", - "BSpline", "BezCurve"): + if utils.get_type(vobj.Object) in ( + "Wire", + "Circle", + "Ellipse", + "Rectangle", + "Polygon", + "BSpline", + "BezCurve", + ): if not "Draft_Edit" in Gui.listCommands(): self.wb_before_edit = Gui.activeWorkbench() Gui.activateWorkbench("DraftWorkbench") @@ -419,8 +429,15 @@ class ViewProviderDraft(object): if mode == 1 or mode == 2: return None - if utils.get_type(vobj.Object) in ("Wire", "Circle", "Ellipse", "Rectangle", "Polygon", - "BSpline", "BezCurve"): + if utils.get_type(vobj.Object) in ( + "Wire", + "Circle", + "Ellipse", + "Rectangle", + "Polygon", + "BSpline", + "BezCurve", + ): if hasattr(App, "activeDraftCommand") and App.activeDraftCommand: App.activeDraftCommand.finish() Gui.Control.closeDialog() @@ -434,22 +451,28 @@ class ViewProviderDraft(object): def setupContextMenu(self, vobj, menu): tp = utils.get_type(self.Object) - if tp in ("Wire", "Circle", "Ellipse", "Rectangle", "Polygon", - "BSpline", "BezCurve", "Facebinder", "ShapeString", - "PanelSheet", "Profile"): - action_edit = QtGui.QAction(translate("draft", "Edit"), - menu) - QtCore.QObject.connect(action_edit, - QtCore.SIGNAL("triggered()"), - self.edit) + if tp in ( + "Wire", + "Circle", + "Ellipse", + "Rectangle", + "Polygon", + "BSpline", + "BezCurve", + "Facebinder", + "ShapeString", + "PanelSheet", + "Profile", + ): + action_edit = QtGui.QAction(translate("draft", "Edit"), menu) + QtCore.QObject.connect(action_edit, QtCore.SIGNAL("triggered()"), self.edit) menu.addAction(action_edit) if tp == "Wire": - action_flatten = QtGui.QAction(translate("draft", "Flatten"), - menu) - QtCore.QObject.connect(action_flatten, - QtCore.SIGNAL("triggered()"), - self.flatten) # The flatten function is defined in view_wire.py. + action_flatten = QtGui.QAction(translate("draft", "Flatten"), menu) + QtCore.QObject.connect( + action_flatten, QtCore.SIGNAL("triggered()"), self.flatten + ) # The flatten function is defined in view_wire.py. menu.addAction(action_flatten) # The default Part::FeaturePython context menu contains a `Set colors` @@ -457,15 +480,27 @@ class ViewProviderDraft(object): # can only have a single face. In those cases we override this menu and # have to add our own `Transform` item. # To override the default menu this function must return `True`. - if tp in ("Wire", "Circle", "Ellipse", "Rectangle", "Polygon", - "BSpline","BezCurve", "Fillet", "Point", "Shape2DView", - "PanelCut", "PanelSheet", "Profile"): - action_transform = QtGui.QAction(Gui.getIcon("Std_TransformManip.svg"), - translate("Command", "Transform"), # Context `Command` instead of `draft`. - menu) - QtCore.QObject.connect(action_transform, - QtCore.SIGNAL("triggered()"), - self.transform) + if tp in ( + "Wire", + "Circle", + "Ellipse", + "Rectangle", + "Polygon", + "BSpline", + "BezCurve", + "Fillet", + "Point", + "Shape2DView", + "PanelCut", + "PanelSheet", + "Profile", + ): + action_transform = QtGui.QAction( + Gui.getIcon("Std_TransformManip.svg"), + translate("Command", "Transform"), # Context `Command` instead of `draft`. + menu, + ) + QtCore.QObject.connect(action_transform, QtCore.SIGNAL("triggered()"), self.transform) menu.addAction(action_transform) return True @@ -501,8 +536,9 @@ class ViewProviderDraft(object): return ":/icons/Draft_N-Curve.svg" if tp in ("ShapeString"): return ":/icons/Draft_ShapeString_tree.svg" - if hasattr(self.Object,"AutoUpdate") and not self.Object.AutoUpdate: + if hasattr(self.Object, "AutoUpdate") and not self.Object.AutoUpdate: import TechDrawGui + return ":/icons/TechDraw_TreePageUnsync.svg" return ":/icons/Draft_Draft.svg" diff --git a/src/Mod/Draft/draftviewproviders/view_circulararray.py b/src/Mod/Draft/draftviewproviders/view_circulararray.py index a513bdfc6a..923716b64b 100644 --- a/src/Mod/Draft/draftviewproviders/view_circulararray.py +++ b/src/Mod/Draft/draftviewproviders/view_circulararray.py @@ -48,4 +48,5 @@ class ViewProviderCircularArray(ViewProviderDraftArray): """Set the icon in the tree view.""" return ":/icons/Draft_CircularArray" + ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_clone.py b/src/Mod/Draft/draftviewproviders/view_clone.py index 5c1151c538..740d9ba7e3 100644 --- a/src/Mod/Draft/draftviewproviders/view_clone.py +++ b/src/Mod/Draft/draftviewproviders/view_clone.py @@ -35,10 +35,11 @@ import FreeCADGui as Gui from drafttaskpanels import task_scale from draftutils.translate import translate + class ViewProviderClone: """a view provider that displays a Clone icon instead of a Draft icon""" - def __init__(self,vobj): + def __init__(self, vobj): vobj.Proxy = self def attach(self, vobj): @@ -65,9 +66,7 @@ class ViewProviderClone: def setupContextMenu(self, vobj, menu): action_edit = QtGui.QAction(translate("draft", "Edit"), menu) - QtCore.QObject.connect(action_edit, - QtCore.SIGNAL("triggered()"), - self.edit) + QtCore.QObject.connect(action_edit, QtCore.SIGNAL("triggered()"), self.edit) menu.addAction(action_edit) def edit(self): diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index ea062c4843..21e91107e4 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -119,82 +119,56 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): super().set_text_properties(vobj, properties) if "TextSpacing" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Spacing between text and dimension line") - vobj.addProperty("App::PropertyLength", - "TextSpacing", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Spacing between text and dimension line") + vobj.addProperty("App::PropertyLength", "TextSpacing", "Text", _tip, locked=True) vobj.TextSpacing = params.get_param("dimspacing") if "FlipText" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Rotate the dimension text 180 degrees") - vobj.addProperty("App::PropertyBool", - "FlipText", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Rotate the dimension text 180 degrees") + vobj.addProperty("App::PropertyBool", "FlipText", "Text", _tip, locked=True) vobj.FlipText = False if "TextPosition" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Text Position.\n" - "Leave '(0,0,0)' for automatic position") - vobj.addProperty("App::PropertyVectorDistance", - "TextPosition", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Text Position.\n" "Leave '(0,0,0)' for automatic position" + ) + vobj.addProperty( + "App::PropertyVectorDistance", "TextPosition", "Text", _tip, locked=True + ) vobj.TextPosition = App.Vector(0, 0, 0) if "Override" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Text override.\n" - "Write '$dim' so that it is replaced by " - "the dimension length.") - vobj.addProperty("App::PropertyString", - "Override", - "Text", - _tip, - locked=True) - vobj.Override = '' + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Text override.\n" + "Write '$dim' so that it is replaced by " + "the dimension length.", + ) + vobj.addProperty("App::PropertyString", "Override", "Text", _tip, locked=True) + vobj.Override = "" def set_units_properties(self, vobj, properties): """Set unit properties only if they don't already exist.""" super().set_units_properties(vobj, properties) if "Decimals" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The number of decimals to show") - vobj.addProperty("App::PropertyInteger", - "Decimals", - "Units", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "The number of decimals to show") + vobj.addProperty("App::PropertyInteger", "Decimals", "Units", _tip, locked=True) vobj.Decimals = params.get_param("dimPrecision") if "ShowUnit" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Show the unit suffix") - vobj.addProperty("App::PropertyBool", - "ShowUnit", - "Units", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Show the unit suffix") + vobj.addProperty("App::PropertyBool", "ShowUnit", "Units", _tip, locked=True) vobj.ShowUnit = params.get_param("showUnit") if "UnitOverride" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "A unit to express the measurement.\n" - "Leave blank for system default.\n" - "Use 'arch' to force US arch notation") - vobj.addProperty("App::PropertyString", - "UnitOverride", - "Units", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "A unit to express the measurement.\n" + "Leave blank for system default.\n" + "Use 'arch' to force US arch notation", + ) + vobj.addProperty("App::PropertyString", "UnitOverride", "Units", _tip, locked=True) vobj.UnitOverride = params.get_param("overrideUnit") def set_graphics_properties(self, vobj, properties): @@ -202,56 +176,33 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): super().set_graphics_properties(vobj, properties) if "FlipArrows" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Rotate the dimension arrows 180 degrees") - vobj.addProperty("App::PropertyBool", - "FlipArrows", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Rotate the dimension arrows 180 degrees") + vobj.addProperty("App::PropertyBool", "FlipArrows", "Graphics", _tip, locked=True) vobj.FlipArrows = False if "DimOvershoot" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The distance the dimension line " - "is extended\n" - "past the extension lines") - vobj.addProperty("App::PropertyDistance", - "DimOvershoot", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The distance the dimension line " "is extended\n" "past the extension lines", + ) + vobj.addProperty("App::PropertyDistance", "DimOvershoot", "Graphics", _tip, locked=True) vobj.DimOvershoot = params.get_param("dimovershoot") if "ExtLines" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Length of the extension lines") - vobj.addProperty("App::PropertyDistance", - "ExtLines", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Length of the extension lines") + vobj.addProperty("App::PropertyDistance", "ExtLines", "Graphics", _tip, locked=True) vobj.ExtLines = params.get_param("extlines") if "ExtOvershoot" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Length of the extension line\n" - "beyond the dimension line") - vobj.addProperty("App::PropertyDistance", - "ExtOvershoot", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Length of the extension line\n" "beyond the dimension line" + ) + vobj.addProperty("App::PropertyDistance", "ExtOvershoot", "Graphics", _tip, locked=True) vobj.ExtOvershoot = params.get_param("extovershoot") if "ShowLine" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Shows the dimension line and arrows") - vobj.addProperty("App::PropertyBool", - "ShowLine", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Shows the dimension line and arrows") + vobj.addProperty("App::PropertyBool", "ShowLine", "Graphics", _tip, locked=True) vobj.ShowLine = params.get_param("DimShowLine") def getIcon(self): @@ -284,8 +235,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.textpos = coin.SoTransform() self.textcolor = coin.SoBaseColor() self.font = coin.SoFont() - self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. - self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. # The text string needs to be initialized to something, # otherwise it may cause a crash of the system @@ -318,7 +269,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.linecolor = coin.SoBaseColor() self.drawstyle = coin.SoDrawStyle() self.coords = coin.SoCoordinate3() - import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). + import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). + self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance() self.marks = coin.SoSeparator() self.marksDimOvershoot = coin.SoSeparator() @@ -411,8 +363,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.p4 = obj.End base = None - if (hasattr(obj, "Direction") - and not DraftVecUtils.isNull(obj.Direction)): + if hasattr(obj, "Direction") and not DraftVecUtils.isNull(obj.Direction): v2 = self.p1 - obj.Dimline v3 = self.p4 - obj.Dimline v2 = DraftVecUtils.project(v2, obj.Direction) @@ -501,10 +452,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): _plane_rot = DraftVecUtils.getPlaneRotation(u, v1, norm) if _plane_rot is not None: rot1 = App.Placement(_plane_rot).Rotation.Q - self.transDimOvershoot1.rotation.setValue((rot1[0], rot1[1], - rot1[2], rot1[3])) - self.transDimOvershoot2.rotation.setValue((rot1[0], rot1[1], - rot1[2], rot1[3])) + self.transDimOvershoot1.rotation.setValue((rot1[0], rot1[1], rot1[2], rot1[3])) + self.transDimOvershoot2.rotation.setValue((rot1[0], rot1[1], rot1[2], rot1[3])) self.trot = rot1 else: self.trot = (0, 0, 0, 1) @@ -516,10 +465,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): _plane_rot = DraftVecUtils.getPlaneRotation(u, v2) if _plane_rot is not None: rot2 = App.Placement(_plane_rot).Rotation.Q - self.trans1.rotation.setValue((rot2[0], rot2[1], - rot2[2], rot2[3])) - self.trans2.rotation.setValue((rot2[0], rot2[1], - rot2[2], rot2[3])) + self.trans1.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3])) + self.trans2.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3])) if self.p1 != self.p2: u3 = self.p1 - self.p2 @@ -528,10 +475,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): _plane_rot = DraftVecUtils.getPlaneRotation(u3, v3) if _plane_rot is not None: rot3 = App.Placement(_plane_rot).Rotation.Q - self.transExtOvershoot1.rotation.setValue((rot3[0], rot3[1], - rot3[2], rot3[3])) - self.transExtOvershoot2.rotation.setValue((rot3[0], rot3[1], - rot3[2], rot3[3])) + self.transExtOvershoot1.rotation.setValue((rot3[0], rot3[1], rot3[2], rot3[3])) + self.transExtOvershoot2.rotation.setValue((rot3[0], rot3[1], rot3[2], rot3[3])) # Offset is the distance from the dimension line to the textual # element that displays the value of the measurement @@ -560,8 +505,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # The position of the text element in the dimension is provided # in absolute coordinates by the value of `TextPosition`, # if it is different from the default `(0,0,0)` - if (hasattr(vobj, "TextPosition") - and not DraftVecUtils.isNull(vobj.TextPosition)): + if hasattr(vobj, "TextPosition") and not DraftVecUtils.isNull(vobj.TextPosition): self.tbase = vobj.TextPosition else: # Otherwise the position is calculated from the end points @@ -570,11 +514,10 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): center = self.p2 + (self.p3 - self.p2).multiply(0.5) self.tbase = center + offset - self.textpos.translation.setValue([self.tbase.x, - self.tbase.y, - self.tbase.z]) - self.textpos.rotation = coin.SbRotation(self.trot[0], self.trot[1], - self.trot[2], self.trot[3]) + self.textpos.translation.setValue([self.tbase.x, self.tbase.y, self.tbase.z]) + self.textpos.rotation = coin.SbRotation( + self.trot[0], self.trot[1], self.trot[2], self.trot[3] + ) show_unit = True if hasattr(vobj, "ShowUnit"): @@ -589,12 +532,13 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Special representation if we use 'Building US' scheme doc = obj.Document - if (not unit and doc.UnitSystem == doc.getEnumerationsOfProperty("UnitSystem")[5]) \ - or (unit == "arch"): + if (not unit and doc.UnitSystem == doc.getEnumerationsOfProperty("UnitSystem")[5]) or ( + unit == "arch" + ): self.string = App.Units.Quantity(length, App.Units.Length).UserString if self.string.count('"') > 1: # multiple inch tokens - self.string = self.string.replace('"', "", self.string.count('"')-1) + self.string = self.string.replace('"', "", self.string.count('"') - 1) sep = params.get_param("FeetSeparator") # use a custom separator self.string = self.string.replace("' ", "'" + sep) @@ -602,13 +546,9 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.string = self.string.replace(" ", " ") self.string = self.string.replace(" ", " ") elif hasattr(vobj, "Decimals"): - self.string = units.display_external(length, - vobj.Decimals, - 'Length', show_unit, unit) + self.string = units.display_external(length, vobj.Decimals, "Length", show_unit, unit) else: - self.string = units.display_external(length, - None, - 'Length', show_unit, unit) + self.string = units.display_external(length, None, "Length", show_unit, unit) if getattr(vobj, "Override", False): self.string = vobj.Override.replace("$dim", self.string) @@ -620,12 +560,10 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): if m == "Screen": # Calculate the spacing of the text textsize = len(self.string) * vobj.FontSize.Value / 4.0 - spacing = (self.p3 - self.p2).Length/2.0 - textsize + spacing = (self.p3 - self.p2).Length / 2.0 - textsize - self.p2a = self.p2 + DraftVecUtils.scaleTo(self.p3 - self.p2, - spacing) - self.p2b = self.p3 + DraftVecUtils.scaleTo(self.p2 - self.p3, - spacing) + self.p2a = self.p2 + DraftVecUtils.scaleTo(self.p3 - self.p2, spacing) + self.p2b = self.p3 + DraftVecUtils.scaleTo(self.p2 - self.p3, spacing) # fmt: off self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z], [self.p2.x, self.p2.y, self.p2.z], @@ -657,9 +595,12 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Update all dimension values if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if (hasattr(self, "node_wld") and hasattr(self, "p2") - and "ArrowSizeStart" in properties - and "ArrowSizeEnd" in properties): + if ( + hasattr(self, "node_wld") + and hasattr(self, "p2") + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties + ): self.remove_dim_arrows() self.draw_dim_arrows(vobj) if "DimOvershoot" in properties: @@ -671,46 +612,48 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.updateData(obj, "Start") - elif (prop == "FontSize" and "FontSize" in properties - and "ScaleMultiplier" in properties): + elif prop == "FontSize" and "FontSize" in properties and "ScaleMultiplier" in properties: if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - elif (prop == "FontName" and "FontName" in properties - and hasattr(self, "font")): + elif prop == "FontName" and "FontName" in properties and hasattr(self, "font"): self.font.name = str(vobj.FontName) - elif (prop == "TextColor" and "TextColor" in properties - and hasattr(self, "textcolor")): + elif prop == "TextColor" and "TextColor" in properties and hasattr(self, "textcolor"): col = vobj.TextColor self.textcolor.rgb.setValue(col[0], col[1], col[2]) - elif (prop == "LineColor" and "LineColor" in properties - and hasattr(self, "linecolor")): + elif prop == "LineColor" and "LineColor" in properties and hasattr(self, "linecolor"): col = vobj.LineColor self.linecolor.rgb.setValue(col[0], col[1], col[2]) - elif (prop == "LineWidth" and "LineWidth" in properties - and hasattr(self, "drawstyle")): + elif prop == "LineWidth" and "LineWidth" in properties and hasattr(self, "drawstyle"): self.drawstyle.lineWidth = vobj.LineWidth - elif (prop in ("ArrowSizeStart", "ArrowSizeEnd", "ArrowTypeStart", "ArrowTypeEnd") - and "ArrowSizeStart" in properties - and "ArrowSizeEnd" in properties - and "ScaleMultiplier" in properties - and hasattr(self, "node_wld") and hasattr(self, "p2")): + elif ( + prop in ("ArrowSizeStart", "ArrowSizeEnd", "ArrowTypeStart", "ArrowTypeEnd") + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties + and "ScaleMultiplier" in properties + and hasattr(self, "node_wld") + and hasattr(self, "p2") + ): self.remove_dim_arrows() self.draw_dim_arrows(vobj) - elif (prop == "DimOvershoot" - and "DimOvershoot" in properties - and "ScaleMultiplier" in properties): + elif ( + prop == "DimOvershoot" + and "DimOvershoot" in properties + and "ScaleMultiplier" in properties + ): self.remove_dim_overshoot() self.draw_dim_overshoot(vobj) - elif (prop == "ExtOvershoot" - and "ExtOvershoot" in properties - and "ScaleMultiplier" in properties): + elif ( + prop == "ExtOvershoot" + and "ExtOvershoot" in properties + and "ScaleMultiplier" in properties + ): self.remove_ext_overshoot() self.draw_ext_overshoot(vobj) @@ -734,8 +677,12 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" - if not (hasattr(vobj, "ArrowTypeStart") and hasattr(vobj, "ArrowTypeEnd") and - hasattr(vobj, "ArrowSizeStart") and hasattr(vobj, "ArrowSizeEnd")): + if not ( + hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + ): return # Set scale @@ -872,8 +819,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.textpos = coin.SoTransform() self.textcolor = coin.SoBaseColor() self.font = coin.SoFont() - self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. - self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. # The text string needs to be initialized to something, # otherwise it may cause a crash of the system @@ -902,7 +849,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.linecolor = coin.SoBaseColor() self.drawstyle = coin.SoDrawStyle() self.coords = coin.SoCoordinate3() - import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). + import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). + self.arc = coin.SoType.fromName("SoBrepEdgeSet").createInstance() self.marks = coin.SoSeparator() @@ -949,9 +897,9 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): norm = obj.Normal radius = (obj.Dimline - obj.Center).Length - self.circle = Part.makeCircle(radius, obj.Center, norm, - obj.FirstAngle.Value, - obj.LastAngle.Value) + self.circle = Part.makeCircle( + radius, obj.Center, norm, obj.FirstAngle.Value, obj.LastAngle.Value + ) self.p2 = self.circle.Vertexes[0].Point self.p3 = self.circle.Vertexes[-1].Point midp = DraftGeomUtils.findMidpoint(self.circle) @@ -968,13 +916,9 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): show_unit = vobj.ShowUnit if hasattr(vobj, "Decimals"): - self.string = units.display_external(angle, - vobj.Decimals, - 'Angle', show_unit) + self.string = units.display_external(angle, vobj.Decimals, "Angle", show_unit) else: - self.string = units.display_external(angle, - None, - 'Angle', show_unit) + self.string = units.display_external(angle, None, "Angle", show_unit) if vobj.Override: self.string = vobj.Override.replace("$dim", self.string) @@ -1019,31 +963,21 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): i1 = pts1_num i2 = i1 + pts2_num - self.arc.coordIndex.setValues(0, - pts1_num + pts2_num + 1, - list(range(pts1_num)) - + [-1] - + list(range(i1, i2))) + self.arc.coordIndex.setValues( + 0, pts1_num + pts2_num + 1, list(range(pts1_num)) + [-1] + list(range(i1, i2)) + ) if pts1_num >= 3 and pts2_num >= 3: - self.circle1 = Part.Arc(App.Vector(pts1[0][0], - pts1[0][1], - pts1[0][2]), - App.Vector(pts1[1][0], - pts1[1][1], - pts1[1][2]), - App.Vector(pts1[-1][0], - pts1[-1][1], - pts1[-1][2])).toShape() - self.circle2 = Part.Arc(App.Vector(pts2[0][0], - pts2[0][1], - pts2[0][2]), - App.Vector(pts2[1][0], - pts2[1][1], - pts2[1][2]), - App.Vector(pts2[-1][0], - pts2[-1][1], - pts2[-1][2])).toShape() + self.circle1 = Part.Arc( + App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]), + App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]), + App.Vector(pts1[-1][0], pts1[-1][1], pts1[-1][2]), + ).toShape() + self.circle2 = Part.Arc( + App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]), + App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]), + App.Vector(pts2[-1][0], pts2[-1][1], pts2[-1][2]), + ).toShape() else: pts = [] for i in range(arcsegs + 1): @@ -1051,9 +985,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): pts.append([p.x, p.y, p.z]) self.coords.point.setValues(pts) - self.arc.coordIndex.setValues(0, - arcsegs + 1, - list(range(arcsegs + 1))) + self.arc.coordIndex.setValues(0, arcsegs + 1, list(range(arcsegs + 1))) # Set the arrow coords and rotation p2 = (self.p2.x, self.p2.y, self.p2.z) @@ -1065,13 +997,15 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.coord2.point.setValue(p3) # Calculate small chords to make arrows look better - if hasattr(vobj, "ArrowSizeStart") \ - and hasattr(vobj, "ArrowSizeEnd") \ - and hasattr(vobj, "ScaleMultiplier") \ - and hasattr(vobj, "FlipArrows") \ - and vobj.ArrowSizeStart.Value !=0 \ - and vobj.ArrowSizeEnd.Value !=0 \ - and vobj.ScaleMultiplier != 0: + if ( + hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + and hasattr(vobj, "ScaleMultiplier") + and hasattr(vobj, "FlipArrows") + and vobj.ArrowSizeStart.Value != 0 + and vobj.ArrowSizeEnd.Value != 0 + and vobj.ScaleMultiplier != 0 + ): half_arrow_length_sta = 2 * vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier arrow_angle_sta = 2 * math.asin(min(1, half_arrow_length_sta / radius)) half_arrow_length_end = 2 * vobj.ArrowSizeEnd.Value * vobj.ScaleMultiplier @@ -1080,10 +1014,12 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): arrow_angle_sta = -arrow_angle_sta arrow_angle_end = -arrow_angle_end - u1 = (self.circle.valueAt(first + arrow_angle_sta) - - self.circle.valueAt(first)).normalize() - u2 = (self.circle.valueAt(last) - - self.circle.valueAt(last - arrow_angle_end)).normalize() + u1 = ( + self.circle.valueAt(first + arrow_angle_sta) - self.circle.valueAt(first) + ).normalize() + u2 = ( + self.circle.valueAt(last) - self.circle.valueAt(last - arrow_angle_end) + ).normalize() w2 = self.circle.Curve.Axis w1 = w2.negative() @@ -1100,8 +1036,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): # Set text position and rotation self.tbase = midp - if (hasattr(vobj, "TextPosition") - and not DraftVecUtils.isNull(vobj.TextPosition)): + if hasattr(vobj, "TextPosition") and not DraftVecUtils.isNull(vobj.TextPosition): self.tbase = vobj.TextPosition u3 = ray.cross(norm).normalize() @@ -1125,9 +1060,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.tbase = self.tbase.add(offset) q = r.Q - self.textpos.translation.setValue([self.tbase.x, - self.tbase.y, - self.tbase.z]) + self.textpos.translation.setValue([self.tbase.x, self.tbase.y, self.tbase.z]) self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3]) # Set the angle property @@ -1149,9 +1082,12 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): if prop == "ScaleMultiplier" and "ScaleMultiplier" in properties: if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if (hasattr(self, "node_wld") and hasattr(self, "p2") - and "ArrowSizeStart" in properties - and "ArrowSizeEnd" in properties): + if ( + hasattr(self, "node_wld") + and hasattr(self, "p2") + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties + ): self.remove_dim_arrows() self.draw_dim_arrows(vobj) @@ -1161,25 +1097,26 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - elif (prop == "FontName" and hasattr(self, "font")): + elif prop == "FontName" and hasattr(self, "font"): self.font.name = str(vobj.FontName) - elif (prop == "TextColor" and "TextColor" in properties - and hasattr(self, "textcolor")): + elif prop == "TextColor" and "TextColor" in properties and hasattr(self, "textcolor"): col = vobj.TextColor self.textcolor.rgb.setValue(col[0], col[1], col[2]) - elif (prop == "LineColor" and "LineColor" in properties - and hasattr(self, "linecolor")): + elif prop == "LineColor" and "LineColor" in properties and hasattr(self, "linecolor"): col = vobj.LineColor self.linecolor.rgb.setValue(col[0], col[1], col[2]) elif prop == "LineWidth" and hasattr(self, "drawstyle"): self.drawstyle.lineWidth = vobj.LineWidth - elif (prop in ("ArrowSizeStart", "ArrowTypeStart", "ArrowSizeEnd", "ArrowTypeEnd") - and "ScaleMultiplier" in properties - and hasattr(self, "node_wld") and hasattr(self, "p2")): + elif ( + prop in ("ArrowSizeStart", "ArrowTypeStart", "ArrowSizeEnd", "ArrowTypeEnd") + and "ScaleMultiplier" in properties + and hasattr(self, "node_wld") + and hasattr(self, "p2") + ): self.updateData(obj, None) self.remove_dim_arrows() self.draw_dim_arrows(vobj) @@ -1197,8 +1134,12 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" - if not (hasattr(vobj, "ArrowTypeStart") and hasattr(vobj, "ArrowTypeEnd") and - hasattr(vobj, "ArrowSizeStart") and hasattr(vobj, "ArrowSizeEnd")): + if not ( + hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + ): return # Set scale diff --git a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py index 2ae971188a..591308b22d 100644 --- a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py +++ b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py @@ -76,34 +76,34 @@ class ViewProviderDraftAnnotation(object): def set_annotation_properties(self, vobj, properties): """Set annotation properties only if they don't already exist.""" if "ScaleMultiplier" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "General scaling factor that affects " - "the annotation consistently\n" - "because it scales the text, " - "and the line decorations, if any,\n" - "in the same proportion.") - vobj.addProperty("App::PropertyFloat", - "ScaleMultiplier", - "Annotation", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "General scaling factor that affects " + "the annotation consistently\n" + "because it scales the text, " + "and the line decorations, if any,\n" + "in the same proportion.", + ) + vobj.addProperty( + "App::PropertyFloat", "ScaleMultiplier", "Annotation", _tip, locked=True + ) vobj.ScaleMultiplier = params.get_param("DefaultAnnoScaleMultiplier") if "AnnotationStyle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Annotation style to apply " - "to this object.\n" - "When using a saved style " - "some of the view properties " - "will become read-only;\n" - "they will only be editable by changing " - "the style through " - "the 'Annotation style editor' tool.") - vobj.addProperty("App::PropertyEnumeration", - "AnnotationStyle", - "Annotation", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "Annotation style to apply " + "to this object.\n" + "When using a saved style " + "some of the view properties " + "will become read-only;\n" + "they will only be editable by changing " + "the style through " + "the 'Annotation style editor' tool.", + ) + vobj.addProperty( + "App::PropertyEnumeration", "AnnotationStyle", "Annotation", _tip, locked=True + ) styles = [] for key in vobj.Object.Document.Meta.keys(): if key.startswith("Draft_Style_"): @@ -114,33 +114,18 @@ class ViewProviderDraftAnnotation(object): def set_text_properties(self, vobj, properties): """Set text properties only if they don't already exist.""" if "FontName" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Font name") - vobj.addProperty("App::PropertyFont", - "FontName", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Font name") + vobj.addProperty("App::PropertyFont", "FontName", "Text", _tip, locked=True) vobj.FontName = params.get_param("textfont") if "FontSize" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Font size") - vobj.addProperty("App::PropertyLength", - "FontSize", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Font size") + vobj.addProperty("App::PropertyLength", "FontSize", "Text", _tip, locked=True) vobj.FontSize = params.get_param("textheight") if "TextColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Text color") - vobj.addProperty("App::PropertyColor", - "TextColor", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Text color") + vobj.addProperty("App::PropertyColor", "TextColor", "Text", _tip, locked=True) vobj.TextColor = params.get_param("DefaultTextColor") | 0x000000FF def set_units_properties(self, vobj, properties): @@ -152,65 +137,43 @@ class ViewProviderDraftAnnotation(object): return if "ArrowSizeStart" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSizeStart", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") + vobj.addProperty("App::PropertyLength", "ArrowSizeStart", "Graphics", _tip, locked=True) vobj.ArrowSizeStart = params.get_param("arrowsizestart") if "ArrowTypeStart" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowTypeStart", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") + vobj.addProperty( + "App::PropertyEnumeration", "ArrowTypeStart", "Graphics", _tip, locked=True + ) vobj.ArrowTypeStart = utils.ARROW_TYPES vobj.ArrowTypeStart = "None" if vobj.Object.Proxy.Type != "Label": if "ArrowSizeEnd" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSizeEnd", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") + vobj.addProperty( + "App::PropertyLength", "ArrowSizeEnd", "Graphics", _tip, locked=True + ) vobj.ArrowSizeEnd = params.get_param("arrowsizeend") if "ArrowTypeEnd" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowTypeEnd", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") + vobj.addProperty( + "App::PropertyEnumeration", "ArrowTypeEnd", "Graphics", _tip, locked=True + ) vobj.ArrowTypeEnd = utils.ARROW_TYPES vobj.ArrowTypeEnd = "None" if "LineWidth" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Line width") - vobj.addProperty("App::PropertyFloat", - "LineWidth", - "Graphics", - _tip, - locked=True) + vobj.addProperty("App::PropertyFloat", "LineWidth", "Graphics", _tip, locked=True) vobj.LineWidth = params.get_param("DefaultAnnoLineWidth") if "LineColor" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Line color") - vobj.addProperty("App::PropertyColor", - "LineColor", - "Graphics", - _tip, - locked=True) + vobj.addProperty("App::PropertyColor", "LineColor", "Graphics", _tip, locked=True) vobj.LineColor = params.get_param("DefaultAnnoLineColor") | 0x000000FF def dumps(self): @@ -252,7 +215,7 @@ class ViewProviderDraftAnnotation(object): for visprop in utils.get_default_annotation_style().keys(): if visprop in properties: # make property writable - vobj.setPropertyStatus(visprop, '-ReadOnly') + vobj.setPropertyStatus(visprop, "-ReadOnly") else: # set style for key, value in meta.items(): @@ -284,7 +247,7 @@ class ViewProviderDraftAnnotation(object): return None if utils.get_type(vobj.Object) == "AngularDimension": - return False # Required, else edit mode is entered. + return False # Required, else edit mode is entered. if not "Draft_Edit" in Gui.listCommands(): self.wb_before_edit = Gui.activeWorkbench() @@ -315,11 +278,8 @@ class ViewProviderDraftAnnotation(object): if utils.get_type(self.Object) in ("AngularDimension", "Label"): return - action_edit = QtGui.QAction(translate("draft", "Edit"), - menu) - QtCore.QObject.connect(action_edit, - QtCore.SIGNAL("triggered()"), - self.edit) + action_edit = QtGui.QAction(translate("draft", "Edit"), menu) + QtCore.QObject.connect(action_edit, QtCore.SIGNAL("triggered()"), self.edit) menu.addAction(action_edit) def edit(self): @@ -329,4 +289,5 @@ class ViewProviderDraftAnnotation(object): """Return the path to the icon used by the view provider.""" return ":/icons/Draft_Text.svg" + ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_draftlink.py b/src/Mod/Draft/draftviewproviders/view_draftlink.py index 60b54a7b65..b0a625bab3 100644 --- a/src/Mod/Draft/draftviewproviders/view_draftlink.py +++ b/src/Mod/Draft/draftviewproviders/view_draftlink.py @@ -30,32 +30,32 @@ # @{ from draftviewproviders.view_base import ViewProviderDraft -class ViewProviderDraftLink(ViewProviderDraft): - """ A view provider for link type object. - """ - def __init__(self,vobj): +class ViewProviderDraftLink(ViewProviderDraft): + """A view provider for link type object.""" + + def __init__(self, vobj): super(ViewProviderDraftLink, self).__init__(vobj) def getIcon(self): tp = self.Object.Proxy.Type - if tp == 'Array': - if self.Object.ArrayType == 'ortho': + if tp == "Array": + if self.Object.ArrayType == "ortho": return ":/icons/Draft_LinkArray.svg" - elif self.Object.ArrayType == 'polar': + elif self.Object.ArrayType == "polar": return ":/icons/Draft_PolarLinkArray.svg" - elif self.Object.ArrayType == 'circular': + elif self.Object.ArrayType == "circular": return ":/icons/Draft_CircularLinkArray.svg" - elif tp == 'PathArray': + elif tp == "PathArray": return ":/icons/Draft_PathLinkArray.svg" - elif tp == 'PathTwistedArray': + elif tp == "PathTwistedArray": return ":/icons/Draft_PathTwistedLinkArray.svg" - elif tp == 'PointArray': + elif tp == "PointArray": return ":/icons/Draft_PointLinkArray.svg" def claimChildren(self): obj = self.Object - if hasattr(obj,'ExpandArray'): + if hasattr(obj, "ExpandArray"): expand = obj.ExpandArray else: expand = obj.ShowElement diff --git a/src/Mod/Draft/draftviewproviders/view_facebinder.py b/src/Mod/Draft/draftviewproviders/view_facebinder.py index 2190493823..241e27ed77 100644 --- a/src/Mod/Draft/draftviewproviders/view_facebinder.py +++ b/src/Mod/Draft/draftviewproviders/view_facebinder.py @@ -31,6 +31,7 @@ import FreeCADGui as Gui from draftviewproviders.view_base import ViewProviderDraft + class ViewProviderFacebinder(ViewProviderDraft): def __init__(self, vobj): @@ -43,7 +44,8 @@ class ViewProviderFacebinder(ViewProviderDraft): if mode != 0: return None - import DraftGui # Moving this to the top of the file results in a circular import. + import DraftGui # Moving this to the top of the file results in a circular import. + taskd = DraftGui.FacebinderTaskPanel() taskd.obj = vobj.Object taskd.update() diff --git a/src/Mod/Draft/draftviewproviders/view_fillet.py b/src/Mod/Draft/draftviewproviders/view_fillet.py index 89e568f722..425a6f302a 100644 --- a/src/Mod/Draft/draftviewproviders/view_fillet.py +++ b/src/Mod/Draft/draftviewproviders/view_fillet.py @@ -42,6 +42,7 @@ class ViewProviderFillet(ViewProviderWire): def doubleClicked(self, vobj): # See setEdit in ViewProviderDraft. import FreeCADGui as Gui + Gui.runCommand("Std_TransformManip") return True diff --git a/src/Mod/Draft/draftviewproviders/view_hatch.py b/src/Mod/Draft/draftviewproviders/view_hatch.py index f66f0c20bf..994b7ad0b7 100644 --- a/src/Mod/Draft/draftviewproviders/view_hatch.py +++ b/src/Mod/Draft/draftviewproviders/view_hatch.py @@ -1,24 +1,24 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2021 Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * * +# * Copyright (c) 2021 Yorik van Havre * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** """Provides the viewprovider code for the Hatch object.""" @@ -31,6 +31,7 @@ import FreeCADGui as Gui from draftguitools.gui_hatch import Draft_Hatch_TaskPanel from draftutils.translate import translate + class ViewProviderDraftHatch: def __init__(self, vobj): @@ -80,23 +81,20 @@ class ViewProviderDraftHatch: return True def setupContextMenu(self, vobj, menu): - action_edit = QtGui.QAction(translate("draft", "Edit"), - menu) - QtCore.QObject.connect(action_edit, - QtCore.SIGNAL("triggered()"), - self.edit) + action_edit = QtGui.QAction(translate("draft", "Edit"), menu) + QtCore.QObject.connect(action_edit, QtCore.SIGNAL("triggered()"), self.edit) menu.addAction(action_edit) - action_transform = QtGui.QAction(Gui.getIcon("Std_TransformManip.svg"), - translate("Command", "Transform"), # Context `Command` instead of `draft`. - menu) - QtCore.QObject.connect(action_transform, - QtCore.SIGNAL("triggered()"), - self.transform) + action_transform = QtGui.QAction( + Gui.getIcon("Std_TransformManip.svg"), + translate("Command", "Transform"), # Context `Command` instead of `draft`. + menu, + ) + QtCore.QObject.connect(action_transform, QtCore.SIGNAL("triggered()"), self.transform) menu.addAction(action_transform) - return True # Removes `Transform` and `Set colors` from the default - # Part::FeaturePython context menu. See view_base.py. + return True # Removes `Transform` and `Set colors` from the default + # Part::FeaturePython context menu. See view_base.py. def edit(self): Gui.ActiveDocument.setEdit(self.Object, 0) diff --git a/src/Mod/Draft/draftviewproviders/view_label.py b/src/Mod/Draft/draftviewproviders/view_label.py index 0a6e70418d..2b7855aada 100644 --- a/src/Mod/Draft/draftviewproviders/view_label.py +++ b/src/Mod/Draft/draftviewproviders/view_label.py @@ -53,44 +53,25 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): super().set_text_properties(vobj, properties) if "TextAlignment" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Vertical alignment") - vobj.addProperty("App::PropertyEnumeration", - "TextAlignment", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Vertical alignment") + vobj.addProperty("App::PropertyEnumeration", "TextAlignment", "Text", _tip, locked=True) vobj.TextAlignment = ["Top", "Middle", "Bottom"] vobj.TextAlignment = "Bottom" if "MaxChars" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Maximum number of characters " - "on each line of the text box") - vobj.addProperty("App::PropertyInteger", - "MaxChars", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Maximum number of characters " "on each line of the text box" + ) + vobj.addProperty("App::PropertyInteger", "MaxChars", "Text", _tip, locked=True) if "Justification" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Horizontal alignment") - vobj.addProperty("App::PropertyEnumeration", - "Justification", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Horizontal alignment") + vobj.addProperty("App::PropertyEnumeration", "Justification", "Text", _tip, locked=True) vobj.Justification = ["Left", "Center", "Right"] if "LineSpacing" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Line spacing (relative to font size)") - vobj.addProperty("App::PropertyFloat", - "LineSpacing", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Line spacing (relative to font size)") + vobj.addProperty("App::PropertyFloat", "LineSpacing", "Text", _tip, locked=True) vobj.LineSpacing = params.get_param("LineSpacing") def set_graphics_properties(self, vobj, properties): @@ -100,24 +81,15 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): vobj.ArrowTypeStart = params.get_param("dimsymbolstart") if "Frame" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The type of frame around the text " - "of this object") - vobj.addProperty("App::PropertyEnumeration", - "Frame", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The type of frame around the text " "of this object" + ) + vobj.addProperty("App::PropertyEnumeration", "Frame", "Graphics", _tip, locked=True) vobj.Frame = ["None", "Rectangle"] if "Line" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Display a leader line or not") - vobj.addProperty("App::PropertyBool", - "Line", - "Graphics", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Display a leader line or not") + vobj.addProperty("App::PropertyBool", "Line", "Graphics", _tip, locked=True) vobj.Line = True def getIcon(self): @@ -137,7 +109,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.drawstyle = coin.SoDrawStyle() self.drawstyle.style = coin.SoDrawStyle.LINES - import PartGui # Required for "SoBrepEdgeSet" (because a label is not a Part::FeaturePython object). + import PartGui # Required for "SoBrepEdgeSet" (because a label is not a Part::FeaturePython object). self.lcoords = coin.SoCoordinate3() self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance() @@ -145,8 +117,8 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.mattext = coin.SoMaterial() self.textpos = coin.SoTransform() self.font = coin.SoFont() - self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. - self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. self.fcoords = coin.SoCoordinate3() self.frame = coin.SoType.fromName("SoBrepEdgeSet").createInstance() @@ -223,14 +195,16 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if n_points >= 2: self.line.coordIndex.deleteValues(0) self.lcoords.point.setValues(obj.Points) - self.line.coordIndex.setValues(0, - n_points, - range(n_points)) + self.line.coordIndex.setValues(0, n_points, range(n_points)) self.onChanged(obj.ViewObject, "ArrowTypeStart") # When initially called (on doc open) properties of vobj are not yet available. # This function is however triggered again from update_label. - if getattr(vobj, "Justification", "") == "Center" and obj.StraightDistance != 0.0 and obj.StraightDirection != "Custom": + if ( + getattr(vobj, "Justification", "") == "Center" + and obj.StraightDistance != 0.0 + and obj.StraightDirection != "Custom" + ): if obj.StraightDirection != "Vertical": obj.StraightDirection = "Vertical" if not hasattr(vobj, "TextAlignment"): @@ -246,8 +220,10 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if vobj.Justification == "Right": vobj.Justification = "Left" - self.onChanged(obj.ViewObject, "DisplayMode") # Property to trigger update_label and update_frame. - # We could have used a different property. + self.onChanged( + obj.ViewObject, "DisplayMode" + ) # Property to trigger update_label and update_frame. + # We could have used a different property. elif prop == "Text" and obj.Text: self.text_wld.string.setValue("") @@ -266,17 +242,26 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): obj = vobj.Object properties = vobj.PropertiesList - can_update_label = ("DisplayMode" in properties - and "FontName" in properties - and "FontSize" in properties - and "Justification" in properties - and "LineSpacing" in properties - and "ScaleMultiplier" in properties - and "TextAlignment" in properties) # Top, Middle or Bottom. - can_update_frame = (can_update_label - and "Frame" in properties) + can_update_label = ( + "DisplayMode" in properties + and "FontName" in properties + and "FontSize" in properties + and "Justification" in properties + and "LineSpacing" in properties + and "ScaleMultiplier" in properties + and "TextAlignment" in properties + ) # Top, Middle or Bottom. + can_update_frame = can_update_label and "Frame" in properties - if prop in ["DisplayMode", "FontName", "FontSize", "Justification", "LineSpacing", "TextAlignment", "Frame"]: + if prop in [ + "DisplayMode", + "FontName", + "FontSize", + "Justification", + "LineSpacing", + "TextAlignment", + "Frame", + ]: if can_update_label: self.update_label(obj, vobj) if can_update_frame: @@ -292,9 +277,11 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if can_update_frame: self.update_frame(obj, vobj) - elif (prop == "ArrowSizeStart" - and "ArrowSizeStart" in properties - and "ScaleMultiplier" in properties): + elif ( + prop == "ArrowSizeStart" + and "ArrowSizeStart" in properties + and "ScaleMultiplier" in properties + ): s = vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier if s: self.arrowpos.scaleFactor.setValue((s, s, s)) @@ -362,8 +349,9 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if obj.StraightDistance != 0.0 and obj.StraightDirection != "Custom": if obj.StraightDirection != "Vertical": obj.StraightDirection = "Vertical" - if (obj.StraightDistance < 0.0 and vobj.TextAlignment == "Top") \ - or (obj.StraightDistance > 0.0 and vobj.TextAlignment == "Bottom"): + if (obj.StraightDistance < 0.0 and vobj.TextAlignment == "Top") or ( + obj.StraightDistance > 0.0 and vobj.TextAlignment == "Bottom" + ): obj.StraightDistance = -obj.StraightDistance obj.recompute() obj.purgeTouched() @@ -417,23 +405,23 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.startSymbol = gui_utils.dim_symbol(startS) self.arrow.addChild(self.startSymbol) - prec = 10**(-utils.precision()) - x_axis = App.Vector(1,0,0) + prec = 10 ** (-utils.precision()) + x_axis = App.Vector(1, 0, 0) target_dir = None # search in Points to get first point != to TargetPoint and use it # to get the target line direction for pnt in obj.Points[-2::-1]: - if not pnt.isEqual(obj.Points[-1],prec): + if not pnt.isEqual(obj.Points[-1], prec): target_dir = pnt.sub(obj.Points[-1]) break if target_dir is None: target_dir = x_axis - target_dir_xy = obj.Placement.Rotation.inverted()*target_dir - angle = target_dir_xy.getAngle(x_axis)*App.Units.Radian + target_dir_xy = obj.Placement.Rotation.inverted() * target_dir + angle = target_dir_xy.getAngle(x_axis) * App.Units.Radian axis = x_axis.cross(target_dir_xy) rot = App.Rotation(axis, angle) - self.arrowpos.rotation.setValue((obj.Placement.Rotation*rot).Q) + self.arrowpos.rotation.setValue((obj.Placement.Rotation * rot).Q) self.arrowpos.translation.setValue(obj.Points[-1]) def update_frame(self, obj, vobj): @@ -478,9 +466,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): pts.append(first_frame_point) self.fcoords.point.setValues(pts) - self.frame.coordIndex.setValues(0, - len(pts), - range(len(pts))) + self.frame.coordIndex.setValues(0, len(pts), range(len(pts))) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftviewproviders/view_layer.py b/src/Mod/Draft/draftviewproviders/view_layer.py index 70eedc9ed6..29bbfcdac7 100644 --- a/src/Mod/Draft/draftviewproviders/view_layer.py +++ b/src/Mod/Draft/draftviewproviders/view_layer.py @@ -60,122 +60,98 @@ class ViewProviderLayer: def set_override_options(self, vobj, properties): """Set property options only if they don't already exist.""" if "OverrideLineColorChildren" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If it is true, the objects contained " - "within this layer will adopt " - "the line color of the layer") - vobj.addProperty("App::PropertyBool", - "OverrideLineColorChildren", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If it is true, the objects contained " + "within this layer will adopt " + "the line color of the layer", + ) + vobj.addProperty( + "App::PropertyBool", "OverrideLineColorChildren", "Layer", _tip, locked=True + ) vobj.OverrideLineColorChildren = True if "OverrideShapeAppearanceChildren" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If it is true, the objects contained " - "within this layer will adopt " - "the shape appearance of the layer") - vobj.addProperty("App::PropertyBool", - "OverrideShapeAppearanceChildren", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If it is true, the objects contained " + "within this layer will adopt " + "the shape appearance of the layer", + ) + vobj.addProperty( + "App::PropertyBool", "OverrideShapeAppearanceChildren", "Layer", _tip, locked=True + ) vobj.OverrideShapeAppearanceChildren = True if "UsePrintColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "If it is true, the print color " - "will be used when objects in this " - "layer are placed on a TechDraw page") - vobj.addProperty("App::PropertyBool", - "UsePrintColor", - "Print", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "If it is true, the print color " + "will be used when objects in this " + "layer are placed on a TechDraw page", + ) + vobj.addProperty("App::PropertyBool", "UsePrintColor", "Print", _tip, locked=True) def set_visual_properties(self, vobj, properties): """Set visual properties only if they don't already exist.""" if "LineColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The line color of the objects " - "contained within this layer") - vobj.addProperty("App::PropertyColor", - "LineColor", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The line color of the objects " "contained within this layer" + ) + vobj.addProperty("App::PropertyColor", "LineColor", "Layer", _tip, locked=True) vobj.LineColor = params.get_param_view("DefaultShapeLineColor") | 0x000000FF if "ShapeColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The shape color of the objects " - "contained within this layer") - vobj.addProperty("App::PropertyColor", - "ShapeColor", - "Layer", - _tip, - 4, - locked=True) # Hidden + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The shape color of the objects " "contained within this layer" + ) + vobj.addProperty( + "App::PropertyColor", "ShapeColor", "Layer", _tip, 4, locked=True + ) # Hidden vobj.ShapeColor = params.get_param_view("DefaultShapeColor") | 0x000000FF if "ShapeAppearance" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The shape appearance of the objects " - "contained within this layer") - vobj.addProperty("App::PropertyMaterialList", - "ShapeAppearance", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The shape appearance of the objects " "contained within this layer", + ) + vobj.addProperty( + "App::PropertyMaterialList", "ShapeAppearance", "Layer", _tip, locked=True + ) material = App.Material() material.DiffuseColor = params.get_param_view("DefaultShapeColor") | 0x000000FF - vobj.ShapeAppearance = (material, ) + vobj.ShapeAppearance = (material,) if "LineWidth" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The line width of the objects contained " - "within this layer") - vobj.addProperty("App::PropertyFloat", - "LineWidth", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The line width of the objects contained " "within this layer" + ) + vobj.addProperty("App::PropertyFloat", "LineWidth", "Layer", _tip, locked=True) vobj.LineWidth = params.get_param_view("DefaultShapeLineWidth") if "DrawStyle" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The draw style of the objects contained " - "within this layer") - vobj.addProperty("App::PropertyEnumeration", - "DrawStyle", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The draw style of the objects contained " "within this layer" + ) + vobj.addProperty("App::PropertyEnumeration", "DrawStyle", "Layer", _tip, locked=True) vobj.DrawStyle = utils.DRAW_STYLES vobj.DrawStyle = params.get_param("DefaultDrawStyle") if "Transparency" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The transparency of the objects " - "contained within this layer") - vobj.addProperty("App::PropertyPercent", - "Transparency", - "Layer", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "The transparency of the objects " "contained within this layer" + ) + vobj.addProperty("App::PropertyPercent", "Transparency", "Layer", _tip, locked=True) vobj.Transparency = params.get_param_view("DefaultShapeTransparency") if "LinePrintColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The line color of the objects " - "contained within this layer, " - "when used on a TechDraw page") - vobj.addProperty("App::PropertyColor", - "LinePrintColor", - "Print", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", + "The line color of the objects " + "contained within this layer, " + "when used on a TechDraw page", + ) + vobj.addProperty("App::PropertyColor", "LinePrintColor", "Print", _tip, locked=True) vobj.LinePrintColor = params.get_param("DefaultPrintColor") def getIcon(self): @@ -277,18 +253,18 @@ class ViewProviderLayer: target_vobj = target_obj.ViewObject if hasattr(target_vobj, prop): - if old_prop is None \ - or _prop_is_same(getattr(target_vobj, prop), old_prop): + if old_prop is None or _prop_is_same(getattr(target_vobj, prop), old_prop): setattr(target_vobj, prop, getattr(vobj, prop)) # Use the line color for the point color and text color, # and the line width for the point size - dic = {"LineColor": ("PointColor", "TextColor"), "LineWidth": ("PointSize", )} + dic = {"LineColor": ("PointColor", "TextColor"), "LineWidth": ("PointSize",)} if prop in dic: for target_prop in dic[prop]: if hasattr(target_vobj, target_prop): - if old_prop is None \ - or _prop_is_same(getattr(target_vobj, target_prop), old_prop): + if old_prop is None or _prop_is_same( + getattr(target_vobj, target_prop), old_prop + ): setattr(target_vobj, target_prop, getattr(vobj, prop)) def onBeforeChange(self, vobj, prop): @@ -306,7 +282,7 @@ class ViewProviderLayer: material = vobj.ShapeAppearance[0] if material.DiffuseColor != vobj.ShapeColor: material.DiffuseColor = vobj.ShapeColor - vobj.ShapeAppearance = (material, ) + vobj.ShapeAppearance = (material,) # The changed ShapeAppearance will do the rest: return @@ -315,23 +291,26 @@ class ViewProviderLayer: material = vobj.ShapeAppearance[0] if material.Transparency != vobj.Transparency / 100: material.Transparency = vobj.Transparency / 100 - vobj.ShapeAppearance = (material, ) + vobj.ShapeAppearance = (material,) # The changed ShapeAppearance will do the rest: return - if (prop == "ShapeAppearance" - and hasattr(vobj, "ShapeColor") - and hasattr(vobj, "Transparency")): + if ( + prop == "ShapeAppearance" + and hasattr(vobj, "ShapeColor") + and hasattr(vobj, "Transparency") + ): material = vobj.ShapeAppearance[0] if material.DiffuseColor != vobj.ShapeColor: vobj.ShapeColor = material.DiffuseColor if material.Transparency != vobj.Transparency / 100: vobj.Transparency = int(material.Transparency * 100) - if (prop in ("LineColor", "ShapeAppearance", "LineWidth", - "DrawStyle", "Visibility") - and hasattr(vobj, "OverrideLineColorChildren") - and hasattr(vobj, "OverrideShapeAppearanceChildren")): + if ( + prop in ("LineColor", "ShapeAppearance", "LineWidth", "DrawStyle", "Visibility") + and hasattr(vobj, "OverrideLineColorChildren") + and hasattr(vobj, "OverrideShapeAppearanceChildren") + ): old_prop = getattr(self, "old" + prop, None) self.change_view_properties(vobj, prop, old_prop) if hasattr(self, "old" + prop): @@ -349,12 +328,8 @@ class ViewProviderLayer: l_color = vobj.LineColor s_color = vobj.ShapeAppearance[0].DiffuseColor - l_color = QtGui.QColor(int(l_color[0] * 255), - int(l_color[1] * 255), - int(l_color[2] * 255)) - s_color = QtGui.QColor(int(s_color[0] * 255), - int(s_color[1] * 255), - int(s_color[2] * 255)) + l_color = QtGui.QColor(int(l_color[0] * 255), int(l_color[1] * 255), int(l_color[2] * 255)) + s_color = QtGui.QColor(int(s_color[0] * 255), int(s_color[1] * 255), int(s_color[2] * 255)) p1 = QtCore.QPointF(2, 17) p2 = QtCore.QPointF(13, 8) p3 = QtCore.QPointF(30, 15) @@ -366,8 +341,7 @@ class ViewProviderLayer: pt = QtGui.QPainter(image) pt.setBrush(QtGui.QBrush(s_color, QtCore.Qt.SolidPattern)) pt.drawPolygon([p1, p2, p3, p4]) - pt.setPen(QtGui.QPen(l_color, 2, - QtCore.Qt.SolidLine, QtCore.Qt.FlatCap)) + pt.setPen(QtGui.QPen(l_color, 2, QtCore.Qt.SolidLine, QtCore.Qt.FlatCap)) pt.drawPolygon([p1, p2, p3, p4]) pt.end() @@ -479,8 +453,9 @@ class ViewProviderLayer: # the document node, in that case we do nothing. old_parents = [sub[0] for sub in old_data] for new_parent in child.InList: - if (hasattr(new_parent, "Group") - and new_parent not in old_parents): # New group check. + if ( + hasattr(new_parent, "Group") and new_parent not in old_parents + ): # New group check. for old_parent, old_parent_group in old_data: if old_parent == old_layer: parents_to_update.append([old_parent, old_parent_group]) @@ -508,21 +483,25 @@ class ViewProviderLayer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" - action_activate = QtGui.QAction(QtGui.QIcon(":/icons/button_right.svg"), - translate("draft", "Activate Layer"), - menu) + action_activate = QtGui.QAction( + QtGui.QIcon(":/icons/button_right.svg"), translate("draft", "Activate Layer"), menu + ) action_activate.triggered.connect(self.activate) menu.addAction(action_activate) - action_reassign = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Apply.svg"), - translate("draft", "Reassign Properties of Layer"), - menu) + action_reassign = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_Apply.svg"), + translate("draft", "Reassign Properties of Layer"), + menu, + ) action_reassign.triggered.connect(self.reassign_props) menu.addAction(action_reassign) - action_select = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectGroup.svg"), - translate("draft", "Select Layer Contents"), - menu) + action_select = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_SelectGroup.svg"), + translate("draft", "Select Layer Contents"), + menu, + ) action_select.triggered.connect(self.select_contents) menu.addAction(action_select) @@ -562,21 +541,25 @@ class ViewProviderLayerContainer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" - action_add = QtGui.QAction(QtGui.QIcon(":/icons/Draft_NewLayer.svg"), - translate("draft", "Add New Layer"), - menu) + action_add = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_NewLayer.svg"), translate("draft", "Add New Layer"), menu + ) action_add.triggered.connect(self.add_layer) menu.addAction(action_add) - action_reassign = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Apply.svg"), - translate("draft", "Reassign Properties of All Layers"), - menu) + action_reassign = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_Apply.svg"), + translate("draft", "Reassign Properties of All Layers"), + menu, + ) action_reassign.triggered.connect(self.reassign_props) menu.addAction(action_reassign) - action_merge = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Layers.svg"), - translate("draft", "Merge Layer Duplicates"), - menu) + action_merge = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_Layers.svg"), + translate("draft", "Merge Layer Duplicates"), + menu, + ) action_merge.triggered.connect(self.merge_by_name) menu.addAction(action_merge) @@ -587,8 +570,14 @@ class ViewProviderLayerContainer: doc = App.ActiveDocument doc.openTransaction(translate("draft", "Add New Layer")) - Draft.make_layer(name=None, line_color=None, shape_color=None, - line_width=None, draw_style=None, transparency=None) + Draft.make_layer( + name=None, + line_color=None, + shape_color=None, + line_width=None, + draw_style=None, + transparency=None, + ) doc.recompute() doc.commitTransaction() @@ -618,9 +607,11 @@ class ViewProviderLayerContainer: # Try to find the `'base'` layer: base = None for other_layer in layers: - if ((not other_layer in to_delete) # Required if there are duplicate labels. - and other_layer != layer - and other_layer.Label.upper() == base_label.upper()): + if ( + (not other_layer in to_delete) # Required if there are duplicate labels. + and other_layer != layer + and other_layer.Label.upper() == base_label.upper() + ): base = other_layer break diff --git a/src/Mod/Draft/draftviewproviders/view_orthoarray.py b/src/Mod/Draft/draftviewproviders/view_orthoarray.py index e978e1ba97..5b9eec40bf 100644 --- a/src/Mod/Draft/draftviewproviders/view_orthoarray.py +++ b/src/Mod/Draft/draftviewproviders/view_orthoarray.py @@ -48,4 +48,5 @@ class ViewProviderOrthoArray(ViewProviderDraftArray): """Set the icon in the tree view.""" return ":/icons/Draft_Array" + ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_point.py b/src/Mod/Draft/draftviewproviders/view_point.py index 6c803c4581..9ad7bb90e1 100644 --- a/src/Mod/Draft/draftviewproviders/view_point.py +++ b/src/Mod/Draft/draftviewproviders/view_point.py @@ -32,23 +32,24 @@ from draftviewproviders.view_base import ViewProviderDraft class ViewProviderPoint(ViewProviderDraft): """A viewprovider for the Draft Point object""" + def __init__(self, obj): super(ViewProviderPoint, self).__init__(obj) def onChanged(self, vobj, prop): mode = 2 - vobj.setEditorMode('AngularDeflection', mode) - vobj.setEditorMode('BoundingBox', mode) - vobj.setEditorMode('Deviation', mode) - vobj.setEditorMode('DisplayMode', mode) - vobj.setEditorMode('DrawStyle', mode) - vobj.setEditorMode('Lighting', mode) - vobj.setEditorMode('LineColor', mode) - vobj.setEditorMode('LineWidth', mode) - vobj.setEditorMode('Pattern', mode) - vobj.setEditorMode('PatternSize', mode) - vobj.setEditorMode('ShapeAppearance', mode) - vobj.setEditorMode('Transparency', mode) + vobj.setEditorMode("AngularDeflection", mode) + vobj.setEditorMode("BoundingBox", mode) + vobj.setEditorMode("Deviation", mode) + vobj.setEditorMode("DisplayMode", mode) + vobj.setEditorMode("DrawStyle", mode) + vobj.setEditorMode("Lighting", mode) + vobj.setEditorMode("LineColor", mode) + vobj.setEditorMode("LineWidth", mode) + vobj.setEditorMode("Pattern", mode) + vobj.setEditorMode("PatternSize", mode) + vobj.setEditorMode("ShapeAppearance", mode) + vobj.setEditorMode("Transparency", mode) def getIcon(self): return ":/icons/Draft_Dot.svg" @@ -56,6 +57,7 @@ class ViewProviderPoint(ViewProviderDraft): def doubleClicked(self, vobj): # See setEdit in ViewProviderDraft. import FreeCADGui as Gui + Gui.runCommand("Std_TransformManip") return True diff --git a/src/Mod/Draft/draftviewproviders/view_polararray.py b/src/Mod/Draft/draftviewproviders/view_polararray.py index bcd67e155f..bc6593f7d5 100644 --- a/src/Mod/Draft/draftviewproviders/view_polararray.py +++ b/src/Mod/Draft/draftviewproviders/view_polararray.py @@ -48,4 +48,5 @@ class ViewProviderPolarArray(ViewProviderDraftArray): """Set the icon in the tree view.""" return ":/icons/Draft_PolarArray" + ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_rectangle.py b/src/Mod/Draft/draftviewproviders/view_rectangle.py index 12ccd73169..a9efa43aaf 100644 --- a/src/Mod/Draft/draftviewproviders/view_rectangle.py +++ b/src/Mod/Draft/draftviewproviders/view_rectangle.py @@ -34,12 +34,13 @@ from draftviewproviders.view_base import ViewProviderDraft class ViewProviderRectangle(ViewProviderDraft): - def __init__(self,vobj): + def __init__(self, vobj): super(ViewProviderRectangle, self).__init__(vobj) - _tip = QT_TRANSLATE_NOOP("App::Property","Defines a texture image (overrides hatch patterns)") - vobj.addProperty("App::PropertyFile","TextureImage", - "Draft", _tip, locked=True) + _tip = QT_TRANSLATE_NOOP( + "App::Property", "Defines a texture image (overrides hatch patterns)" + ) + vobj.addProperty("App::PropertyFile", "TextureImage", "Draft", _tip, locked=True) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftviewproviders/view_shapestring.py b/src/Mod/Draft/draftviewproviders/view_shapestring.py index 42b6f2056c..d5e07eee5f 100644 --- a/src/Mod/Draft/draftviewproviders/view_shapestring.py +++ b/src/Mod/Draft/draftviewproviders/view_shapestring.py @@ -1,24 +1,24 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2022 Mario Passaglia * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** +# *************************************************************************** +# * * +# * Copyright (c) 2022 Mario Passaglia * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** """Provides the viewprovider code for the Shapestring object.""" @@ -28,9 +28,10 @@ import FreeCADGui as Gui from draftviewproviders.view_base import ViewProviderDraft from drafttaskpanels.task_shapestring import ShapeStringTaskPanelEdit + class ViewProviderShapeString(ViewProviderDraft): - def __init__(self,vobj): + def __init__(self, vobj): vobj.Proxy = self @@ -42,7 +43,9 @@ class ViewProviderShapeString(ViewProviderDraft): if mode != 0: return None - if not "Draft_Edit" in Gui.listCommands(): # Using Draft_Edit to detect if the Draft, Arch or BIM WB has been loaded. + if ( + not "Draft_Edit" in Gui.listCommands() + ): # Using Draft_Edit to detect if the Draft, Arch or BIM WB has been loaded. self.wb_before_edit = Gui.activeWorkbench() Gui.activateWorkbench("DraftWorkbench") self.task = ShapeStringTaskPanelEdit(vobj) diff --git a/src/Mod/Draft/draftviewproviders/view_text.py b/src/Mod/Draft/draftviewproviders/view_text.py index 60a307c6c9..47de8fbfd1 100644 --- a/src/Mod/Draft/draftviewproviders/view_text.py +++ b/src/Mod/Draft/draftviewproviders/view_text.py @@ -49,23 +49,13 @@ class ViewProviderText(ViewProviderDraftAnnotation): super().set_text_properties(vobj, properties) if "Justification" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Horizontal alignment") - vobj.addProperty("App::PropertyEnumeration", - "Justification", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Horizontal alignment") + vobj.addProperty("App::PropertyEnumeration", "Justification", "Text", _tip, locked=True) vobj.Justification = ["Left", "Center", "Right"] if "LineSpacing" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Line spacing (relative to font size)") - vobj.addProperty("App::PropertyFloat", - "LineSpacing", - "Text", - _tip, - locked=True) + _tip = QT_TRANSLATE_NOOP("App::Property", "Line spacing (relative to font size)") + vobj.addProperty("App::PropertyFloat", "LineSpacing", "Text", _tip, locked=True) vobj.LineSpacing = params.get_param("LineSpacing") def getIcon(self): @@ -79,8 +69,8 @@ class ViewProviderText(ViewProviderDraftAnnotation): # Main attributes of the Coin scenegraph self.mattext = coin.SoMaterial() self.font = coin.SoFont() - self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. - self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. textdrawstyle = coin.SoDrawStyle() textdrawstyle.style = coin.SoDrawStyle.FILLED @@ -133,8 +123,7 @@ class ViewProviderText(ViewProviderDraftAnnotation): properties = vobj.PropertiesList - if (prop == "ScaleMultiplier" and "ScaleMultiplier" in properties - and vobj.ScaleMultiplier): + if prop == "ScaleMultiplier" and "ScaleMultiplier" in properties and vobj.ScaleMultiplier: if "FontSize" in properties: self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier @@ -145,8 +134,12 @@ class ViewProviderText(ViewProviderDraftAnnotation): elif prop == "FontName" and "FontName" in properties: self.font.name = vobj.FontName.encode("utf8") - elif (prop == "FontSize" and "FontSize" in properties - and "ScaleMultiplier" in properties and vobj.ScaleMultiplier): + elif ( + prop == "FontSize" + and "FontSize" in properties + and "ScaleMultiplier" in properties + and vobj.ScaleMultiplier + ): # In v0.19 this code causes an `AttributeError` exception # during loading of the document as `ScaleMultiplier` # apparently isn't set immediately when the document loads. @@ -189,7 +182,7 @@ class ViewProviderText(ViewProviderDraftAnnotation): Gui.draftToolBar.textValue.setFocus() def createObject(self): - if hasattr(self,"Object"): + if hasattr(self, "Object"): txt = self.text if not txt: self.finish() @@ -199,7 +192,7 @@ class ViewProviderText(ViewProviderDraftAnnotation): txt.pop() t_list = ['"' + l + '"' for l in txt] list_as_text = ", ".join(t_list) - string = '[' + list_as_text + ']' + string = "[" + list_as_text + "]" Gui.doCommand("FreeCAD.ActiveDocument." + self.Object.Name + ".Text = " + string) App.ActiveDocument.recompute() self.finish() diff --git a/src/Mod/Draft/draftviewproviders/view_wire.py b/src/Mod/Draft/draftviewproviders/view_wire.py index 685f83dfdd..ad4bcb666e 100644 --- a/src/Mod/Draft/draftviewproviders/view_wire.py +++ b/src/Mod/Draft/draftviewproviders/view_wire.py @@ -61,39 +61,25 @@ class ViewProviderWire(ViewProviderDraft): if not hasattr(vobj, "ArrowSizeStart"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSizeStart", - "Draft", - _tip, - locked=True) + vobj.addProperty("App::PropertyLength", "ArrowSizeStart", "Draft", _tip, locked=True) vobj.ArrowSizeStart = params.get_param("arrowsizestart") if not hasattr(vobj, "ArrowTypeStart"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowTypeStart", - "Draft", - _tip, - locked=True) + vobj.addProperty( + "App::PropertyEnumeration", "ArrowTypeStart", "Draft", _tip, locked=True + ) vobj.ArrowTypeStart = utils.ARROW_TYPES vobj.ArrowTypeStart = "None" if not hasattr(vobj, "ArrowSizeEnd"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSizeEnd", - "Draft", - _tip, - locked=True) + vobj.addProperty("App::PropertyLength", "ArrowSizeEnd", "Draft", _tip, locked=True) vobj.ArrowSizeEnd = params.get_param("arrowsizeend") if not hasattr(vobj, "ArrowTypeEnd"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowTypeEnd", - "Draft", - _tip, - locked=True) + vobj.addProperty("App::PropertyEnumeration", "ArrowTypeEnd", "Draft", _tip, locked=True) vobj.ArrowTypeEnd = utils.ARROW_TYPES vobj.ArrowTypeEnd = "None" @@ -121,11 +107,13 @@ class ViewProviderWire(ViewProviderDraft): self.onChanged(vobj, "ArrowSizeStart") def updateData(self, obj, prop): - if prop == "Points" \ - and hasattr(obj, "Points") \ - and len(obj.Points) >= 2 \ - and hasattr(self, "coords1") \ - and hasattr(self, "coords2"): + if ( + prop == "Points" + and hasattr(obj, "Points") + and len(obj.Points) >= 2 + and hasattr(self, "coords1") + and hasattr(self, "coords2") + ): self.coords1.translation.setValue(*obj.Points[0]) v1 = obj.Points[1].sub(obj.Points[0]) if not DraftVecUtils.isNull(v1): @@ -142,24 +130,25 @@ class ViewProviderWire(ViewProviderDraft): self.coords2.rotation.setValue(rot2) def onChanged(self, vobj, prop): - if prop in ["ArrowSizeStart", - "ArrowSizeEnd", - "ArrowTypeStart", - "ArrowTypeEnd", - "Visibility"] \ - and hasattr(vobj, "ArrowSizeStart") \ - and hasattr(vobj, "ArrowSizeEnd") \ - and hasattr(vobj, "ArrowTypeStart") \ - and hasattr(vobj, "ArrowTypeEnd") \ - and hasattr(vobj, "Visibility") \ - and hasattr(self, "pt1") \ - and hasattr(self, "pt2"): + if ( + prop + in ["ArrowSizeStart", "ArrowSizeEnd", "ArrowTypeStart", "ArrowTypeEnd", "Visibility"] + and hasattr(vobj, "ArrowSizeStart") + and hasattr(vobj, "ArrowSizeEnd") + and hasattr(vobj, "ArrowTypeStart") + and hasattr(vobj, "ArrowTypeEnd") + and hasattr(vobj, "Visibility") + and hasattr(self, "pt1") + and hasattr(self, "pt2") + ): rn = vobj.RootNode rn.removeChild(self.pt1) rn.removeChild(self.pt2) if vobj.Visibility: self.pt1.removeChild(self.startSymbol) - self.startSymbol = gui_utils.dim_symbol(utils.ARROW_TYPES.index(vobj.ArrowTypeStart)) + self.startSymbol = gui_utils.dim_symbol( + utils.ARROW_TYPES.index(vobj.ArrowTypeStart) + ) self.pt1.addChild(self.startSymbol) self.coords1.scaleFactor.setValue([vobj.ArrowSizeStart] * 3) @@ -172,28 +161,30 @@ class ViewProviderWire(ViewProviderDraft): rn.addChild(self.pt1) rn.addChild(self.pt2) - if prop == "LineColor" \ - and hasattr(vobj, "LineColor") \ - and hasattr(self, "pt1") \ - and hasattr(self, "pt2"): + if ( + prop == "LineColor" + and hasattr(vobj, "LineColor") + and hasattr(self, "pt1") + and hasattr(self, "pt2") + ): self.color.rgb.setValue(*vobj.LineColor[:3]) super().onChanged(vobj, prop) return def claimChildren(self): - if hasattr(self.Object,"Base"): - return [self.Object.Base,self.Object.Tool] + if hasattr(self.Object, "Base"): + return [self.Object.Base, self.Object.Tool] return [] - def flatten(self): # Only to be used for Draft_Wires. + def flatten(self): # Only to be used for Draft_Wires. if not hasattr(self, "Object"): return wp = WorkingPlane.get_working_plane() - flat_wire = wires.flattenWire(self.Object.Shape.Wires[0], - origin=wp.position, - normal=wp.axis) + flat_wire = wires.flattenWire( + self.Object.Shape.Wires[0], origin=wp.position, normal=wp.axis + ) doc = App.ActiveDocument doc.openTransaction(translate("draft", "Flatten")) diff --git a/src/Mod/Draft/draftviewproviders/view_wpproxy.py b/src/Mod/Draft/draftviewproviders/view_wpproxy.py index 579e747bd6..76e4aca7f1 100644 --- a/src/Mod/Draft/draftviewproviders/view_wpproxy.py +++ b/src/Mod/Draft/draftviewproviders/view_wpproxy.py @@ -40,33 +40,29 @@ from draftutils import params class ViewProviderWorkingPlaneProxy: """A View Provider for working plane proxies""" - def __init__(self,vobj): + def __init__(self, vobj): # ViewData: 0,1,2: position; 3,4,5,6: rotation; 7: near dist; 8: far dist, 9:aspect ratio; # 10: focal dist; 11: height (ortho) or height angle (persp); 12: ortho (0) or persp (1) _tip = QT_TRANSLATE_NOOP("App::Property", "The display length of this section plane") - vobj.addProperty("App::PropertyLength", "DisplaySize", - "Draft", _tip, - locked=True) + vobj.addProperty("App::PropertyLength", "DisplaySize", "Draft", _tip, locked=True) _tip = QT_TRANSLATE_NOOP("App::Property", "The size of the arrows of this section plane") - vobj.addProperty("App::PropertyLength", "ArrowSize", - "Draft", _tip, - locked=True) + vobj.addProperty("App::PropertyLength", "ArrowSize", "Draft", _tip, locked=True) - vobj.addProperty("App::PropertyPercent","Transparency","Base","",locked=True) + vobj.addProperty("App::PropertyPercent", "Transparency", "Base", "", locked=True) - vobj.addProperty("App::PropertyFloat","LineWidth","Base","",locked=True) + vobj.addProperty("App::PropertyFloat", "LineWidth", "Base", "", locked=True) - vobj.addProperty("App::PropertyColor","LineColor","Base","",locked=True) + vobj.addProperty("App::PropertyColor", "LineColor", "Base", "", locked=True) - vobj.addProperty("App::PropertyFloatList","ViewData","Base","",locked=True) + vobj.addProperty("App::PropertyFloatList", "ViewData", "Base", "", locked=True) - vobj.addProperty("App::PropertyBool","RestoreView","Base","",locked=True) + vobj.addProperty("App::PropertyBool", "RestoreView", "Base", "", locked=True) - vobj.addProperty("App::PropertyMap","VisibilityMap","Base","",locked=True) + vobj.addProperty("App::PropertyMap", "VisibilityMap", "Base", "", locked=True) - vobj.addProperty("App::PropertyBool","RestoreState","Base","",locked=True) + vobj.addProperty("App::PropertyBool", "RestoreState", "Base", "", locked=True) vobj.DisplaySize = 100 vobj.ArrowSize = 5 @@ -84,56 +80,63 @@ class ViewProviderWorkingPlaneProxy: def claimChildren(self): return [] - def doubleClicked(self,vobj): + def doubleClicked(self, vobj): Gui.runCommand("Draft_SelectPlane") return True - def setupContextMenu(self,vobj,menu): - action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Save Camera Position",menu) - QtCore.QObject.connect(action1,QtCore.SIGNAL("triggered()"),self.writeCamera) + def setupContextMenu(self, vobj, menu): + action1 = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_SelectPlane.svg"), "Save Camera Position", menu + ) + QtCore.QObject.connect(action1, QtCore.SIGNAL("triggered()"), self.writeCamera) menu.addAction(action1) - action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Save Visibility of Objects",menu) - QtCore.QObject.connect(action2,QtCore.SIGNAL("triggered()"),self.writeState) + action2 = QtGui.QAction( + QtGui.QIcon(":/icons/Draft_SelectPlane.svg"), "Save Visibility of Objects", menu + ) + QtCore.QObject.connect(action2, QtCore.SIGNAL("triggered()"), self.writeState) menu.addAction(action2) def writeCamera(self): - if hasattr(self,"Object"): + if hasattr(self, "Object"): n = Gui.ActiveDocument.ActiveView.getCameraNode() - App.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft","Writing camera position")+"\n") + App.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft", "Writing camera position") + "\n") cdata = list(n.position.getValue().getValue()) cdata.extend(list(n.orientation.getValue().getValue())) cdata.append(n.nearDistance.getValue()) cdata.append(n.farDistance.getValue()) cdata.append(n.aspectRatio.getValue()) cdata.append(n.focalDistance.getValue()) - if isinstance(n,coin.SoOrthographicCamera): + if isinstance(n, coin.SoOrthographicCamera): cdata.append(n.height.getValue()) - cdata.append(0.0) # orthograhic camera - elif isinstance(n,coin.SoPerspectiveCamera): + cdata.append(0.0) # orthograhic camera + elif isinstance(n, coin.SoPerspectiveCamera): cdata.append(n.heightAngle.getValue()) - cdata.append(1.0) # perspective camera + cdata.append(1.0) # perspective camera self.Object.ViewObject.ViewData = cdata def writeState(self): - if hasattr(self,"Object"): - App.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft","Writing objects shown/hidden state")+"\n") + if hasattr(self, "Object"): + App.Console.PrintMessage( + QT_TRANSLATE_NOOP("Draft", "Writing objects shown/hidden state") + "\n" + ) vis = {} for o in App.ActiveDocument.Objects: if o.ViewObject: vis[o.Name] = str(o.ViewObject.Visibility) self.Object.ViewObject.VisibilityMap = vis - def attach(self,vobj): + def attach(self, vobj): self.clip = None self.mat1 = coin.SoMaterial() self.mat2 = coin.SoMaterial() self.fcoords = coin.SoCoordinate3() fs = coin.SoIndexedFaceSet() - fs.coordIndex.setValues(0,7,[0,1,2,-1,0,2,3]) + fs.coordIndex.setValues(0, 7, [0, 1, 2, -1, 0, 2, 3]) self.drawstyle = coin.SoDrawStyle() self.drawstyle.style = coin.SoDrawStyle.LINES self.lcoords = coin.SoCoordinate3() - import PartGui # Required for "SoBrepEdgeSet" (because a WorkingPlaneProxy is not a Part::FeaturePython object). + import PartGui # Required for "SoBrepEdgeSet" (because a WorkingPlaneProxy is not a Part::FeaturePython object). + ls = coin.SoType.fromName("SoBrepEdgeSet").createInstance() # fmt: off ls.coordIndex.setValues( @@ -162,77 +165,77 @@ class ViewProviderWorkingPlaneProxy: psep.addChild(ls) sep.addChild(fsep) sep.addChild(psep) - vobj.addDisplayMode(sep,"Default") - self.onChanged(vobj,"DisplaySize") - self.onChanged(vobj,"LineColor") - self.onChanged(vobj,"Transparency") + vobj.addDisplayMode(sep, "Default") + self.onChanged(vobj, "DisplaySize") + self.onChanged(vobj, "LineColor") + self.onChanged(vobj, "Transparency") self.Object = vobj.Object - def getDisplayModes(self,vobj): + def getDisplayModes(self, vobj): return ["Default"] def getDefaultDisplayMode(self): return "Default" - def setDisplayMode(self,mode): + def setDisplayMode(self, mode): return mode - def updateData(self,obj,prop): + def updateData(self, obj, prop): if prop in ["Placement"]: - self.onChanged(obj.ViewObject,"DisplaySize") + self.onChanged(obj.ViewObject, "DisplaySize") return - def onChanged(self,vobj,prop): + def onChanged(self, vobj, prop): if prop == "LineColor": l = vobj.LineColor - self.mat1.diffuseColor.setValue([l[0],l[1],l[2]]) - self.mat2.diffuseColor.setValue([l[0],l[1],l[2]]) + self.mat1.diffuseColor.setValue([l[0], l[1], l[2]]) + self.mat2.diffuseColor.setValue([l[0], l[1], l[2]]) elif prop == "Transparency": - if hasattr(vobj,"Transparency"): - self.mat2.transparency.setValue(vobj.Transparency/100.0) + if hasattr(vobj, "Transparency"): + self.mat2.transparency.setValue(vobj.Transparency / 100.0) - elif prop in ["DisplaySize","ArrowSize"]: - if hasattr(vobj,"DisplaySize"): - l = vobj.DisplaySize.Value/2 + elif prop in ["DisplaySize", "ArrowSize"]: + if hasattr(vobj, "DisplaySize"): + l = vobj.DisplaySize.Value / 2 else: l = 1 verts = [] fverts = [] l1 = 0.1 - if hasattr(vobj,"ArrowSize"): + if hasattr(vobj, "ArrowSize"): l1 = vobj.ArrowSize.Value if vobj.ArrowSize.Value > 0 else 0.1 - l2 = l1/3 + l2 = l1 / 3 pl = App.Placement(vobj.Object.Placement) - fverts.append(pl.multVec(App.Vector(-l,-l,0))) - fverts.append(pl.multVec(App.Vector(l,-l,0))) - fverts.append(pl.multVec(App.Vector(l,l,0))) - fverts.append(pl.multVec(App.Vector(-l,l,0))) + fverts.append(pl.multVec(App.Vector(-l, -l, 0))) + fverts.append(pl.multVec(App.Vector(l, -l, 0))) + fverts.append(pl.multVec(App.Vector(l, l, 0))) + fverts.append(pl.multVec(App.Vector(-l, l, 0))) - verts.append(pl.multVec(App.Vector(0,0,0))) - verts.append(pl.multVec(App.Vector(l-l1,0,0))) - verts.append(pl.multVec(App.Vector(l-l1,l2,0))) - verts.append(pl.multVec(App.Vector(l,0,0))) - verts.append(pl.multVec(App.Vector(l-l1,-l2,0))) - verts.append(pl.multVec(App.Vector(l-l1,l2,0))) + verts.append(pl.multVec(App.Vector(0, 0, 0))) + verts.append(pl.multVec(App.Vector(l - l1, 0, 0))) + verts.append(pl.multVec(App.Vector(l - l1, l2, 0))) + verts.append(pl.multVec(App.Vector(l, 0, 0))) + verts.append(pl.multVec(App.Vector(l - l1, -l2, 0))) + verts.append(pl.multVec(App.Vector(l - l1, l2, 0))) - verts.append(pl.multVec(App.Vector(0,0,0))) - verts.append(pl.multVec(App.Vector(0,l-l1,0))) - verts.append(pl.multVec(App.Vector(-l2,l-l1,0))) - verts.append(pl.multVec(App.Vector(0,l,0))) - verts.append(pl.multVec(App.Vector(l2,l-l1,0))) - verts.append(pl.multVec(App.Vector(-l2,l-l1,0))) + verts.append(pl.multVec(App.Vector(0, 0, 0))) + verts.append(pl.multVec(App.Vector(0, l - l1, 0))) + verts.append(pl.multVec(App.Vector(-l2, l - l1, 0))) + verts.append(pl.multVec(App.Vector(0, l, 0))) + verts.append(pl.multVec(App.Vector(l2, l - l1, 0))) + verts.append(pl.multVec(App.Vector(-l2, l - l1, 0))) - verts.append(pl.multVec(App.Vector(0,0,0))) - verts.append(pl.multVec(App.Vector(0,0,l-l1))) - verts.append(pl.multVec(App.Vector(-l2,0,l-l1))) - verts.append(pl.multVec(App.Vector(0,0,l))) - verts.append(pl.multVec(App.Vector(l2,0,l-l1))) - verts.append(pl.multVec(App.Vector(-l2,0,l-l1))) - verts.append(pl.multVec(App.Vector(0,-l2,l-l1))) - verts.append(pl.multVec(App.Vector(0,0,l))) - verts.append(pl.multVec(App.Vector(0,l2,l-l1))) - verts.append(pl.multVec(App.Vector(0,-l2,l-l1))) + verts.append(pl.multVec(App.Vector(0, 0, 0))) + verts.append(pl.multVec(App.Vector(0, 0, l - l1))) + verts.append(pl.multVec(App.Vector(-l2, 0, l - l1))) + verts.append(pl.multVec(App.Vector(0, 0, l))) + verts.append(pl.multVec(App.Vector(l2, 0, l - l1))) + verts.append(pl.multVec(App.Vector(-l2, 0, l - l1))) + verts.append(pl.multVec(App.Vector(0, -l2, l - l1))) + verts.append(pl.multVec(App.Vector(0, 0, l))) + verts.append(pl.multVec(App.Vector(0, l2, l - l1))) + verts.append(pl.multVec(App.Vector(0, -l2, l - l1))) self.lcoords.point.setValues(verts) self.fcoords.point.setValues(fverts) @@ -244,7 +247,8 @@ class ViewProviderWorkingPlaneProxy: def dumps(self): return None - def loads(self,state): + def loads(self, state): return None + ## @} diff --git a/src/Mod/Draft/importAirfoilDAT.py b/src/Mod/Draft/importAirfoilDAT.py index e9af498e59..45ff0afad0 100644 --- a/src/Mod/Draft/importAirfoilDAT.py +++ b/src/Mod/Draft/importAirfoilDAT.py @@ -3,11 +3,11 @@ # \brief Airfoil (.dat) file importer # # This module provides support for importing airfoil .dat files -'''@package importAirfoilDAT +"""@package importAirfoilDAT Airfoil (.dat) file importer This module provides support for importing airfoil .dat files. -''' +""" # Check code with # flake8 --ignore=E226,E266,E401,W503 @@ -48,11 +48,11 @@ from draftutils.utils import pyopen if FreeCAD.GuiUp: from draftutils.translate import translate else: + def translate(context, txt): return txt - useDraftWire = True @@ -125,12 +125,12 @@ def process(filename): than 3 points. """ # Regex to identify data rows and throw away unused metadata - xval = r'(?P\-?\s*\d*\.*\d*([Ee]\-?\d+)?)' - yval = r'(?P\-?\s*\d*\.*\d*([Ee]\-?\d+)?)' - _regex = r'^\s*' + xval + r'\,?\s*' + yval + r'\s*$' + xval = r"(?P\-?\s*\d*\.*\d*([Ee]\-?\d+)?)" + yval = r"(?P\-?\s*\d*\.*\d*([Ee]\-?\d+)?)" + _regex = r"^\s*" + xval + r"\,?\s*" + yval + r"\s*$" regex = re.compile(_regex) - afile = pyopen(filename, 'r') + afile = pyopen(filename, "r") # read the airfoil name which is always in the first line airfoilname = afile.readline().strip() @@ -141,9 +141,7 @@ def process(filename): # Collect the data for lin in afile: curdat = regex.match(lin) - if (curdat is not None - and curdat.group("xval") - and curdat.group("yval")): + if curdat is not None and curdat.group("xval") and curdat.group("yval"): x = float(curdat.group("xval")) y = float(curdat.group("yval")) @@ -167,7 +165,7 @@ def process(filename): if coords[0:-1].count(coords[0]) > 1: flippoint = coords.index(coords[0], 1) upper = coords[0:flippoint] - lower = coords[flippoint+1:] + lower = coords[flippoint + 1 :] lower.reverse() for i in lower: upper.append(i) @@ -199,7 +197,7 @@ def process(filename): wire = Part.Wire(lines) face = Part.Face(wire) - obj = FreeCAD.ActiveDocument.addObject('Part::Feature', airfoilname) + obj = FreeCAD.ActiveDocument.addObject("Part::Feature", airfoilname) obj.Shape = face return obj diff --git a/src/Mod/Draft/importDWG.py b/src/Mod/Draft/importDWG.py index c482639d89..6b1f1126d6 100644 --- a/src/Mod/Draft/importDWG.py +++ b/src/Mod/Draft/importDWG.py @@ -2,7 +2,7 @@ ## @package importDWG # \ingroup DRAFT # \brief DWG file importer & exporter -''' +""" @package importDWG ingroup DRAFT \brief DWG file importer & exporter @@ -15,7 +15,7 @@ importDXF Test files https://knowledge.autodesk.com/support/autocad/downloads/ caas/downloads/content/autocad-sample-files.html -''' +""" # Check code quality with # flake8 --ignore=E226,E266,E401,W503 @@ -47,12 +47,11 @@ from draftutils import params if FreeCAD.GuiUp: from draftutils.translate import translate else: + def translate(context, txt): return txt - - def open(filename): """Open filename and parse using importDXF.open(). @@ -69,6 +68,7 @@ def open(filename): dxf = convertToDxf(filename) if dxf: import importDXF + doc = importDXF.open(dxf) return doc return @@ -96,6 +96,7 @@ def insert(filename, docname): dxf = convertToDxf(filename) if dxf: import importDXF + # Warning: function doesn't return? doc = importDXF.insert(dxf, docname) return doc @@ -123,6 +124,7 @@ def export(objectslist, filename): import importDXF import os import tempfile + outdir = tempfile.mkdtemp() _basename = os.path.splitext(os.path.basename(filename))[0] dxf = outdir + os.sep + _basename + ".dxf" @@ -154,7 +156,7 @@ def get_libredwg_converter(typ): path = params.get_param("TeighaFileConverter") - if "dwg2dxf" in path or "dxf2dwg" in path: # path set manually + if "dwg2dxf" in path or "dxf2dwg" in path: # path set manually if typ not in path: path = os.path.dirname(path) + "/" + typ + os.path.splitext(path)[1] if os.path.exists(path) and os.path.isfile(path): @@ -164,7 +166,7 @@ def get_libredwg_converter(typ): path = sub.replace("\\", "/") + "/" + typ + ".exe" if os.path.exists(path) and os.path.isfile(path): return path - else: # for Linux and macOS + else: # for Linux and macOS for sub in os.getenv("PATH").split(os.pathsep): path = sub + "/" + typ if os.path.exists(path) and os.path.isfile(path): @@ -192,7 +194,7 @@ def get_oda_converter(): path = params.get_param("TeighaFileConverter") - if "ODAFileConverter" in path: # path set manually + if "ODAFileConverter" in path: # path set manually if os.path.exists(path) and os.path.isfile(path): return path elif platform.system() == "Windows": @@ -206,7 +208,7 @@ def get_oda_converter(): path = "/usr/bin/ODAFileConverter" if os.path.exists(path) and os.path.isfile(path): return path - else: # for macOS + else: # for macOS path = "/Applications/ODAFileConverter.app/Contents/MacOS/ODAFileConverter" if os.path.exists(path) and os.path.isfile(path): return path @@ -233,7 +235,7 @@ def get_qcad_converter(): path = params.get_param("TeighaFileConverter") - if "dwg2dwg" in path: # path set manually + if "dwg2dwg" in path: # path set manually pass elif platform.system() == "Windows": path = os.path.expandvars("%ProgramFiles%\\QCAD\\dwg2dwg.bat").replace("\\", "/") @@ -245,7 +247,7 @@ def get_qcad_converter(): if "qcad" in sub: path = path + "/" + sub + "/" + "dwg2dwg" break - else: # for macOS + else: # for macOS path = "/Applications/QCAD.app/Contents/Resources/dwg2dwg" if os.path.exists(path) and os.path.isfile(path): @@ -274,11 +276,17 @@ def convertToDxf(dwgfilename): dwgfilename = dwgfilename.replace("\\", "/") conv = params.get_param("DWGConversion") - error_msg = translate("draft", """Error during DWG conversion. + error_msg = ( + translate( + "draft", + """Error during DWG conversion. Try moving the DWG file to a directory path without spaces and non-english characters, -or try saving to a lower DWG version.""") + "\n" +or try saving to a lower DWG version.""", + ) + + "\n" + ) - if conv in [0, 1]: # LibreDWG + if conv in [0, 1]: # LibreDWG libredwg = get_libredwg_converter("dwg2dxf") if libredwg is not None: outdir = tempfile.mkdtemp().replace("\\", "/") @@ -296,7 +304,7 @@ or try saving to a lower DWG version.""") + "\n" elif conv != 0: FCC.PrintError(translate("draft", "LibreDWG converter not found") + "\n") - if conv in [0, 2]: # ODA + if conv in [0, 2]: # ODA oda = get_oda_converter() if oda is not None: indir = os.path.dirname(dwgfilename) @@ -315,7 +323,7 @@ or try saving to a lower DWG version.""") + "\n" elif conv != 0: FCC.PrintError(translate("draft", "ODA converter not found") + "\n") - if conv in [0, 3]: # QCAD + if conv in [0, 3]: # QCAD qcad = get_qcad_converter() if qcad is not None: outdir = tempfile.mkdtemp().replace("\\", "/") @@ -323,7 +331,7 @@ or try saving to a lower DWG version.""") + "\n" result = outdir + "/" + os.path.splitext(basename)[0] + ".dxf" cmdline = [qcad, "-f", "-o", result, dwgfilename] FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n") - proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows + proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows proc.communicate() if os.path.exists(result): FCC.PrintMessage(translate("draft", "Conversion successful") + "\n") @@ -333,10 +341,16 @@ or try saving to a lower DWG version.""") + "\n" elif conv != 0: FCC.PrintError(translate("draft", "QCAD converter not found") + "\n") - FCC.PrintError(translate("draft", """No suitable external DWG converter has been found. + FCC.PrintError( + translate( + "draft", + """No suitable external DWG converter has been found. Please set one manually under menu Edit → Preferences → Import/Export → DWG For more information see: -https://wiki.freecad.org/Import_Export_Preferences""") + "\n") +https://wiki.freecad.org/Import_Export_Preferences""", + ) + + "\n" + ) return None @@ -364,7 +378,7 @@ def convertToDwg(dxffilename, dwgfilename): dwgfilename = dwgfilename.replace("\\", "/") conv = params.get_param("DWGConversion") - if conv in [0, 1]: # LibreDWG + if conv in [0, 1]: # LibreDWG libredwg = get_libredwg_converter("dxf2dwg") if libredwg is not None: cmdline = [libredwg, dxffilename, "-y", "-o", dwgfilename] @@ -375,7 +389,7 @@ def convertToDwg(dxffilename, dwgfilename): elif conv != 0: FCC.PrintError(translate("draft", "LibreDWG converter not found") + "\n") - if conv in [0, 2]: # ODA + if conv in [0, 2]: # ODA oda = get_oda_converter() if oda is not None: indir = os.path.dirname(dxffilename) @@ -389,19 +403,25 @@ def convertToDwg(dxffilename, dwgfilename): elif conv != 0: FCC.PrintError(translate("draft", "ODA converter not found") + "\n") - if conv in [0, 3]: # QCAD + if conv in [0, 3]: # QCAD qcad = get_qcad_converter() if qcad is not None: cmdline = [qcad, "-f", "-o", dwgfilename, dxffilename] FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n") - proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows + proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows proc.communicate() return dwgfilename elif conv != 0: FCC.PrintError(translate("draft", "QCAD converter not found") + "\n") - FCC.PrintError(translate("draft", """No suitable external DWG converter has been found. + FCC.PrintError( + translate( + "draft", + """No suitable external DWG converter has been found. Please set one manually under menu Edit → Preferences → Import/Export → DWG For more information see: -https://wiki.freecad.org/Import_Export_Preferences""") + "\n") +https://wiki.freecad.org/Import_Export_Preferences""", + ) + + "\n" + ) return None diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 5f1660edc7..27a39c117b 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -75,6 +75,7 @@ gui = FreeCAD.GuiUp draftui = None if gui: import FreeCADGui + try: draftui = FreeCADGui.draftToolBar except (AttributeError, NameError): @@ -89,9 +90,11 @@ if gui: from draftutils.translate import translate from PySide import QtWidgets else: + def translate(context, txt): return txt + dxfReader = None dxfColorMap = None dxfLibrary = None @@ -115,13 +118,13 @@ def errorDXFLib(gui): """ dxfAllowDownload = params.get_param("dxfAllowDownload") if dxfAllowDownload: - files = ['dxfColorMap.py', 'dxfImportObjects.py', - 'dxfLibrary.py', 'dxfReader.py'] + files = ["dxfColorMap.py", "dxfImportObjects.py", "dxfLibrary.py", "dxfReader.py"] - baseurl = 'https://raw.githubusercontent.com/yorikvanhavre/' - baseurl += 'Draft-dxf-importer/master/' + baseurl = "https://raw.githubusercontent.com/yorikvanhavre/" + baseurl += "Draft-dxf-importer/master/" import ArchCommands from FreeCAD import Base + progressbar = Base.ProgressIndicator() progressbar.start("Downloading files...", 4) for f in files: @@ -130,43 +133,63 @@ def errorDXFLib(gui): p = ArchCommands.download(baseurl + f, force=True) if not p: if gui: - message = translate("Draft", """Download of DXF libraries failed. + message = translate( + "Draft", + """Download of DXF libraries failed. Please install the DXF Library addon manually -from menu Tools → Addon Manager""") +from menu Tools → Addon Manager""", + ) QtWidgets.QMessageBox.information(None, "", message) else: - FCC.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n") - FCC.PrintWarning("Please install the DXF Library addon from Tools → Addon Manager\n") + FCC.PrintWarning( + "The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n" + ) + FCC.PrintWarning( + "Please install the DXF Library addon from Tools → Addon Manager\n" + ) break progressbar.stop() sys.path.append(FreeCAD.ConfigGet("UserAppData")) else: if gui: - message = translate('draft', """The DXF import/export libraries needed by FreeCAD to handle + message = translate( + "draft", + """The DXF import/export libraries needed by FreeCAD to handle the DXF format were not found on this system. Please either allow FreeCAD to download these libraries: 1 - Load Draft workbench 2 - Menu Edit → Preferences → Import-Export → DXF → Enable downloads Or download these libraries manually, as explained on https://github.com/yorikvanhavre/Draft-dxf-importer -To enabled FreeCAD to download these libraries, answer Yes.""") - reply = QtWidgets.QMessageBox.question(None, "", message, - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No) +To enabled FreeCAD to download these libraries, answer Yes.""", + ) + reply = QtWidgets.QMessageBox.question( + None, + "", + message, + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, + QtWidgets.QMessageBox.No, + ) if reply == QtWidgets.QMessageBox.Yes: params.set_param("dxfAllowDownload", True) errorDXFLib(gui) if reply == QtWidgets.QMessageBox.No: pass else: - FCC.PrintWarning("The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n") + FCC.PrintWarning( + "The DXF import/export libraries needed by FreeCAD to handle the DXF format are not installed.\n" + ) _ver = FreeCAD.Version() _maj = _ver[0] _min = _ver[1] if float(_maj + "." + _min) >= 0.17: - FCC.PrintWarning("Please install the DXF Library addon from Tools → Addon Manager\n") + FCC.PrintWarning( + "Please install the DXF Library addon from Tools → Addon Manager\n" + ) else: - FCC.PrintWarning("Please check https://github.com/yorikvanhavre/Draft-dxf-importer\n") + FCC.PrintWarning( + "Please check https://github.com/yorikvanhavre/Draft-dxf-importer\n" + ) def getDXFlibs(): @@ -186,6 +209,7 @@ def getDXFlibs(): global dxfLibrary, dxfColorMap, dxfReader import dxfLibrary import dxfColorMap + try: import dxfReader except Exception: @@ -197,14 +221,14 @@ def getDXFlibs(): if float(dxfLibrary.__version__[1:5]) >= CURRENTDXFLIB: libsok = True else: - FCC.PrintWarning("DXF libraries need to be updated. " - "Trying to download…\n") + FCC.PrintWarning("DXF libraries need to be updated. " "Trying to download…\n") libsok = False if not libsok: errorDXFLib(gui) try: import dxfColorMap, dxfLibrary, dxfReader import importlib + importlib.reload(dxfColorMap) importlib.reload(dxfLibrary) importlib.reload(dxfReader) @@ -236,12 +260,12 @@ def deformat(text): t = re.sub(r"\\\\.*?;", "", t) # replace UTF codes by utf chars sts = re.split("\\\\(U\\+....)", t) - t = u"".join(sts) + t = "".join(sts) # replace degrees, diameters chars - t = re.sub(r'%%d', u'°', t) - t = re.sub(r'%%c', u'Ø', t) - t = re.sub(r'%%D', u'°', t) - t = re.sub(r'%%C', u'Ø', t) + t = re.sub(r"%%d", "°", t) + t = re.sub(r"%%c", "Ø", t) + t = re.sub(r"%%D", "°", t) + t = re.sub(r"%%C", "Ø", t) # print("output text: ", t) return t @@ -299,14 +323,16 @@ def locateLayer(wantedLayer, color=None, drawstyle=None, visibility=True): # layers is a global variable. # It should probably be passed as an argument. if wantedLayer is None: - wantedLayer = '0' + wantedLayer = "0" for layer in layers: if layer.Label == wantedLayer: return layer if dxfUseDraftVisGroups: - newLayer = Draft.make_layer(name=wantedLayer, - line_color=(0.0,0.0,0.0) if not color else color, - draw_style="Solid" if not drawstyle else drawstyle) + newLayer = Draft.make_layer( + name=wantedLayer, + line_color=(0.0, 0.0, 0.0) if not color else color, + draw_style="Solid" if not drawstyle else drawstyle, + ) newLayer.Visibility = visibility else: newLayer = doc.addObject("App::DocumentObjectGroup", wantedLayer) @@ -339,7 +365,7 @@ def getdimheight(style): Use local variables, not global variables. """ for t in drawing.tables.data: - if t.name == 'dimstyle': + if t.name == "dimstyle": for a in t.data: if hasattr(a, "type"): if a.type == "dimstyle": @@ -380,7 +406,7 @@ def calcBulge(v1, bulge, v2): The new point between `v1` and `v2`. """ chord = v2.sub(v1) - sagitta = (bulge * chord.Length)/2 + sagitta = (bulge * chord.Length) / 2 perp = chord.cross(Vector(0, 0, 1)) startpoint = v1.add(chord.multiply(0.5)) if not DraftVecUtils.isNull(perp): @@ -459,7 +485,9 @@ def getACI(ob, text=False): for parent in ob.InList: if Draft.getType(parent) == "Layer": if ob in parent.Group: - if hasattr(parent, "ViewObject") and hasattr(parent.ViewObject, "OverrideChildren"): + if hasattr(parent, "ViewObject") and hasattr( + parent.ViewObject, "OverrideChildren" + ): if parent.ViewObject.OverrideChildren: return 256 # BYLAYER if text: @@ -469,9 +497,7 @@ def getACI(ob, text=False): aci = [0, 442] for i in range(255, -1, -1): ref = dxfColorMap.color_map[i] - dist = ((ref[0]-col[0])**2 - + (ref[1]-col[1])**2 - + (ref[2]-col[2])**2) + dist = (ref[0] - col[0]) ** 2 + (ref[1] - col[1]) ** 2 + (ref[2] - col[2]) ** 2 if dist <= aci[1]: aci = [i, dist] return aci[0] @@ -556,7 +582,7 @@ def isBrightBackground(): else: r1, g1, b1, _ = utils.get_rgba_tuple(params.get_param_view("BackgroundColor")) cv = Vector(r1, g1, b1) - value = cv.x*.3 + cv.y*.59 + cv.z*.11 + value = cv.x * 0.3 + cv.y * 0.59 + cv.z * 0.11 if value < 128: return False else: @@ -716,9 +742,7 @@ def vec(pt): if resolvedScale != 1: v = v * resolvedScale else: - v = Vector(round(pt[0], pre), - round(pt[1], pre), - round(pt[2], pre)) + v = Vector(round(pt[0], pre), round(pt[1], pre), round(pt[2], pre)) if resolvedScale != 1: v.multiply(resolvedScale) return v @@ -757,8 +781,7 @@ def placementFromDXFOCS(ent): WorkingPlane.align_to_point_and_axis, WorkingPlane.get_global_coords """ draftWPlane = WorkingPlane.PlaneBase() - draftWPlane.align_to_point_and_axis(Vector(0.0, 0.0, 0.0), - vec(ent.extrusion), 0.0) + draftWPlane.align_to_point_and_axis(Vector(0.0, 0.0, 0.0), vec(ent.extrusion), 0.0) # Object Coordinate Systems (OCS) # http://docs.autodesk.com/ACD/2011/ENU/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7941.htm # Arbitrary Axis Algorithm @@ -766,14 +789,14 @@ def placementFromDXFOCS(ent): # Riferimenti dell'algoritmo dell'asse arbitrario in italiano # http://docs.autodesk.com/ACD/2011/ITA/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7941.htm # http://docs.autodesk.com/ACD/2011/ITA/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-793d.htm#WSc30cd3d5faa8f6d81cb25f1ffb755717d-7ff5 - if (draftWPlane.axis == FreeCAD.Vector(1.0, 0.0, 0.0)): + if draftWPlane.axis == FreeCAD.Vector(1.0, 0.0, 0.0): draftWPlane.u = FreeCAD.Vector(0.0, 1.0, 0.0) draftWPlane.v = FreeCAD.Vector(0.0, 0.0, 1.0) - elif (draftWPlane.axis == FreeCAD.Vector(-1.0, 0.0, 0.0)): + elif draftWPlane.axis == FreeCAD.Vector(-1.0, 0.0, 0.0): draftWPlane.u = FreeCAD.Vector(0.0, -1.0, 0.0) draftWPlane.v = FreeCAD.Vector(0.0, 0.0, 1.0) else: - if ((abs(ent.extrusion[0]) < (1.0 / 64.0)) and (abs(ent.extrusion[1]) < (1.0 / 64.0))): + if (abs(ent.extrusion[0]) < (1.0 / 64.0)) and (abs(ent.extrusion[1]) < (1.0 / 64.0)): draftWPlane.u = FreeCAD.Vector(0.0, 1.0, 0.0).cross(draftWPlane.axis) else: draftWPlane.u = FreeCAD.Vector(0.0, 0.0, 1.0).cross(draftWPlane.axis) @@ -783,7 +806,7 @@ def placementFromDXFOCS(ent): draftWPlane.position = Vector(0.0, 0.0, 0.0) pl = draftWPlane.get_placement() - if ((ent.type == "lwpolyline") or (ent.type == "polyline")): + if (ent.type == "lwpolyline") or (ent.type == "polyline"): pl.Base = draftWPlane.get_global_coords(vec([0.0, 0.0, ent.elevation])) else: pl.Base = draftWPlane.get_global_coords(vec(ent.loc)) @@ -884,9 +907,9 @@ def drawPolyline(polyline, forceShape=False, num=None): edges = [] curves = False verts = [] - for p in range(len(polyline.points)-1): + for p in range(len(polyline.points) - 1): p1 = polyline.points[p] - p2 = polyline.points[p+1] + p2 = polyline.points[p + 1] v1 = vec(p1) v2 = vec(p2) verts.append(v1) @@ -911,7 +934,7 @@ def drawPolyline(polyline, forceShape=False, num=None): warn(polyline, num) verts.append(v2) if polyline.closed: - p1 = polyline.points[len(polyline.points)-1] + p1 = polyline.points[len(polyline.points) - 1] p2 = polyline.points[0] v1 = vec(p1) v2 = vec(p2) @@ -932,9 +955,9 @@ def drawPolyline(polyline, forceShape=False, num=None): width = rawValue(polyline, 43) if width and dxfRenderPolylineWidth: w = Part.Wire(edges) - w1 = w.makeOffset(width/2) + w1 = w.makeOffset(width / 2) if polyline.closed: - w2 = w.makeOffset(-width/2) + w2 = w.makeOffset(-width / 2) w1 = Part.Face(w1) w2 = Part.Face(w2) if w1.BoundBox.DiagonalLength > w2.BoundBox.DiagonalLength: @@ -996,18 +1019,15 @@ def drawArc(arc, forceShape=False): pre = Draft.precision() pl = placementFromDXFOCS(arc) rad = vec(arc.radius) - firstangle = round(arc.start_angle%360, pre) - lastangle = round(arc.end_angle%360, pre) + firstangle = round(arc.start_angle % 360, pre) + lastangle = round(arc.end_angle % 360, pre) try: if (dxfCreateDraft or dxfCreateSketch) and (not forceShape): - return Draft.make_circle(rad, pl, face=False, - startangle=firstangle, - endangle=lastangle) + return Draft.make_circle(rad, pl, face=False, startangle=firstangle, endangle=lastangle) else: circle = Part.Circle() circle.Radius = rad - shape = circle.toShape(math.radians(firstangle), - math.radians(lastangle)) + shape = circle.toShape(math.radians(firstangle), math.radians(lastangle)) shape.Placement = pl return shape except Part.OCCError: @@ -1100,7 +1120,7 @@ def drawEllipse(ellipse, forceShape=False): end = round(ellipse.end_angle, pre) majv = vec(ellipse.major) majr = majv.Length - minr = majr*ellipse.ratio + minr = majr * ellipse.ratio el = Part.Ellipse(vec((0, 0, 0)), majr, minr) x = majv.normalize() z = vec(ellipse.extrusion).normalize() @@ -1109,7 +1129,7 @@ def drawEllipse(ellipse, forceShape=False): pl = FreeCAD.Placement(m) pl.move(c) if (dxfCreateDraft or dxfCreateSketch) and (not forceShape): - if (start != 0.0) or ((end != 0.0) or (end != round(math.pi/2, pre))): + if (start != 0.0) or ((end != 0.0) or (end != round(math.pi / 2, pre))): shape = el.toShape(start, end) shape.Placement = pl return shape @@ -1182,13 +1202,13 @@ def drawMesh(mesh, forceShape=False): pts = mesh.points udim = rawValue(mesh, 71) vdim = rawValue(mesh, 72) - for u in range(udim-1): - for v in range(vdim-1): - b = u+v*udim + for u in range(udim - 1): + for v in range(vdim - 1): + b = u + v * udim p1 = pts[b] - p2 = pts[b+1] - p3 = pts[b+udim] - p4 = pts[b+udim+1] + p2 = pts[b + 1] + p3 = pts[b + udim] + p4 = pts[b + udim + 1] md.append([p1, p2, p4]) md.append([p1, p4, p3]) elif mesh.flags == 64: @@ -1276,8 +1296,7 @@ def drawSolid(solid): return None -def drawSplineIterpolation(verts, closed=False, forceShape=False, - alwaysDiscretize=False): +def drawSplineIterpolation(verts, closed=False, forceShape=False, alwaysDiscretize=False): """Return a wire or spline, opened or closed. Parameters @@ -1327,7 +1346,7 @@ def drawSplineIterpolation(verts, closed=False, forceShape=False, return ob else: if dxfDiscretizeCurves or alwaysDiscretize: - sh = Part.makePolygon(verts+[verts[0]]) + sh = Part.makePolygon(verts + [verts[0]]) else: sp = Part.BSplineCurve() # print(knots) @@ -1507,17 +1526,17 @@ def drawSpline(spline, forceShape=False): # print(groupnumber) if nbknots != len(knots): - raise ValueError('Wrong number of knots') + raise ValueError("Wrong number of knots") if nbcontrolp != len(controlpoints): - raise ValueError('Wrong number of control points') + raise ValueError("Wrong number of control points") if nbfitp != len(fitpoints): - raise ValueError('Wrong number of fit points') + raise ValueError("Wrong number of fit points") if rational == all((w == 1.0 or w is None) for w in weights): - raise ValueError('inconsistant rational flag') + raise ValueError("inconsistant rational flag") if len(weights) == 0: weights = None elif len(weights) != len(controlpoints): - raise ValueError('Wrong number of weights') + raise ValueError("Wrong number of weights") # build knotvector and multvector # this means to remove duplicate knots @@ -1538,41 +1557,42 @@ def drawSpline(spline, forceShape=False): # check if the multiplicities are valid innermults = multvector[:] if periodic else multvector[1:-1] if any(m > degree for m in innermults): # invalid - if all(m == degree+1 for m in multvector): + if all(m == degree + 1 for m in multvector): if not forceShape and weights is None: points = controlpoints[:] - del points[degree+1::degree+1] + del points[degree + 1 :: degree + 1] return Draft.make_bezcurve(points, degree=degree) else: poles = controlpoints[:] edges = [] - while len(poles) >= degree+1: + while len(poles) >= degree + 1: # bezier segments bzseg = Part.BezierCurve() bzseg.increase(degree) - bzseg.setPoles(poles[0:degree+1]) - poles = poles[degree+1:] + bzseg.setPoles(poles[0 : degree + 1]) + poles = poles[degree + 1 :] if weights is not None: - bzseg.setWeights(weights[0:degree+1]) - weights = weights[degree+1:] + bzseg.setWeights(weights[0 : degree + 1]) + weights = weights[degree + 1 :] edges.append(bzseg.toShape()) return Part.Wire(edges) else: - warn('polygon fallback on %s' % spline) - return drawSplineIterpolation(controlpoints, closed=closed, - forceShape=forceShape, - alwaysDiscretize=True) + warn("polygon fallback on %s" % spline) + return drawSplineIterpolation( + controlpoints, closed=closed, forceShape=forceShape, alwaysDiscretize=True + ) if fitpoints and not controlpoints: - return drawSplineIterpolation(fitpoints, closed=closed, - forceShape=forceShape) + return drawSplineIterpolation(fitpoints, closed=closed, forceShape=forceShape) try: bspline = Part.BSplineCurve() - bspline.buildFromPolesMultsKnots(poles=controlpoints, - mults=multvector, - knots=knotvector, - degree=degree, - periodic=periodic, - weights=weights) + bspline.buildFromPolesMultsKnots( + poles=controlpoints, + mults=multvector, + knots=knotvector, + degree=degree, + periodic=periodic, + weights=weights, + ) return bspline.toShape() except Part.OCCError: warn(spline) @@ -1640,7 +1660,7 @@ def drawBlock(blockref, num=None, createObject=False): Use local variables, not global variables. """ if not dxfStarBlocks: - if blockref.name[0] == '*': + if blockref.name[0] == "*": return None if len(blockref.entities.data) == 0: print("skipping empty block ", blockref.name) @@ -1648,48 +1668,48 @@ def drawBlock(blockref, num=None, createObject=False): # print("creating block ", blockref.name, # " containing ", len(blockref.entities.data), " entities") shapes = [] - for line in blockref.entities.get_type('line'): + for line in blockref.entities.get_type("line"): s = drawLine(line, forceShape=True) if s: shapes.append(s) - for polyline in blockref.entities.get_type('polyline'): + for polyline in blockref.entities.get_type("polyline"): if hasattr(polyline, "flags") and polyline.flags in [16, 64]: s = drawMesh(polyline, forceShape=True) else: s = drawPolyline(polyline, forceShape=True) if s: shapes.append(s) - for polyline in blockref.entities.get_type('lwpolyline'): + for polyline in blockref.entities.get_type("lwpolyline"): s = drawPolyline(polyline, forceShape=True) if s: shapes.append(s) - for arc in blockref.entities.get_type('arc'): + for arc in blockref.entities.get_type("arc"): s = drawArc(arc, forceShape=True) if s: shapes.append(s) - for circle in blockref.entities.get_type('circle'): + for circle in blockref.entities.get_type("circle"): s = drawCircle(circle, forceShape=True) if s: shapes.append(s) - for insert in blockref.entities.get_type('insert'): + for insert in blockref.entities.get_type("insert"): # print("insert ",insert," in block ",insert.block[0]) - if dxfStarBlocks or insert.block[0] != '*': + if dxfStarBlocks or insert.block[0] != "*": s = drawInsert(insert) if s: shapes.append(s) - for solid in blockref.entities.get_type('solid'): + for solid in blockref.entities.get_type("solid"): s = drawSolid(solid) if s: shapes.append(s) - for spline in blockref.entities.get_type('spline'): + for spline in blockref.entities.get_type("spline"): s = drawSpline(spline, forceShape=True) if s: shapes.append(s) - for text in blockref.entities.get_type('text'): + for text in blockref.entities.get_type("text"): if dxfImportTexts: if dxfImportLayouts or (not rawValue(text, 67)): addText(text) - for text in blockref.entities.get_type('mtext'): + for text in blockref.entities.get_type("mtext"): if dxfImportTexts: if dxfImportLayouts or (not rawValue(text, 67)): print("adding block text", text.value, " from ", blockref) @@ -1887,12 +1907,12 @@ def attribs(insert): break if index is None: return [] - j = index+1 + j = index + 1 while True: ent = drawing.entities.data[j] - if str(ent) == 'seqend': + if str(ent) == "seqend": return atts - elif str(ent) == 'attrib': + elif str(ent) == "attrib": atts.append(ent) j += 1 @@ -1992,9 +2012,7 @@ def addText(text, attrib=False): if attrib: lay = locateLayer(rawValue(text, 8)) val = rawValue(text, 1) - pos = vec([rawValue(text, 10), - rawValue(text, 20), - rawValue(text, 30)]) + pos = vec([rawValue(text, 10), rawValue(text, 20), rawValue(text, 30)]) hgt = vec(rawValue(text, 40)) else: lay = locateLayer(text.layer) @@ -2023,8 +2041,7 @@ def addText(text, attrib=False): ax = (xv.cross(Vector(1, 0, 0))).negative() if DraftVecUtils.isNull(ax): ax = Vector(0, 0, 1) - ang = -math.degrees(DraftVecUtils.angle(xv, - Vector(1, 0, 0), ax)) + ang = -math.degrees(DraftVecUtils.angle(xv, Vector(1, 0, 0), ax)) Draft.rotate(newob, ang, axis=ax) if ax == Vector(0, 0, -1): ax = Vector(0, 0, 1) @@ -2042,11 +2059,11 @@ def addText(text, attrib=False): if hasattr(text, "alignment"): yv = ax.cross(xv) if text.alignment in [1, 2, 3]: - sup = DraftVecUtils.scaleTo(yv, fsize/TEXTSCALING).negative() + sup = DraftVecUtils.scaleTo(yv, fsize / TEXTSCALING).negative() # print(ax, sup) pos = pos.add(sup) elif text.alignment in [4, 5, 6]: - sup = DraftVecUtils.scaleTo(yv, fsize/(2*TEXTSCALING)).negative() + sup = DraftVecUtils.scaleTo(yv, fsize / (2 * TEXTSCALING)).negative() pos = pos.add(sup) newob.Placement.Base = pos if gui: @@ -2263,11 +2280,11 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): drawstyle = "Dotted" if ("DASHDOT" in lt.upper()) or ("CENTER" in lt.upper()): drawstyle = "Dashdot" - locateLayer(name, color, drawstyle, layer.color>0) + locateLayer(name, color, drawstyle, layer.color > 0) else: locateLayer("0", (0.0, 0.0, 0.0), "Solid") - # Draw lines + # Draw lines lines = drawing.entities.get_type("line") if lines: FCC.PrintMessage("drawing " + str(len(lines)) + " lines...\n") @@ -2279,16 +2296,12 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): FreeCAD.ActiveDocument.recompute() if dxfMakeBlocks or dxfJoin: if sketch: - shape = Draft.make_sketch(shape, - autoconstraints=True, - addTo=sketch) + shape = Draft.make_sketch(shape, autoconstraints=True, addTo=sketch) else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) sketch = shape else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) elif dxfJoin or getShapes: if isinstance(shape, Part.Shape): shapes.append(shape) @@ -2323,23 +2336,18 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): if shape: if dxfCreateSketch: if isinstance(shape, Part.Shape): - t = FreeCAD.ActiveDocument.addObject("Part::Feature", - "Shape") + t = FreeCAD.ActiveDocument.addObject("Part::Feature", "Shape") t.Shape = shape shape = t FreeCAD.ActiveDocument.recompute() if dxfMakeBlocks or dxfJoin: if sketch: - shape = Draft.make_sketch(shape, - autoconstraints=True, - addTo=sketch) + shape = Draft.make_sketch(shape, autoconstraints=True, addTo=sketch) else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) sketch = shape else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) elif dxfJoin or getShapes: if isinstance(shape, Part.Shape): shapes.append(shape) @@ -2365,16 +2373,12 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): FreeCAD.ActiveDocument.recompute() if dxfMakeBlocks or dxfJoin: if sketch: - shape = Draft.make_sketch(shape, - autoconstraints=True, - addTo=sketch) + shape = Draft.make_sketch(shape, autoconstraints=True, addTo=sketch) else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) sketch = shape else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) elif dxfJoin or getShapes: if isinstance(shape, Part.Shape): shapes.append(shape) @@ -2398,13 +2402,14 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): if gui: d = QtWidgets.QMessageBox() d.setText("Warning: High number of entities to join (>100)") - d.setInformativeText("This might take a long time " - "or even freeze your computer. " - "Are you sure? You can also disable " - "the 'join geometry' setting in DXF " - "import preferences") - d.setStandardButtons(QtWidgets.QMessageBox.Ok - | QtWidgets.QMessageBox.Cancel) + d.setInformativeText( + "This might take a long time " + "or even freeze your computer. " + "Are you sure? You can also disable " + "the 'join geometry' setting in DXF " + "import preferences" + ) + d.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) d.setDefaultButton(QtWidgets.QMessageBox.Cancel) res = d.exec_() if res == QtWidgets.QMessageBox.Cancel: @@ -2417,7 +2422,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): # Draw circles circles = drawing.entities.get_type("circle") if circles: - FCC.PrintMessage("drawing " + str(len(circles))+" circles...\n") + FCC.PrintMessage("drawing " + str(len(circles)) + " circles...\n") for circle in circles: if dxfImportLayouts or (not rawValue(circle, 67)): shape = drawCircle(circle) @@ -2426,16 +2431,12 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): FreeCAD.ActiveDocument.recompute() if dxfMakeBlocks or dxfJoin: if sketch: - shape = Draft.make_sketch(shape, - autoconstraints=True, - addTo=sketch) + shape = Draft.make_sketch(shape, autoconstraints=True, addTo=sketch) else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) sketch = shape else: - shape = Draft.make_sketch(shape, - autoconstraints=True) + shape = Draft.make_sketch(shape, autoconstraints=True) elif dxfMakeBlocks: addToBlock(shape, circle.layer) elif getShapes: @@ -2623,6 +2624,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): _Dimension(newob) if gui: from Draft import _ViewProviderDimension + _ViewProviderDimension(newob.ViewObject) newob.Start = p1 newob.End = p2 @@ -2636,7 +2638,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): else: st = rawValue(dim, 3) size = getdimheight(st) or 1 - newob.ViewObject.FontSize = float(size)*TEXTSCALING + newob.ViewObject.FontSize = float(size) * TEXTSCALING else: FCC.PrintMessage("skipping dimensions...\n") @@ -2716,7 +2718,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): newinserts = [] for i in inserts: if dxfImportLayouts or (not rawValue(i, 67)): - if i.block[0] != '*': + if i.block[0] != "*": newinserts.append(i) inserts = newinserts if inserts: @@ -2737,8 +2739,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): if dxfMakeBlocks: addToBlock(shape, insert.layer) else: - newob = addObject(shape, "Block." + insert.block, - insert.layer) + newob = addObject(shape, "Block." + insert.block, insert.layer) if gui: formatObject(newob, insert) num += 1 @@ -2759,7 +2760,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): del blockobjects # Move layer contents to layers - for (l, contents) in layerObjects.items(): + for l, contents in layerObjects.items(): l.Group += contents # Finishing @@ -2813,11 +2814,13 @@ def _import_dxf_file(filename, doc_name=None): if gui and not use_legacy and hGrp.GetBool("dxfShowDialog", True): try: import ImportGui + entity_counts = ImportGui.preScanDxf(filename) except Exception: entity_counts = {} from DxfImportDialog import DxfImportDialog + dlg = DxfImportDialog(entity_counts) if dlg.exec_(): @@ -2833,7 +2836,7 @@ def _import_dxf_file(filename, doc_name=None): params.set_param("dxfImportAsFused", mode == 3) hGrp.SetBool("dxfShowDialog", dlg.get_show_dialog_again()) else: - return None, None, None, None # Return None to indicate cancellation + return None, None, None, None # Return None to indicate cancellation finally: if gui: FreeCADGui.resumeWaitCursor() @@ -2841,13 +2844,13 @@ def _import_dxf_file(filename, doc_name=None): import_mode = hGrp.GetInt("DxfImportMode", 2) # --- Document Handling --- - if doc_name: # INSERT operation + if doc_name: # INSERT operation try: doc = FreeCAD.getDocument(doc_name) except NameError: doc = FreeCAD.newDocument(doc_name) FreeCAD.setActiveDocument(doc_name) - else: # OPEN operation + else: # OPEN operation docname = os.path.splitext(os.path.basename(filename))[0] doc = FreeCAD.newDocument(docname) doc.Label = docname @@ -2859,7 +2862,7 @@ def _import_dxf_file(filename, doc_name=None): # Take snapshot of objects before import objects_before = set(doc.Objects) - stats = None # For C++ importer stats + stats = None # For C++ importer stats if use_legacy: getDXFlibs() if dxfReader: @@ -2867,12 +2870,14 @@ def _import_dxf_file(filename, doc_name=None): else: errorDXFLib(gui) return None, None - else: # Modern C++ Importer + else: # Modern C++ Importer if gui: import ImportGui + stats = ImportGui.readDXF(filename) else: import Import + stats = Import.readDXF(filename) # Find the newly created objects @@ -2884,7 +2889,7 @@ def _import_dxf_file(filename, doc_name=None): draft_postprocessor = DxfDraftPostProcessor(doc, newly_created_objects, import_mode) draft_postprocessor.run() - Draft.convert_draft_texts() # This is a general utility that should run for both importers + Draft.convert_draft_texts() # This is a general utility that should run for both importers doc.recompute() processing_end_time = time.perf_counter() @@ -2920,6 +2925,7 @@ def open(filename): return doc + def insert(filename, docname): """Import a file into the specified document. @@ -2969,6 +2975,7 @@ def getShapes(filename): # EXPORT ###################################################################### + def projectShape(shape, direction, tess=None): """Project shape in a given direction. @@ -3006,6 +3013,7 @@ def projectShape(shape, direction, tess=None): TechDraw.projectEx, DraftGeomUtils.cleanProjection """ import TechDraw + edges = [] try: groups = TechDraw.projectEx(shape, direction) @@ -3018,8 +3026,7 @@ def projectShape(shape, direction, tess=None): edges.append(g) # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges)) if tess: - return DraftGeomUtils.cleanProjection(Part.makeCompound(edges), - tess[0], tess[1]) + return DraftGeomUtils.cleanProjection(Part.makeCompound(edges), tess[0], tess[1]) else: return Part.makeCompound(edges) # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges)) @@ -3085,8 +3092,7 @@ def getArcData(edge): # ang1 -= DraftVecUtils.angle(edge.Curve.XAxis) # ang2 -= DraftVecUtils.angle(edge.Curve.XAxis) - return (DraftVecUtils.tup(ce), radius, - math.degrees(ang1), math.degrees(ang2)) + return (DraftVecUtils.tup(ce), radius, math.degrees(ang1), math.degrees(ang2)) def getSplineSegs(edge): @@ -3115,11 +3121,11 @@ def getSplineSegs(edge): else: points.append(edge.valueAt(edge.FirstParameter)) if edge.Length > seglength: - nbsegs = int(math.ceil(edge.Length/seglength)) - step = (edge.LastParameter-edge.FirstParameter)/nbsegs + nbsegs = int(math.ceil(edge.Length / seglength)) + step = (edge.LastParameter - edge.FirstParameter) / nbsegs for nv in range(1, nbsegs): # print("value at", nv*step, "=", edge.valueAt(nv*step)) - v = edge.valueAt(edge.FirstParameter+(nv*step)) + v = edge.valueAt(edge.FirstParameter + (nv * step)) points.append(v) points.append(edge.valueAt(edge.LastParameter)) return points @@ -3184,6 +3190,7 @@ def getWire(wire, nospline=False, lw=True, asis=False): -------- calcBulge """ + def fmt(v, b=0.0): if lw: # LWpolyline format @@ -3191,6 +3198,7 @@ def getWire(wire, nospline=False, lw=True, asis=False): else: # Polyline format return ((v.x, v.y, v.z), None, [None, None], b) + points = [] if asis: points = [fmt(v.Point) for v in wire.OrderedVertexes] @@ -3201,17 +3209,17 @@ def getWire(wire, nospline=False, lw=True, asis=False): v1 = edge.Vertexes[0].Point if DraftGeomUtils.geomType(edge) == "Circle": # polyline bulge -> negative makes the arc go clockwise - angle = edge.LastParameter-edge.FirstParameter - bul = math.tan(angle/4) + angle = edge.LastParameter - edge.FirstParameter + bul = math.tan(angle / 4) # if cross1[2] < 0: # # polyline bulge -> negative makes the arc go clockwise # bul = -bul if edge.Curve.Axis.dot(Vector(0, 0, 1)) < 0: bul = -bul points.append(fmt(v1, bul)) - elif (DraftGeomUtils.geomType(edge) in ["BSplineCurve", - "BezierCurve", - "Ellipse"]) and (not nospline): + elif (DraftGeomUtils.geomType(edge) in ["BSplineCurve", "BezierCurve", "Ellipse"]) and ( + not nospline + ): spline = getSplineSegs(edge) spline.pop() for p in spline: @@ -3255,8 +3263,7 @@ def getBlock(sh, obj, lwPoly=False): return block -def writeShape(sh, ob, dxfobject, nospline=False, lwPoly=False, - layer=None, color=None, asis=False): +def writeShape(sh, ob, dxfobject, nospline=False, lwPoly=False, layer=None, color=None, asis=False): """Write the object's shape contents in the given DXF object. Iterates over the wires (polylines) and lone edges of `sh`. @@ -3343,32 +3350,40 @@ def writeShape(sh, ob, dxfobject, nospline=False, lwPoly=False, center, radius, ang1, ang2 = getArcData(wire.Edges[0]) if center is not None: if len(wire.Edges[0].Vertexes) == 1: # circle - dxfobject.append(dxfLibrary.Circle(center, radius, - color=color, - layer=layer)) + dxfobject.append(dxfLibrary.Circle(center, radius, color=color, layer=layer)) else: # arc - dxfobject.append(dxfLibrary.Arc(center, radius, - ang1, ang2, color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.Arc(center, radius, ang1, ang2, color=color, layer=layer) + ) else: if lwPoly: if hasattr(dxfLibrary, "LwPolyLine"): - dxfobject.append(dxfLibrary.LwPolyLine(getWire(wire, nospline, asis=asis), - [0.0, 0.0], - int(DraftGeomUtils.isReallyClosed(wire)), - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.LwPolyLine( + getWire(wire, nospline, asis=asis), + [0.0, 0.0], + int(DraftGeomUtils.isReallyClosed(wire)), + color=color, + layer=layer, + ) + ) else: - FCC.PrintWarning("LwPolyLine support not found. " - "Please delete dxfLibrary.py " - "from your FreeCAD user directory " - "to force auto-update\n") + FCC.PrintWarning( + "LwPolyLine support not found. " + "Please delete dxfLibrary.py " + "from your FreeCAD user directory " + "to force auto-update\n" + ) else: - dxfobject.append(dxfLibrary.PolyLine(getWire(wire, nospline, lw=False, asis=asis), - [0.0, 0.0, 0.0], - int(DraftGeomUtils.isReallyClosed(wire)), - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.PolyLine( + getWire(wire, nospline, lw=False, asis=asis), + [0.0, 0.0, 0.0], + int(DraftGeomUtils.isReallyClosed(wire)), + color=color, + layer=layer, + ) + ) if len(processededges) < len(sh.Edges): # lone edges loneedges = [] for e in sh.Edges: @@ -3377,51 +3392,51 @@ def writeShape(sh, ob, dxfobject, nospline=False, lwPoly=False, # print("lone edges ", loneedges) for edge in loneedges: # splines - if (DraftGeomUtils.geomType(edge) in ["BSplineCurve", - "BezierCurve"]): + if DraftGeomUtils.geomType(edge) in ["BSplineCurve", "BezierCurve"]: if (len(edge.Vertexes) == 1) and (edge.Curve.isClosed()) and (edge.Area > 0): # special case: 1-vert closed spline, approximate as a circle c = DraftGeomUtils.getCircleFromSpline(edge) if c: - dxfobject.append(dxfLibrary.Circle(DraftVecUtils.tup(c.Curve.Center), - c.Curve.Radius, - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.Circle( + DraftVecUtils.tup(c.Curve.Center), + c.Curve.Radius, + color=color, + layer=layer, + ) + ) else: points = [] spline = getSplineSegs(edge) for p in spline: points.append(((p.x, p.y, p.z), None, [None, None], 0.0)) - dxfobject.append(dxfLibrary.PolyLine(points, - [0.0, 0.0, 0.0], - 0, color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.PolyLine(points, [0.0, 0.0, 0.0], 0, color=color, layer=layer) + ) elif DraftGeomUtils.geomType(edge) == "Circle": # curves center, radius, ang1, ang2 = getArcData(edge) if center is not None: if not isinstance(center, tuple): center = DraftVecUtils.tup(center) if len(edge.Vertexes) == 1: # circles - dxfobject.append(dxfLibrary.Circle(center, - radius, - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.Circle(center, radius, color=color, layer=layer) + ) else: # arcs - dxfobject.append(dxfLibrary.Arc(center, - radius, - ang1, ang2, - color=getACI(ob), - layer=layer)) + dxfobject.append( + dxfLibrary.Arc( + center, radius, ang1, ang2, color=getACI(ob), layer=layer + ) + ) elif DraftGeomUtils.geomType(edge) == "Ellipse": # ellipses: if params.get_param("DiscretizeEllipses"): points = [] spline = getSplineSegs(edge) for p in spline: points.append(((p.x, p.y, p.z), None, [None, None], 0.0)) - dxfobject.append(dxfLibrary.PolyLine(points, - [0.0, 0.0, 0.0], - 0, color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.PolyLine(points, [0.0, 0.0, 0.0], 0, color=color, layer=layer) + ) else: if hasattr(dxfLibrary, "Ellipse"): center = DraftVecUtils.tup(edge.Curve.Center) @@ -3430,30 +3445,39 @@ def writeShape(sh, ob, dxfobject, nospline=False, lwPoly=False, end = edge.LastParameter ax = edge.Curve.Focus1.sub(edge.Curve.Center) major = DraftVecUtils.tup(DraftVecUtils.scaleTo(ax, edge.Curve.MajorRadius)) - minor = edge.Curve.MinorRadius/edge.Curve.MajorRadius + minor = edge.Curve.MinorRadius / edge.Curve.MajorRadius # print("exporting ellipse: ", center, norm, # start, end, major, minor) - dxfobject.append(dxfLibrary.Ellipse(center=center, - majorAxis=major, - normalAxis=norm, - minorAxisRatio=minor, - startParameter=start, - endParameter=end, - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.Ellipse( + center=center, + majorAxis=major, + normalAxis=norm, + minorAxisRatio=minor, + startParameter=start, + endParameter=end, + color=color, + layer=layer, + ) + ) else: - FCC.PrintWarning("Ellipses support not found. " - "Please delete dxfLibrary.py " - "from your FreeCAD user directory " - "to force auto-update\n") + FCC.PrintWarning( + "Ellipses support not found. " + "Please delete dxfLibrary.py " + "from your FreeCAD user directory " + "to force auto-update\n" + ) else: # anything else is treated as lines if len(edge.Vertexes) > 1: ve1 = edge.Vertexes[0].Point ve2 = edge.Vertexes[1].Point - dxfobject.append(dxfLibrary.Line([DraftVecUtils.tup(ve1), - DraftVecUtils.tup(ve2)], - color=color, - layer=layer)) + dxfobject.append( + dxfLibrary.Line( + [DraftVecUtils.tup(ve1), DraftVecUtils.tup(ve2)], + color=color, + layer=layer, + ) + ) def writeMesh(ob, dxf): @@ -3489,10 +3513,11 @@ def writeMesh(ob, dxf): for f in meshdata[1]: faces.append([f[0] + 1, f[1] + 1, f[2] + 1]) # print(len(points),len(faces)) - dxf.append(dxfLibrary.PolyLine([points, faces], - [0.0, 0.0, 0.0], - 64, color=getACI(ob), - layer=getGroup(ob))) + dxf.append( + dxfLibrary.PolyLine( + [points, faces], [0.0, 0.0, 0.0], 64, color=getACI(ob), layer=getGroup(ob) + ) + ) def writePanelCut(ob, dxf, nospline, lwPoly, parent=None): @@ -3576,14 +3601,11 @@ def writePanelCut(ob, dxf, nospline, lwPoly, parent=None): inl = None outl = outl.Wires[0] - writeShape(outl, parent, dxf, nospline, lwPoly, - layer="Outlines", color=5) + writeShape(outl, parent, dxf, nospline, lwPoly, layer="Outlines", color=5) if inl: - writeShape(inl, parent, dxf, nospline, lwPoly, - layer="Cuts", color=4) + writeShape(inl, parent, dxf, nospline, lwPoly, layer="Cuts", color=4) if tag: - writeShape(tag, parent, dxf, nospline, lwPoly, - layer="Tags", color=2, asis=True) + writeShape(tag, parent, dxf, nospline, lwPoly, layer="Tags", color=2, asis=True) # sticky fonts can render very odd wires... # for w in tag.Edges: # pts = [(v.X, v.Y, v.Z) for v in w.Vertexes] @@ -3674,6 +3696,7 @@ def export(objectslist, filename, nospline=False, lwPoly=False): readPreferences() if not dxfUseLegacyExporter: import Import + version = 14 if nospline: version = 12 @@ -3716,24 +3739,26 @@ def export(objectslist, filename, nospline=False, lwPoly=False): # other cases, treat objects one by one dxf = dxfLibrary.Drawing() # add global variables - if hasattr(dxf,"header"): - dxf.header.append(" 9\n$DIMTXT\n 40\n" + str(params.get_param("textheight")) + "\n") + if hasattr(dxf, "header"): + dxf.header.append( + " 9\n$DIMTXT\n 40\n" + str(params.get_param("textheight")) + "\n" + ) dxf.header.append(" 9\n$INSUNITS\n 70\n4\n") for ob in exportLayers: if ob.Label != "0": # dxflibrary already creates it - ltype = 'continuous' + ltype = "continuous" if ob.ViewObject: if ob.ViewObject.DrawStyle == "Dashed": - ltype = 'DASHED' + ltype = "DASHED" elif ob.ViewObject.DrawStyle == "Dotted": - ltype = 'HIDDEN' + ltype = "HIDDEN" elif ob.ViewObject.DrawStyle == "Dashdot": - ltype = 'DASHDOT' + ltype = "DASHDOT" # print("exporting layer:", ob.Label, # getACI(ob), ltype) - dxf.layers.append(dxfLibrary.Layer(name=ob.Label, - color=getACI(ob), - lineType=ltype)) + dxf.layers.append( + dxfLibrary.Layer(name=ob.Label, color=getACI(ob), lineType=ltype) + ) base_sketch_pla = None # Placement of the 1st sketch. for ob in exportList: obtype = Draft.getType(ob) @@ -3744,22 +3769,18 @@ def export(objectslist, filename, nospline=False, lwPoly=False): sb = ob.Proxy.sheetborder if sb: sb.Placement = ob.Placement - writeShape(sb, ob, dxf, nospline, lwPoly, - layer="Sheets", color=1) + writeShape(sb, ob, dxf, nospline, lwPoly, layer="Sheets", color=1) ss = ob.Proxy.sheettag if ss: ss.Placement = ob.Placement.multiply(ss.Placement) - writeShape(ss, ob, dxf, nospline, lwPoly, - layer="SheetTags", color=1) + writeShape(ss, ob, dxf, nospline, lwPoly, layer="SheetTags", color=1) for subob in ob.Group: if Draft.getType(subob) == "PanelCut": - writePanelCut(subob, dxf, nospline, lwPoly, - parent=ob) + writePanelCut(subob, dxf, nospline, lwPoly, parent=ob) elif subob.isDerivedFrom("Part::Feature"): shp = subob.Shape.copy() shp.Placement = ob.Placement.multiply(shp.Placement) - writeShape(shp, ob, dxf, nospline, lwPoly, - layer="Outlines", color=5) + writeShape(shp, ob, dxf, nospline, lwPoly, layer="Outlines", color=5) elif obtype == "PanelCut": writePanelCut(ob, dxf, nospline, lwPoly) @@ -3777,74 +3798,103 @@ def export(objectslist, filename, nospline=False, lwPoly=False): lspc = FreeCAD.Vector(_h) p1 = ob.Placement.multVec(p2 + lspc) justifyhor = ("Left", "Center", "Right").index(vobj.TextAlign) - dxf.append(dxfLibrary.Text(t1, - p1, - alignment=p1 if justifyhor else None, - height=h1 * 0.8, - justifyhor=justifyhor, - rotation=rotation, - color=getACI(ob, text=True), - style='STANDARD', - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Text( + t1, + p1, + alignment=p1 if justifyhor else None, + height=h1 * 0.8, + justifyhor=justifyhor, + rotation=rotation, + color=getACI(ob, text=True), + style="STANDARD", + layer=getStrGroup(ob), + ) + ) if t2: ofs = FreeCAD.Vector(0, -lspc.Length, 0) if rotation: Z = FreeCAD.Vector(0, 0, 1) ofs = FreeCAD.Rotation(Z, rotation).multVec(ofs) - dxf.append(dxfLibrary.Text(t2, - p1.add(ofs), - alignment=p1.add(ofs) if justifyhor else None, - height=h2 * 0.8, - justifyhor=justifyhor, - rotation=rotation, - color=getACI(ob, text=True), - style='STANDARD', - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Text( + t2, + p1.add(ofs), + alignment=p1.add(ofs) if justifyhor else None, + height=h2 * 0.8, + justifyhor=justifyhor, + rotation=rotation, + color=getACI(ob, text=True), + style="STANDARD", + layer=getStrGroup(ob), + ) + ) elif obtype == "Axis": axes = ob.Proxy.getAxisData(ob) if not axes: continue for ax in axes: - dxf.append(dxfLibrary.Line([ax[0], - ax[1]], - color=getACI(ob), - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Line([ax[0], ax[1]], color=getACI(ob), layer=getStrGroup(ob)) + ) h = 1 if gui: vobj = ob.ViewObject h = float(vobj.FontSize) for text in vobj.Proxy.getTextData(): - pos = text[1].add(FreeCAD.Vector(0,-h/2,0)) - dxf.append(dxfLibrary.Text(text[0], - pos, - alignment=pos, - height=h, - justifyhor=1, - color=getACI(ob), - style='STANDARD', - layer=getStrGroup(ob))) + pos = text[1].add(FreeCAD.Vector(0, -h / 2, 0)) + dxf.append( + dxfLibrary.Text( + text[0], + pos, + alignment=pos, + height=h, + justifyhor=1, + color=getACI(ob), + style="STANDARD", + layer=getStrGroup(ob), + ) + ) for shape in vobj.Proxy.getShapeData(): - if hasattr(shape,"Curve") and isinstance(shape.Curve,Part.Circle): - dxf.append(dxfLibrary.Circle(shape.Curve.Center, - shape.Curve.Radius, - color=getACI(ob), - layer=getStrGroup(ob))) + if hasattr(shape, "Curve") and isinstance(shape.Curve, Part.Circle): + dxf.append( + dxfLibrary.Circle( + shape.Curve.Center, + shape.Curve.Radius, + color=getACI(ob), + layer=getStrGroup(ob), + ) + ) else: if lwPoly: - points = [(v.Point.x, v.Point.y, v.Point.z, None, None, 0.0) for v in shape.Vertexes] - dxf.append(dxfLibrary.LwPolyLine(points, - [0.0, 0.0], - 1, - color=getACI(ob), - layer=getGroup(ob))) + points = [ + (v.Point.x, v.Point.y, v.Point.z, None, None, 0.0) + for v in shape.Vertexes + ] + dxf.append( + dxfLibrary.LwPolyLine( + points, + [0.0, 0.0], + 1, + color=getACI(ob), + layer=getGroup(ob), + ) + ) else: - points = [((v.Point.x, v.Point.y, v.Point.z), None, [None, None], 0.0) for v in shape.Vertexes] - dxf.append(dxfLibrary.PolyLine(points, - [0.0, 0.0, 0.0], - 1, - color=getACI(ob), - layer=getGroup(ob))) + points = [ + ((v.Point.x, v.Point.y, v.Point.z), None, [None, None], 0.0) + for v in shape.Vertexes + ] + dxf.append( + dxfLibrary.PolyLine( + points, + [0.0, 0.0, 0.0], + 1, + color=getACI(ob), + layer=getGroup(ob), + ) + ) elif ob.isDerivedFrom("Part::Feature"): tess = None @@ -3871,27 +3921,34 @@ def export(objectslist, filename, nospline=False, lwPoly=False): sh = ob.Shape if sh: if not sh.isNull(): - if sh.ShapeType == 'Compound': + if sh.ShapeType == "Compound": if len(sh.Wires) == 1: # only one wire in this compound, # no lone edge -> polyline if len(sh.Wires[0].Edges) == len(sh.Edges): - writeShape(sh, ob, dxf, - nospline, lwPoly) + writeShape(sh, ob, dxf, nospline, lwPoly) else: # 1 wire + lone edges -> block block = getBlock(sh, ob, lwPoly) dxf.blocks.append(block) - dxf.append(dxfLibrary.Insert(name=ob.Name.upper(), - color=getACI(ob), - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Insert( + name=ob.Name.upper(), + color=getACI(ob), + layer=getStrGroup(ob), + ) + ) else: # all other cases: block block = getBlock(sh, ob, lwPoly) dxf.blocks.append(block) - dxf.append(dxfLibrary.Insert(name=ob.Name.upper(), - color=getACI(ob), - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Insert( + name=ob.Name.upper(), + color=getACI(ob), + layer=getStrGroup(ob), + ) + ) else: writeShape(sh, ob, dxf, nospline, lwPoly) @@ -3902,25 +3959,35 @@ def export(objectslist, filename, nospline=False, lwPoly=False): # well, anyway, at the moment, Draft only writes # single-line texts, so... for text in ob.LabelText: - point = DraftVecUtils.tup(Vector(ob.Position.x, - ob.Position.y - ob.LabelText.index(text), - ob.Position.z)) + point = DraftVecUtils.tup( + Vector( + ob.Position.x, + ob.Position.y - ob.LabelText.index(text), + ob.Position.z, + ) + ) if gui: height = float(ob.ViewObject.FontSize) - justifyhor = ("Left", "Center", "Right").index(ob.ViewObject.Justification) + justifyhor = ("Left", "Center", "Right").index( + ob.ViewObject.Justification + ) else: height = 1 justifyhor = 0 - dxf.append(dxfLibrary.Text(text, - point, - alignment=point if justifyhor else None, - height=height, - justifyhor=justifyhor, - color=getACI(ob, text=True), - style='STANDARD', - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Text( + text, + point, + alignment=point if justifyhor else None, + height=height, + justifyhor=justifyhor, + color=getACI(ob, text=True), + style="STANDARD", + layer=getStrGroup(ob), + ) + ) - elif obtype in ("DraftText","Text"): + elif obtype in ("DraftText", "Text"): # texts if gui: height = float(ob.ViewObject.FontSize) @@ -3929,21 +3996,29 @@ def export(objectslist, filename, nospline=False, lwPoly=False): height = 1 justifyhor = 0 for idx, text in enumerate(ob.Text): - point = DraftVecUtils.tup(Vector(ob.Placement.Base.x, - ob.Placement.Base.y - (height * 1.2 * idx), - ob.Placement.Base.z)) + point = DraftVecUtils.tup( + Vector( + ob.Placement.Base.x, + ob.Placement.Base.y - (height * 1.2 * idx), + ob.Placement.Base.z, + ) + ) rotation = math.degrees(ob.Placement.Rotation.Angle) - dxf.append(dxfLibrary.Text(text, - point, - alignment=point if justifyhor else None, - height=height * 0.8, - justifyhor=justifyhor, - rotation=rotation, - color=getACI(ob, text=True), - style='STANDARD', - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Text( + text, + point, + alignment=point if justifyhor else None, + height=height * 0.8, + justifyhor=justifyhor, + rotation=rotation, + color=getACI(ob, text=True), + style="STANDARD", + layer=getStrGroup(ob), + ) + ) - elif obtype in ["Dimension","LinearDimension"]: + elif obtype in ["Dimension", "LinearDimension"]: p1 = DraftVecUtils.tup(ob.Start) p2 = DraftVecUtils.tup(ob.End) base = Part.LineSegment(ob.Start, ob.End).toShape() @@ -3952,10 +4027,9 @@ def export(objectslist, filename, nospline=False, lwPoly=False): pbase = DraftVecUtils.tup(ob.End) else: pbase = DraftVecUtils.tup(ob.End.add(proj.negative())) - dxf.append(dxfLibrary.Dimension(pbase, - p1, p2, - color=getACI(ob), - layer=getStrGroup(ob))) + dxf.append( + dxfLibrary.Dimension(pbase, p1, p2, color=getACI(ob), layer=getStrGroup(ob)) + ) dxf.saveas(filename) @@ -3966,8 +4040,8 @@ def export(objectslist, filename, nospline=False, lwPoly=False): class dxfcounter: - """DXF counter class to count the number of entities. - """ + """DXF counter class to count the number of entities.""" + def __init__(self): # this leaves 10000 entities for the template self.count = 10000 @@ -3975,7 +4049,7 @@ class dxfcounter: def incr(self, matchobj): self.count += 1 # print(format(self.count, '02x')) - return format(self.count, '02x') + return format(self.count, "02x") def exportPage(page, filename): @@ -4025,8 +4099,7 @@ def exportPage(page, filename): template = template.replace(editables[i], values[i]) else: # dummy default template - print("DXF version of the template not found. " - "Creating a default empty template.") + print("DXF version of the template not found. " "Creating a default empty template.") _v = FreeCAD.Version() _version = _v[0] + "." + _v[1] + "-" + _v[2] template = "999\nFreeCAD DXF exporter v" + _version + "\n" @@ -4041,8 +4114,7 @@ def exportPage(page, filename): if ver: # at the moment this is not used. # TODO: if r12, do not print ellipses or splines - if ver[0].upper() in ["AC1009", "AC1010", "AC1011", - "AC1012", "AC1013"]: + if ver[0].upper() in ["AC1009", "AC1010", "AC1011", "AC1012", "AC1013"]: r12 = True for view in views: b, e = getViewDXF(view) @@ -4106,8 +4178,7 @@ def getViewBlock(geom, view, blockcount): for g in geom: # getDXF returns a list of entities if dxfExportBlocks: # change layer and set color and ltype to BYBLOCK (0) - g = g.replace("sheet_layer\n", - "0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") + g = g.replace("sheet_layer\n", "0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") block += "0\nBLOCK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockBegin\n2\n" block += view.Name + str(blockcount) block += "\n70\n0\n10\n0\n20\n0\n3\n" @@ -4117,7 +4188,14 @@ def getViewBlock(geom, view, blockcount): insert += "0\nINSERT\n5\n_handle_\n8\n0\n6\nBYLAYER\n62\n256\n2\n" insert += view.Name + str(blockcount) insert += "\n10\n" + str(view.X) + "\n20\n" + str(view.Y) - insert += "\n30\n0\n41\n" + str(view.Scale) + "\n42\n" + str(view.Scale) + "\n43\n" + str(view.Scale) + insert += ( + "\n30\n0\n41\n" + + str(view.Scale) + + "\n42\n" + + str(view.Scale) + + "\n43\n" + + str(view.Scale) + ) insert += "\n50\n" + str(r) + "\n" blockcount += 1 else: @@ -4170,17 +4248,18 @@ def getViewDXF(view): elif view.isDerivedFrom("TechDraw::DrawViewArch"): import ArchSectionPlane + geom = ArchSectionPlane.getDXF(view) block, insert, blockcount = getViewBlock(geom, view, blockcount) elif view.isDerivedFrom("TechDraw::DrawViewPart"): import TechDraw + for obj in view.Source: proj = TechDraw.projectToDXF(obj.Shape, view.Direction) if dxfExportBlocks: # change layer and set color and ltype to BYBLOCK (0) - proj = proj.replace("sheet_layer\n", - "0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") + proj = proj.replace("sheet_layer\n", "0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") block += "0\nBLOCK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockBegin\n2\n" block += view.Name + str(blockcount) block += "\n70\n0\n10\n0\n20\n0\n3\n" + view.Name + str(blockcount) @@ -4196,12 +4275,12 @@ def getViewDXF(view): blockcount += 1 else: proj = proj.replace("sheet_layer\n", "0\n5\n_handle_\n") - insert += proj # view.Rotation is ignored + insert += proj # view.Rotation is ignored elif view.isDerivedFrom("TechDraw::DrawViewAnnotation"): insert = "0\nTEXT\n5\n_handle_\n8\n0\n100\nAcDbEntity\n100\nAcDbText\n5\n_handle_" insert += "\n10\n" + str(view.X) + "\n20\n" + str(view.Y) - insert += "\n30\n0\n40\n" + str(view.Scale/2) + insert += "\n30\n0\n40\n" + str(view.Scale / 2) insert += "\n50\n" + str(view.Rotation) insert += "\n1\n" + view.Text[0] + "\n" @@ -4250,7 +4329,7 @@ def readPreferences(): import_mode = 1 elif hGrp.GetBool("dxfImportAsFused", False): import_mode = 3 - else: # Default to "Individual part shapes" + else: # Default to "Individual part shapes" import_mode = 2 hGrp.SetInt("DxfImportMode", import_mode) @@ -4260,7 +4339,7 @@ def readPreferences(): # Legacy override for sketch creation takes highest priority dxfCreateSketch = hGrp.GetBool("dxfCreateSketch", False) - if dxfCreateSketch: # dxfCreateSketch overrides the import mode for the legacy importer + if dxfCreateSketch: # dxfCreateSketch overrides the import mode for the legacy importer dxfCreatePart = False dxfCreateDraft = False dxfMakeBlocks = False @@ -4300,8 +4379,10 @@ def readPreferences(): dxfBrightBackground = isBrightBackground() dxfDefaultColor = getColor() + class DxfImportReporter: """Formats and reports statistics from a DXF import process.""" + def __init__(self, filename, stats_dict, total_time=0.0): self.filename = filename self.stats = stats_dict @@ -4322,30 +4403,30 @@ class DxfImportReporter: lines.append(f"File encoding: {self.stats.get('dxfEncoding', 'Unknown')}") # Scaling info - file_units = self.stats.get('fileUnits', 'Not specified') - source = self.stats.get('scalingSource', '') + file_units = self.stats.get("fileUnits", "Not specified") + source = self.stats.get("scalingSource", "") if source: lines.append(f"File units: {file_units} (from {source})") else: lines.append(f"File units: {file_units}") - manual_scaling = self.stats.get('importSettings', {}).get('Manual scaling factor', '1.0') + manual_scaling = self.stats.get("importSettings", {}).get("Manual scaling factor", "1.0") lines.append(f"Manual scaling factor: {manual_scaling}") - final_scaling = self.stats.get('finalScalingFactor', 1.0) + final_scaling = self.stats.get("finalScalingFactor", 1.0) lines.append(f"Final scaling: 1 DXF unit = {final_scaling:.4f} mm") lines.append("") # Timing lines.append("Performance:") - cpp_time = self.stats.get('importTimeSeconds', 0.0) + cpp_time = self.stats.get("importTimeSeconds", 0.0) lines.append(f" - C++ import time: {cpp_time:.4f} seconds") lines.append(f" - Total import time: {self.total_time:.4f} seconds") lines.append("") # Settings lines.append("Import settings:") - settings = self.stats.get('importSettings', {}) + settings = self.stats.get("importSettings", {}) if settings: for key, value in sorted(settings.items()): lines.append(f" - {key}: {value}") @@ -4356,7 +4437,7 @@ class DxfImportReporter: # Counts lines.append("Entity counts:") total_read = 0 - unsupported_keys = self.stats.get('unsupportedFeatures', {}).keys() + unsupported_keys = self.stats.get("unsupportedFeatures", {}).keys() unsupported_entity_names = set() for key in unsupported_keys: # Extract the entity name from the key string, e.g., 'HATCH' from "Entity type 'HATCH'" @@ -4365,7 +4446,7 @@ class DxfImportReporter: unsupported_entity_names.add(entity_name_match.group(1)) has_unsupported_indicator = False - entities = self.stats.get('entityCounts', {}) + entities = self.stats.get("entityCounts", {}) if entities: for key, value in sorted(entities.items()): indicator = "" @@ -4384,7 +4465,7 @@ class DxfImportReporter: # System Blocks lines.append("System Blocks:") - system_blocks = self.stats.get('systemBlockCounts', {}) + system_blocks = self.stats.get("systemBlockCounts", {}) if system_blocks: for key, value in sorted(system_blocks.items()): lines.append(f" - {key}: {value}") @@ -4397,7 +4478,7 @@ class DxfImportReporter: lines.append("") lines.append("Unsupported features:") - unsupported = self.stats.get('unsupportedFeatures', {}) + unsupported = self.stats.get("unsupportedFeatures", {}) if unsupported: for key, occurrences in sorted(unsupported.items()): count = len(occurrences) @@ -4437,6 +4518,7 @@ class DxfDraftPostProcessor: converting them into fully parametric Draft objects while preserving the block and layer hierarchy. """ + def __init__(self, doc, new_objects, import_mode): self.doc = doc self.all_imported_objects = new_objects @@ -4455,8 +4537,7 @@ class DxfDraftPostProcessor: for block_def_obj in block_group.Group: if block_def_obj.isValid() and block_def_obj.isDerivedFrom("Part::Compound"): block_definitions[block_def_obj] = [ - child for child in block_def_obj.Links - if child.isValid() + child for child in block_def_obj.Links if child.isValid() ] all_block_internal_objects_set = set() @@ -4489,12 +4570,13 @@ class DxfDraftPostProcessor: # Skip invalid objects or objects that are block definitions themselves (their # links/children will be converted) - if not part_obj.isValid() or \ - (part_obj.isDerivedFrom("Part::Compound") and hasattr(part_obj, "Links")): + if not part_obj.isValid() or ( + part_obj.isDerivedFrom("Part::Compound") and hasattr(part_obj, "Links") + ): return None, None new_obj = None - obj_type_str = None # Will be set based on converted type + obj_type_str = None # Will be set based on converted type # Handle specific Part primitives (created directly by C++ importer as Part::Line, # Part::Circle, Part::Vertex) These C++ primitives (Part::Line, Part::Circle) inherently @@ -4503,12 +4585,13 @@ class DxfDraftPostProcessor: # Input `part_obj` is Part::Line. Create a Part::Part2DObjectPython as the # Python-extensible base for Draft Line. Part::Part2DObjectPython (via Part::Feature) # inherently has Shape and Placement, and supports .Proxy. - new_obj = self.doc.addObject("Part::Part2DObjectPython", - self.doc.getUniqueObjectName("Line")) + new_obj = self.doc.addObject( + "Part::Part2DObjectPython", self.doc.getUniqueObjectName("Line") + ) # Transfer the TopoDS_Shape from the original Part::Line to the new object's Shape # property. new_obj.Shape = part_obj.Shape - Draft.Wire(new_obj) # Attach the Python proxy. It will find Shape, Placement. + Draft.Wire(new_obj) # Attach the Python proxy. It will find Shape, Placement. # Manually transfer the parametric data from the Part::Line primitive # to the new Draft.Wire's 'Points' property. @@ -4520,8 +4603,9 @@ class DxfDraftPostProcessor: elif part_obj.isDerivedFrom("Part::Circle"): # Input `part_obj` is Part::Circle. Create a Part::Part2DObjectPython. - new_obj = self.doc.addObject("Part::Part2DObjectPython", - self.doc.getUniqueObjectName("Circle")) + new_obj = self.doc.addObject( + "Part::Part2DObjectPython", self.doc.getUniqueObjectName("Circle") + ) # Transfer the TopoDS_Shape from the original Part::Circle. This needs to happen # *before* proxy attach. new_obj.Shape = part_obj.Shape @@ -4535,37 +4619,42 @@ class DxfDraftPostProcessor: # to them. # Part::Circle has Radius, Angle1, Angle2 properties. # Draft.Circle proxy uses FirstAngle and LastAngle instead of Angle1 and Angle2. - if hasattr(part_obj, 'Radius'): + if hasattr(part_obj, "Radius"): new_obj.Radius = FreeCAD.Units.Quantity(part_obj.Radius.Value, "mm") # Calculate and transfer angles - if hasattr(part_obj, 'Angle1') and hasattr(part_obj, 'Angle2'): + if hasattr(part_obj, "Angle1") and hasattr(part_obj, "Angle2"): start_angle, end_angle = self._get_canonical_angles( - part_obj.Angle1.Value, - part_obj.Angle2.Value, - part_obj.Radius.Value + part_obj.Angle1.Value, part_obj.Angle2.Value, part_obj.Radius.Value ) new_obj.FirstAngle = FreeCAD.Units.Quantity(start_angle, "deg") new_obj.LastAngle = FreeCAD.Units.Quantity(end_angle, "deg") # Determine the final object type string based on the canonical angles - is_full_circle = (abs(new_obj.FirstAngle.Value - 0.0) < 1e-7 and - abs(new_obj.LastAngle.Value - 360.0) < 1e-7) + is_full_circle = ( + abs(new_obj.FirstAngle.Value - 0.0) < 1e-7 + and abs(new_obj.LastAngle.Value - 360.0) < 1e-7 + ) obj_type_str = "Circle" if is_full_circle else "Arc" - - elif part_obj.isDerivedFrom("Part::Vertex"): # Input `part_obj` is Part::Vertex (C++ primitive for a point location). + elif part_obj.isDerivedFrom( + "Part::Vertex" + ): # Input `part_obj` is Part::Vertex (C++ primitive for a point location). # For Draft.Point, the proxy expects an App::FeaturePython base. - new_obj = self.doc.addObject("App::FeaturePython", self.doc.getUniqueObjectName("Point")) - new_obj.addExtension("Part::AttachExtensionPython") # Needed to provide Placement for App::FeaturePython. + new_obj = self.doc.addObject( + "App::FeaturePython", self.doc.getUniqueObjectName("Point") + ) + new_obj.addExtension( + "Part::AttachExtensionPython" + ) # Needed to provide Placement for App::FeaturePython. # Transfer Placement explicitly from the original Part::Vertex. - if hasattr(part_obj, 'Placement'): + if hasattr(part_obj, "Placement"): new_obj.Placement = part_obj.Placement else: new_obj.Placement = FreeCAD.Placement() - Draft.Point(new_obj) # Attach the Python proxy. + Draft.Point(new_obj) # Attach the Python proxy. obj_type_str = "Point" elif part_obj.isDerivedFrom("Part::Ellipse"): @@ -4576,7 +4665,9 @@ class DxfDraftPostProcessor: if is_full_ellipse: # Create the C++ base object that has .Shape and .Placement. - new_obj = self.doc.addObject("Part::Part2DObjectPython", self.doc.getUniqueObjectName("Ellipse")) + new_obj = self.doc.addObject( + "Part::Part2DObjectPython", self.doc.getUniqueObjectName("Ellipse") + ) # Attach the parametric Draft.Ellipse Python proxy. Draft.Ellipse(new_obj) @@ -4591,15 +4682,20 @@ class DxfDraftPostProcessor: else: # Fallback for elliptical arcs. - new_obj = self.doc.addObject("Part::Part2DObjectPython", self.doc.getUniqueObjectName("EllipticalArc")) - Draft.Wire(new_obj) # Attach proxy. + new_obj = self.doc.addObject( + "Part::Part2DObjectPython", self.doc.getUniqueObjectName("EllipticalArc") + ) + Draft.Wire(new_obj) # Attach proxy. # Re-create geometry at the origin using parametric properties. # Convert degrees back to radians for the geometry kernel. center_at_origin = FreeCAD.Vector(0, 0, 0) - geom = Part.Ellipse(center_at_origin, part_obj.MajorRadius.Value, part_obj.MinorRadius.Value) - shape_at_origin = geom.toShape(math.radians(part_obj.Angle1.Value), - math.radians(part_obj.Angle2.Value)) + geom = Part.Ellipse( + center_at_origin, part_obj.MajorRadius.Value, part_obj.MinorRadius.Value + ) + shape_at_origin = geom.toShape( + math.radians(part_obj.Angle1.Value), math.radians(part_obj.Angle2.Value) + ) # Assign the un-transformed shape and the separate placement. new_obj.Shape = shape_at_origin @@ -4607,17 +4703,23 @@ class DxfDraftPostProcessor: obj_type_str = "Shape" # --- Handle generic Part::Feature objects (from C++ importer, wrapping TopoDS_Shapes like Wires, Splines, Ellipses) --- - elif part_obj.isDerivedFrom("Part::Feature"): # Input `part_obj` is a generic Part::Feature (from C++ importer). - shape = part_obj.Shape # This is the underlying TopoDS_Shape (Wire, Edge, Compound, Face etc.). + elif part_obj.isDerivedFrom( + "Part::Feature" + ): # Input `part_obj` is a generic Part::Feature (from C++ importer). + shape = ( + part_obj.Shape + ) # This is the underlying TopoDS_Shape (Wire, Edge, Compound, Face etc.). if not shape.isValid(): return None, None # Determine specific Draft object type based on the ShapeType of the TopoDS_Shape. - if shape.ShapeType == "Wire": # If the TopoDS_Shape is a Wire (from DXF POLYLINE). + if shape.ShapeType == "Wire": # If the TopoDS_Shape is a Wire (from DXF POLYLINE). # Create a Part::Part2DObjectPython as the Python-extensible base for Draft Wire. - new_obj = self.doc.addObject("Part::Part2DObjectPython", self.doc.getUniqueObjectName("Wire")) - new_obj.Shape = shape # Transfer the TopoDS_Wire from the original Part::Feature. - Draft.Wire(new_obj) # Attach Python proxy. It will find Shape, Placement. + new_obj = self.doc.addObject( + "Part::Part2DObjectPython", self.doc.getUniqueObjectName("Wire") + ) + new_obj.Shape = shape # Transfer the TopoDS_Wire from the original Part::Feature. + Draft.Wire(new_obj) # Attach Python proxy. It will find Shape, Placement. # Check if all segments of the wire are straight lines. # If so, we can safely populate the .Points property to make it parametric. @@ -4626,27 +4728,33 @@ class DxfDraftPostProcessor: for edge in shape.Edges: if edge.Curve.TypeId == "Part::GeomLine": - continue # This is a straight segment + continue # This is a straight segment else: is_all_lines = False - break # Found a curve, no need to check further + break # Found a curve, no need to check further if is_all_lines and shape.OrderedVertexes: # All segments are straight, so we can make it an editable wire points = [v.Point for v in shape.OrderedVertexes] new_obj.Points = points - new_obj.Closed = shape.isClosed() # Transfer specific properties expected by Draft.Wire. + new_obj.Closed = ( + shape.isClosed() + ) # Transfer specific properties expected by Draft.Wire. obj_type_str = "Wire" # Fallback for other Part::Feature shapes (e.g., 3DFACE, SOLID, or unsupported Edge types). - else: # If the TopoDS_Shape is not a recognized primitive (e.g., Compound, Face, Solid). + else: # If the TopoDS_Shape is not a recognized primitive (e.g., Compound, Face, Solid). # Wrap it in a Part::FeaturePython to allow Python property customization if needed. - new_obj = self.doc.addObject("Part::FeaturePython", self.doc.getUniqueObjectName("Shape")) - new_obj.addExtension("Part::AttachExtensionPython") # Add extension for Placement for App::FeaturePython. - new_obj.Shape = shape # Assign the TopoDS_Shape from the original Part::Feature. + new_obj = self.doc.addObject( + "Part::FeaturePython", self.doc.getUniqueObjectName("Shape") + ) + new_obj.addExtension( + "Part::AttachExtensionPython" + ) # Add extension for Placement for App::FeaturePython. + new_obj.Shape = shape # Assign the TopoDS_Shape from the original Part::Feature. # Explicitly set Placement for App::FeaturePython. - if hasattr(part_obj, 'Placement'): + if hasattr(part_obj, "Placement"): new_obj.Placement = part_obj.Placement else: new_obj.Placement = FreeCAD.Placement() @@ -4654,21 +4762,23 @@ class DxfDraftPostProcessor: obj_type_str = "Shape" # --- Handle App::Link objects (block instances from C++ importer) --- - elif part_obj.isDerivedFrom("App::Link"): # Input `part_obj` is an App::Link. + elif part_obj.isDerivedFrom("App::Link"): # Input `part_obj` is an App::Link. # App::Link objects are already suitable as a base for Draft.Clone/Array links. # They natively have Placement and Link properties, and support .Proxy. - new_obj = part_obj # Reuse the object directly. + new_obj = part_obj # Reuse the object directly. obj_type_str = "Link" # --- Handle App::FeaturePython placeholder objects (Text, Dimension from C++ importer) --- - elif part_obj.isDerivedFrom("App::FeaturePython"): # Input `part_obj` is an App::FeaturePython placeholder. + elif part_obj.isDerivedFrom( + "App::FeaturePython" + ): # Input `part_obj` is an App::FeaturePython placeholder. # These are specific placeholders the C++ importer created (`DxfEntityType` property). # They are processed later in `_create_from_placeholders` to become proper Draft.Text/Dimension objects. - return None, None # Don't process them here; let the dedicated function handle them. + return None, None # Don't process them here; let the dedicated function handle them. # --- Final Common Steps for Newly Created Draft Objects --- if new_obj: - new_obj.Label = part_obj.Label # Always transfer label. + new_obj.Label = part_obj.Label # Always transfer label. # If `new_obj` was freshly created (not `part_obj` reused), and `part_obj` had a Placement, # ensure `new_obj`'s Placement is correctly set from `part_obj`. @@ -4679,7 +4789,9 @@ class DxfDraftPostProcessor: new_obj.Placement = part_obj.Placement elif not hasattr(new_obj, "Placement"): # This should ideally not happen with the corrected logic above. - FCC.PrintWarning(f"Created object '{new_obj.Label}' of type '{obj_type_str}' does not have a 'Placement' property even after intended setup. This is unexpected.\n") + FCC.PrintWarning( + f"Created object '{new_obj.Label}' of type '{obj_type_str}' does not have a 'Placement' property even after intended setup. This is unexpected.\n" + ) # Add the original object (from C++ importer) to the list for deletion. if new_obj is not part_obj: @@ -4690,7 +4802,9 @@ class DxfDraftPostProcessor: # If no conversion could be made (e.g., unsupported DXF entity not falling into a handled case), # mark original for deletion and return None. self.all_originals_to_delete.add(part_obj) - FCC.PrintWarning(f"DXF Post-Processor: Failed to convert object '{part_obj.Label}'. Discarding.\n") + FCC.PrintWarning( + f"DXF Post-Processor: Failed to convert object '{part_obj.Label}'. Discarding.\n" + ) return None, None def _parent_object_to_layer(self, new_obj, original_obj): @@ -4703,14 +4817,16 @@ class DxfDraftPostProcessor: layer_obj = None if found_layers: for l_obj in found_layers: - if Draft.get_type(l_obj) == 'Layer': + if Draft.get_type(l_obj) == "Layer": layer_obj = l_obj break if layer_obj: layer_obj.Proxy.addObject(layer_obj, new_obj) else: - FCC.PrintWarning(f"DXF Post-Processor: Could not find a valid Draft Layer with label '{layer_name}' for object '{new_obj.Label}'.\n") + FCC.PrintWarning( + f"DXF Post-Processor: Could not find a valid Draft Layer with label '{layer_name}' for object '{new_obj.Label}'.\n" + ) def _create_and_parent_geometry(self, intermediate_obj): """High-level helper to convert, name, and parent a single geometric object.""" @@ -4723,7 +4839,9 @@ class DxfDraftPostProcessor: self._parent_object_to_layer(new_draft_obj, intermediate_obj) self.newly_created_draft_objects.append(new_draft_obj) else: - FCC.PrintWarning(f"DXF Post-Processor: Failed to convert object '{intermediate_obj.Label}'. Discarding.\n") + FCC.PrintWarning( + f"DXF Post-Processor: Failed to convert object '{intermediate_obj.Label}'. Discarding.\n" + ) return new_draft_obj def _create_from_placeholders(self, placeholders): @@ -4774,7 +4892,7 @@ class DxfDraftPostProcessor: # A type of 0 indicates that the dimension is projected. The # projection direction is given by its rotation angle. if dim_type == 0 and hasattr(placeholder, "DxfRotation"): - angle = placeholder.DxfRotation.Value # Angle is in radians + angle = placeholder.DxfRotation.Value # Angle is in radians # The Direction property on a Draft.Dimension controls its # projection. Setting it here ensures the ViewProvider @@ -4795,7 +4913,9 @@ class DxfDraftPostProcessor: self._parent_object_to_layer(new_obj, placeholder) self.newly_created_draft_objects.append(new_obj) except Exception as e: - FCC.PrintWarning(f"Could not create Draft object from placeholder '{placeholder.Label}': {e}\n") + FCC.PrintWarning( + f"Could not create Draft object from placeholder '{placeholder.Label}': {e}\n" + ) self.all_originals_to_delete.update(placeholders) @@ -4813,9 +4933,11 @@ class DxfDraftPostProcessor: try: proxy_name = obj.Proxy.__class__.__name__ if proxy_name in ("Wire", "Line"): - if ViewProviderWire: ViewProviderWire(obj.ViewObject) + if ViewProviderWire: + ViewProviderWire(obj.ViewObject) elif proxy_name == "Circle": - if ViewProviderDraft: ViewProviderDraft(obj.ViewObject) + if ViewProviderDraft: + ViewProviderDraft(obj.ViewObject) elif proxy_name == "Text": if hasattr(obj, "DxfTextHeight"): obj.ViewObject.FontSize = obj.DxfTextHeight * TEXTSCALING @@ -4829,10 +4951,14 @@ class DxfDraftPostProcessor: for obj in self.all_originals_to_delete: if obj.isValid() and self.doc.getObject(obj.Name) is not None: try: - if not obj.isDerivedFrom("App::DocumentObjectGroup") and not obj.isDerivedFrom("App::Link"): + if not obj.isDerivedFrom("App::DocumentObjectGroup") and not obj.isDerivedFrom( + "App::Link" + ): self.doc.removeObject(obj.Name) except Exception as e: - FCC.PrintWarning(f"Failed to delete object '{getattr(obj, 'Label', obj.Name)}': {e}\n") + FCC.PrintWarning( + f"Failed to delete object '{getattr(obj, 'Label', obj.Name)}': {e}\n" + ) def _cleanup_organizational_groups(self): """Removes empty organizational groups after processing.""" @@ -4909,9 +5035,13 @@ class DxfDraftPostProcessor: # Process geometry inside block definitions for block_def_obj, original_children in block_defs.items(): - new_draft_children = [self._create_and_parent_geometry(child) for child in original_children] + new_draft_children = [ + self._create_and_parent_geometry(child) for child in original_children + ] block_def_obj.Links = [obj for obj in new_draft_children if obj] - self.all_originals_to_delete.update(set(original_children) - set(new_draft_children)) + self.all_originals_to_delete.update( + set(original_children) - set(new_draft_children) + ) # Process top-level geometry converted_top_geo = [] @@ -4931,6 +5061,7 @@ class DxfDraftPostProcessor: self.doc.abortTransaction() FCC.PrintError(f"Aborting DXF post-processing due to an error: {e}\n") import traceback + traceback.print_exc() return finally: diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 810cd25d8e..ce8578be25 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -2,7 +2,7 @@ ## @package importOCA # \ingroup DRAFT # \brief OCA (Open CAD Format) file importer & exporter -'''@package importOCA +"""@package importOCA OCA (Open CAD Format) file importer & exporter This module provides support for importing from and exporting to @@ -11,7 +11,7 @@ See: https://groups.google.com/forum/#!forum/open_cad_format As of 2019 this file format is practically obsolete, and this module is not maintained. -''' +""" # Check code with # flake8 --ignore=E226,E266,E401,W503 @@ -49,12 +49,11 @@ from draftutils.utils import pyopen if FreeCAD.GuiUp: from draftutils.translate import translate else: + def translate(context, txt): return txt - - def getpoint(data): """Turn an OCA point definition into a FreeCAD.Vector. @@ -82,8 +81,7 @@ def getpoint(data): elif data[1][0] == "C": # Error: DraftGeomUtils.findProjection() # doesn't exist - return DraftGeomUtils.findProjection(objects[data[0]], - objects[data[1]]) + return DraftGeomUtils.findProjection(objects[data[0]], objects[data[1]]) elif data[0][0] == "C": if objects[data[0]]: p1 = objects[data[0]].Curve.Position @@ -141,7 +139,7 @@ def getarc(data): verts = [] for p in range(len(pts)): if pts[p] == "P": - verts.append(getpoint(pts[p:p+3])) + verts.append(getpoint(pts[p : p + 3])) elif pts[p][0] == "P": verts.append(getpoint([pts[p]])) if verts[0] and verts[1] and verts[2]: @@ -153,11 +151,11 @@ def getarc(data): lines = [] for p in range(len(data)): if data[p] == "P": - verts.append(getpoint(data[p:p+4])) + verts.append(getpoint(data[p : p + 4])) elif data[p][0] == "P": verts.append(getpoint([data[p]])) elif data[p] == "VAL": - rad = float(data[p+1]) + rad = float(data[p + 1]) elif data[p][0] == "L": lines.append(objects[data[p]]) c = Part.Circle() @@ -174,12 +172,10 @@ def getarc(data): rad = None for p in range(len(data)): if data[p] == "VAL": - rad = float(data[p+1]) + rad = float(data[p + 1]) elif data[p][0] == "L": lines.append(objects[data[p]]) - circles = DraftGeomUtils.circleFrom2LinesRadius(lines[0], - lines[1], - rad) + circles = DraftGeomUtils.circleFrom2LinesRadius(lines[0], lines[1], rad) if circles: c = circles[0] if c: @@ -203,7 +199,7 @@ def getline(data): verts = [] for p in range(len(data)): if data[p] == "P": - verts.append(getpoint(data[p:p+4])) + verts.append(getpoint(data[p : p + 4])) elif data[p][0] == "P": verts.append(getpoint([data[p]])) L = Part.LineSegment(verts[0], verts[1]) @@ -246,7 +242,7 @@ def writepoint(vector): str A string "P(X Y Z)" with the information from `vector`. """ - return "P("+str(vector.x)+" "+str(vector.y)+" "+str(vector.z)+")" + return "P(" + str(vector.x) + " " + str(vector.y) + " " + str(vector.z) + ")" def createobject(oid, doc): @@ -303,7 +299,7 @@ def parse(filename, doc): if _id[0] == "P": # point objects[_id] = getpoint(data) - elif ((_id[0] == "A") and params.get_param("ocaareas")): + elif (_id[0] == "A") and params.get_param("ocaareas"): # area objects[_id] = getarea(data) createobject(_id, doc) @@ -325,9 +321,7 @@ def parse(filename, doc): elif readline[0:6] == "DEFCOL": # color c = readline.split() - color = (float(c[1])/255, - float(c[2])/255, - float(c[3])/255) + color = (float(c[1]) / 255, float(c[2]) / 255, float(c[3]) / 255) def open(filename): @@ -408,33 +402,31 @@ def export(exportList, filename): for e in ob.Shape.Edges: edges.append(e) if not (edges or faces): - FCC.PrintMessage(translate("importOCA", - "OCA: found no data to export") - + "\n") + FCC.PrintMessage(translate("importOCA", "OCA: found no data to export") + "\n") return # writing file - oca = pyopen(filename, 'w') + oca = pyopen(filename, "w") oca.write("#oca file generated from FreeCAD\r\n") oca.write("# edges\r\n") count = 1 for e in edges: if DraftGeomUtils.geomType(e) == "Line": - oca.write("L"+str(count)+"=") + oca.write("L" + str(count) + "=") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) oca.write("\r\n") elif DraftGeomUtils.geomType(e) == "Circle": if len(e.Vertexes) > 1: - oca.write("C"+str(count)+"=ARC ") + oca.write("C" + str(count) + "=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: - oca.write("C"+str(count)+"= ") + oca.write("C" + str(count) + "= ") oca.write(writepoint(e.Curve.Center)) oca.write(" ") oca.write(str(e.Curve.Radius)) @@ -442,7 +434,7 @@ def export(exportList, filename): count += 1 oca.write("# faces\r\n") for f in faces: - oca.write("A"+str(count)+"=S(POL") + oca.write("A" + str(count) + "=S(POL") for v in f.Vertexes: oca.write(" ") oca.write(writepoint(v.Point)) @@ -453,6 +445,4 @@ def export(exportList, filename): # closing oca.close() - FCC.PrintMessage(translate("importOCA", - "successfully exported") - + " " + filename + "\n") + FCC.PrintMessage(translate("importOCA", "successfully exported") + " " + filename + "\n") diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index f8a1ac2904..247d71b8cd 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -71,6 +71,7 @@ from copy import deepcopy if FreeCAD.GuiUp: from PySide import QtWidgets import FreeCADGui + gui = True try: draftui = FreeCADGui.draftToolBar @@ -82,157 +83,156 @@ else: svgcolors = { - 'Pink': (255, 192, 203), - 'Blue': (0, 0, 255), - 'Honeydew': (240, 255, 240), - 'Purple': (128, 0, 128), - 'Fuchsia': (255, 0, 255), - 'LawnGreen': (124, 252, 0), - 'Amethyst': (153, 102, 204), - 'Crimson': (220, 20, 60), - 'White': (255, 255, 255), - 'NavajoWhite': (255, 222, 173), - 'Cornsilk': (255, 248, 220), - 'Bisque': (255, 228, 196), - 'PaleGreen': (152, 251, 152), - 'Brown': (165, 42, 42), - 'DarkTurquoise': (0, 206, 209), - 'DarkGreen': (0, 100, 0), - 'MediumOrchid': (186, 85, 211), - 'Chocolate': (210, 105, 30), - 'PapayaWhip': (255, 239, 213), - 'Olive': (128, 128, 0), - 'Silver': (192, 192, 192), - 'PeachPuff': (255, 218, 185), - 'Plum': (221, 160, 221), - 'DarkGoldenrod': (184, 134, 11), - 'SlateGrey': (112, 128, 144), - 'MintCream': (245, 255, 250), - 'CornflowerBlue': (100, 149, 237), - 'Gold': (255, 215, 0), - 'HotPink': (255, 105, 180), - 'DarkBlue': (0, 0, 139), - 'LimeGreen': (50, 205, 50), - 'DeepSkyBlue': (0, 191, 255), - 'DarkKhaki': (189, 183, 107), - 'LightGrey': (211, 211, 211), - 'Yellow': (255, 255, 0), - 'Gainsboro': (220, 220, 220), - 'MistyRose': (255, 228, 225), - 'SandyBrown': (244, 164, 96), - 'DeepPink': (255, 20, 147), - 'Magenta': (255, 0, 255), - 'AliceBlue': (240, 248, 255), - 'DarkCyan': (0, 139, 139), - 'DarkSlateGrey': (47, 79, 79), - 'GreenYellow': (173, 255, 47), - 'DarkOrchid': (153, 50, 204), - 'OliveDrab': (107, 142, 35), - 'Chartreuse': (127, 255, 0), - 'Peru': (205, 133, 63), - 'Orange': (255, 165, 0), - 'Red': (255, 0, 0), - 'Wheat': (245, 222, 179), - 'LightCyan': (224, 255, 255), - 'LightSeaGreen': (32, 178, 170), - 'BlueViolet': (138, 43, 226), - 'LightSlateGrey': (119, 136, 153), - 'Cyan': (0, 255, 255), - 'MediumPurple': (147, 112, 219), - 'MidnightBlue': (25, 25, 112), - 'FireBrick': (178, 34, 34), - 'PaleTurquoise': (175, 238, 238), - 'PaleGoldenrod': (238, 232, 170), - 'Gray': (128, 128, 128), - 'MediumSeaGreen': (60, 179, 113), - 'Moccasin': (255, 228, 181), - 'Ivory': (255, 255, 240), - 'DarkSlateBlue': (72, 61, 139), - 'Beige': (245, 245, 220), - 'Green': (0, 128, 0), - 'SlateBlue': (106, 90, 205), - 'Teal': (0, 128, 128), - 'Azure': (240, 255, 255), - 'LightSteelBlue': (176, 196, 222), - 'DimGrey': (105, 105, 105), - 'Tan': (210, 180, 140), - 'AntiqueWhite': (250, 235, 215), - 'SkyBlue': (135, 206, 235), - 'GhostWhite': (248, 248, 255), - 'MediumTurquoise': (72, 209, 204), - 'FloralWhite': (255, 250, 240), - 'LavenderBlush': (255, 240, 245), - 'SeaGreen': (46, 139, 87), - 'Lavender': (230, 230, 250), - 'BlanchedAlmond': (255, 235, 205), - 'DarkOliveGreen': (85, 107, 47), - 'DarkSeaGreen': (143, 188, 143), - 'SpringGreen': (0, 255, 127), - 'Navy': (0, 0, 128), - 'Orchid': (218, 112, 214), - 'SaddleBrown': (139, 69, 19), - 'IndianRed': (205, 92, 92), - 'Snow': (255, 250, 250), - 'SteelBlue': (70, 130, 180), - 'MediumSlateBlue': (123, 104, 238), - 'Black': (0, 0, 0), - 'LightBlue': (173, 216, 230), - 'Turquoise': (64, 224, 208), - 'MediumVioletRed': (199, 21, 133), - 'DarkViolet': (148, 0, 211), - 'DarkGray': (169, 169, 169), - 'Salmon': (250, 128, 114), - 'DarkMagenta': (139, 0, 139), - 'Tomato': (255, 99, 71), - 'WhiteSmoke': (245, 245, 245), - 'Goldenrod': (218, 165, 32), - 'MediumSpringGreen': (0, 250, 154), - 'DodgerBlue': (30, 144, 255), - 'Aqua': (0, 255, 255), - 'ForestGreen': (34, 139, 34), - 'LemonChiffon': (255, 250, 205), - 'LightSlateGray': (119, 136, 153), - 'SlateGray': (112, 128, 144), - 'LightGray': (211, 211, 211), - 'Indigo': (75, 0, 130), - 'CadetBlue': (95, 158, 160), - 'LightYellow': (255, 255, 224), - 'DarkOrange': (255, 140, 0), - 'PowderBlue': (176, 224, 230), - 'RoyalBlue': (65, 105, 225), - 'Sienna': (160, 82, 45), - 'Thistle': (216, 191, 216), - 'Lime': (0, 255, 0), - 'Seashell': (255, 245, 238), - 'DarkRed': (139, 0, 0), - 'LightSkyBlue': (135, 206, 250), - 'YellowGreen': (154, 205, 50), - 'Aquamarine': (127, 255, 212), - 'LightCoral': (240, 128, 128), - 'DarkSlateGray': (47, 79, 79), - 'Khaki': (240, 230, 140), - 'DarkGrey': (169, 169, 169), - 'BurlyWood': (222, 184, 135), - 'LightGoldenrodYellow': (250, 250, 210), - 'MediumBlue': (0, 0, 205), - 'DarkSalmon': (233, 150, 122), - 'RosyBrown': (188, 143, 143), - 'LightSalmon': (255, 160, 122), - 'PaleVioletRed': (219, 112, 147), - 'Coral': (255, 127, 80), - 'Violet': (238, 130, 238), - 'Grey': (128, 128, 128), - 'LightGreen': (144, 238, 144), - 'Linen': (250, 240, 230), - 'OrangeRed': (255, 69, 0), - 'DimGray': (105, 105, 105), - 'Maroon': (128, 0, 0), - 'LightPink': (255, 182, 193), - 'MediumAquamarine': (102, 205, 170), - 'OldLace': (253, 245, 230) + "Pink": (255, 192, 203), + "Blue": (0, 0, 255), + "Honeydew": (240, 255, 240), + "Purple": (128, 0, 128), + "Fuchsia": (255, 0, 255), + "LawnGreen": (124, 252, 0), + "Amethyst": (153, 102, 204), + "Crimson": (220, 20, 60), + "White": (255, 255, 255), + "NavajoWhite": (255, 222, 173), + "Cornsilk": (255, 248, 220), + "Bisque": (255, 228, 196), + "PaleGreen": (152, 251, 152), + "Brown": (165, 42, 42), + "DarkTurquoise": (0, 206, 209), + "DarkGreen": (0, 100, 0), + "MediumOrchid": (186, 85, 211), + "Chocolate": (210, 105, 30), + "PapayaWhip": (255, 239, 213), + "Olive": (128, 128, 0), + "Silver": (192, 192, 192), + "PeachPuff": (255, 218, 185), + "Plum": (221, 160, 221), + "DarkGoldenrod": (184, 134, 11), + "SlateGrey": (112, 128, 144), + "MintCream": (245, 255, 250), + "CornflowerBlue": (100, 149, 237), + "Gold": (255, 215, 0), + "HotPink": (255, 105, 180), + "DarkBlue": (0, 0, 139), + "LimeGreen": (50, 205, 50), + "DeepSkyBlue": (0, 191, 255), + "DarkKhaki": (189, 183, 107), + "LightGrey": (211, 211, 211), + "Yellow": (255, 255, 0), + "Gainsboro": (220, 220, 220), + "MistyRose": (255, 228, 225), + "SandyBrown": (244, 164, 96), + "DeepPink": (255, 20, 147), + "Magenta": (255, 0, 255), + "AliceBlue": (240, 248, 255), + "DarkCyan": (0, 139, 139), + "DarkSlateGrey": (47, 79, 79), + "GreenYellow": (173, 255, 47), + "DarkOrchid": (153, 50, 204), + "OliveDrab": (107, 142, 35), + "Chartreuse": (127, 255, 0), + "Peru": (205, 133, 63), + "Orange": (255, 165, 0), + "Red": (255, 0, 0), + "Wheat": (245, 222, 179), + "LightCyan": (224, 255, 255), + "LightSeaGreen": (32, 178, 170), + "BlueViolet": (138, 43, 226), + "LightSlateGrey": (119, 136, 153), + "Cyan": (0, 255, 255), + "MediumPurple": (147, 112, 219), + "MidnightBlue": (25, 25, 112), + "FireBrick": (178, 34, 34), + "PaleTurquoise": (175, 238, 238), + "PaleGoldenrod": (238, 232, 170), + "Gray": (128, 128, 128), + "MediumSeaGreen": (60, 179, 113), + "Moccasin": (255, 228, 181), + "Ivory": (255, 255, 240), + "DarkSlateBlue": (72, 61, 139), + "Beige": (245, 245, 220), + "Green": (0, 128, 0), + "SlateBlue": (106, 90, 205), + "Teal": (0, 128, 128), + "Azure": (240, 255, 255), + "LightSteelBlue": (176, 196, 222), + "DimGrey": (105, 105, 105), + "Tan": (210, 180, 140), + "AntiqueWhite": (250, 235, 215), + "SkyBlue": (135, 206, 235), + "GhostWhite": (248, 248, 255), + "MediumTurquoise": (72, 209, 204), + "FloralWhite": (255, 250, 240), + "LavenderBlush": (255, 240, 245), + "SeaGreen": (46, 139, 87), + "Lavender": (230, 230, 250), + "BlanchedAlmond": (255, 235, 205), + "DarkOliveGreen": (85, 107, 47), + "DarkSeaGreen": (143, 188, 143), + "SpringGreen": (0, 255, 127), + "Navy": (0, 0, 128), + "Orchid": (218, 112, 214), + "SaddleBrown": (139, 69, 19), + "IndianRed": (205, 92, 92), + "Snow": (255, 250, 250), + "SteelBlue": (70, 130, 180), + "MediumSlateBlue": (123, 104, 238), + "Black": (0, 0, 0), + "LightBlue": (173, 216, 230), + "Turquoise": (64, 224, 208), + "MediumVioletRed": (199, 21, 133), + "DarkViolet": (148, 0, 211), + "DarkGray": (169, 169, 169), + "Salmon": (250, 128, 114), + "DarkMagenta": (139, 0, 139), + "Tomato": (255, 99, 71), + "WhiteSmoke": (245, 245, 245), + "Goldenrod": (218, 165, 32), + "MediumSpringGreen": (0, 250, 154), + "DodgerBlue": (30, 144, 255), + "Aqua": (0, 255, 255), + "ForestGreen": (34, 139, 34), + "LemonChiffon": (255, 250, 205), + "LightSlateGray": (119, 136, 153), + "SlateGray": (112, 128, 144), + "LightGray": (211, 211, 211), + "Indigo": (75, 0, 130), + "CadetBlue": (95, 158, 160), + "LightYellow": (255, 255, 224), + "DarkOrange": (255, 140, 0), + "PowderBlue": (176, 224, 230), + "RoyalBlue": (65, 105, 225), + "Sienna": (160, 82, 45), + "Thistle": (216, 191, 216), + "Lime": (0, 255, 0), + "Seashell": (255, 245, 238), + "DarkRed": (139, 0, 0), + "LightSkyBlue": (135, 206, 250), + "YellowGreen": (154, 205, 50), + "Aquamarine": (127, 255, 212), + "LightCoral": (240, 128, 128), + "DarkSlateGray": (47, 79, 79), + "Khaki": (240, 230, 140), + "DarkGrey": (169, 169, 169), + "BurlyWood": (222, 184, 135), + "LightGoldenrodYellow": (250, 250, 210), + "MediumBlue": (0, 0, 205), + "DarkSalmon": (233, 150, 122), + "RosyBrown": (188, 143, 143), + "LightSalmon": (255, 160, 122), + "PaleVioletRed": (219, 112, 147), + "Coral": (255, 127, 80), + "Violet": (238, 130, 238), + "Grey": (128, 128, 128), + "LightGreen": (144, 238, 144), + "Linen": (250, 240, 230), + "OrangeRed": (255, 69, 0), + "DimGray": (105, 105, 105), + "Maroon": (128, 0, 0), + "LightPink": (255, 182, 193), + "MediumAquamarine": (102, 205, 170), + "OldLace": (253, 245, 230), } -svgcolorslower = \ - dict((key.lower(), value) for (key, value) in list(svgcolors.items())) +svgcolorslower = dict((key.lower(), value) for (key, value) in list(svgcolors.items())) def getcolor(color): @@ -253,7 +253,7 @@ def getcolor(color): FreeCAD.Console.PrintMessage("Color defined as 'none', defaulting to black\n") return (0.0, 0.0, 0.0, 0.0) if color[0] == "#": - if len(color) == 7 or len(color) == 9: # Color string '#RRGGBB' or '#RRGGBBAA' + if len(color) == 7 or len(color) == 9: # Color string '#RRGGBB' or '#RRGGBBAA' r = float(int(color[1:3], 16) / 255.0) g = float(int(color[3:5], 16) / 255.0) b = float(int(color[5:7], 16) / 255.0) @@ -261,27 +261,29 @@ def getcolor(color): if len(color) == 9: a = float(int(color[7:9], 16) / 255.0) FreeCAD.Console.PrintMessage(f"Non standard color format #RRGGBBAA : {color}\n") - return (r, g, b, 1-a) - if len(color) == 4: # Color string '#RGB' + return (r, g, b, 1 - a) + if len(color) == 4: # Color string '#RGB' # Expand the hex digits r = float(int(color[1], 16) * 17 / 255.0) g = float(int(color[2], 16) * 17 / 255.0) b = float(int(color[3], 16) * 17 / 255.0) return (r, g, b, 0.0) - if color.lower().startswith('rgb(') or color.lower().startswith('rgba('): # Color string 'rgb[a](0.12,0.23,0.3,0.0)' - cvalues = color.lstrip('rgba(').rstrip(')').replace('%', '').split(',') + if color.lower().startswith("rgb(") or color.lower().startswith( + "rgba(" + ): # Color string 'rgb[a](0.12,0.23,0.3,0.0)' + cvalues = color.lstrip("rgba(").rstrip(")").replace("%", "").split(",") if len(cvalues) == 3: a = 1.0 - if '%' in color: + if "%" in color: r, g, b = [int(float(cv)) / 100.0 for cv in cvalues] else: r, g, b = [int(float(cv)) / 255.0 for cv in cvalues] if len(cvalues) == 4: - if '%' in color: + if "%" in color: r, g, b, a = [int(float(cv)) / 100.0 for cv in cvalues] else: r, g, b, a = [int(float(cv)) / 255.0 for cv in cvalues] - return (r, g, b, 1-a) + return (r, g, b, 1 - a) # Trying named color like 'MediumAquamarine' v = svgcolorslower.get(color.lower()) if v: @@ -322,7 +324,7 @@ def transformCopyShape(shape, m): return shape.transformGeometry(m) -def getsize(length, mode='discard', base=1): +def getsize(length, mode="discard", base=1): """Parse the length string containing number and unit. Parameters @@ -358,74 +360,74 @@ def getsize(length, mode='discard', base=1): # # The percentage factor is arbitrarily chosen, as it should depend # on the viewport size or for filling patterns on the bounding box. - if mode == 'mm90.0': + if mode == "mm90.0": tomm = { - '': 25.4/90, # default - 'px': 25.4/90, - 'pt': 4.0/3 * 25.4/90, - 'pc': 15 * 25.4/90, - 'mm': 1.0, - 'cm': 10.0, - 'in': 25.4, - 'em': 15 * 2.54/90, - 'ex': 10 * 2.54/90, - '%': 100 + "": 25.4 / 90, # default + "px": 25.4 / 90, + "pt": 4.0 / 3 * 25.4 / 90, + "pc": 15 * 25.4 / 90, + "mm": 1.0, + "cm": 10.0, + "in": 25.4, + "em": 15 * 2.54 / 90, + "ex": 10 * 2.54 / 90, + "%": 100, } - elif mode == 'mm96.0': + elif mode == "mm96.0": tomm = { - '': 25.4/96, # default - 'px': 25.4/96, - 'pt': 4.0/3 * 25.4/96, - 'pc': 15 * 25.4/96, - 'mm': 1.0, - 'cm': 10.0, - 'in': 25.4, - 'em': 15 * 2.54/96, - 'ex': 10 * 2.54/96, - '%': 100 + "": 25.4 / 96, # default + "px": 25.4 / 96, + "pt": 4.0 / 3 * 25.4 / 96, + "pc": 15 * 25.4 / 96, + "mm": 1.0, + "cm": 10.0, + "in": 25.4, + "em": 15 * 2.54 / 96, + "ex": 10 * 2.54 / 96, + "%": 100, } - elif mode == 'css90.0': + elif mode == "css90.0": topx = { - '': 1.0, # default - 'px': 1.0, - 'pt': 4.0/3, - 'pc': 15, - 'mm': 90.0/25.4, - 'cm': 90.0/254.0, - 'in': 90, - 'em': 15, - 'ex': 10, - '%': 100 + "": 1.0, # default + "px": 1.0, + "pt": 4.0 / 3, + "pc": 15, + "mm": 90.0 / 25.4, + "cm": 90.0 / 254.0, + "in": 90, + "em": 15, + "ex": 10, + "%": 100, } - elif mode == 'css96.0': + elif mode == "css96.0": topx = { - '': 1.0, # default - 'px': 1.0, - 'pt': 4.0/3, - 'pc': 15, - 'mm': 96.0/25.4, - 'cm': 96.0/254.0, - 'in': 96, - 'em': 15, - 'ex': 10, - '%': 100 + "": 1.0, # default + "px": 1.0, + "pt": 4.0 / 3, + "pc": 15, + "mm": 96.0 / 25.4, + "cm": 96.0 / 254.0, + "in": 96, + "em": 15, + "ex": 10, + "%": 100, } # Extract a number from a string like '+56215.14565E+6mm' - _num = '([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)' - _unit = '(px|pt|pc|mm|cm|in|em|ex|%)?' + _num = "([-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)" + _unit = "(px|pt|pc|mm|cm|in|em|ex|%)?" _full_num = _num + _unit number, exponent, unit = re.findall(_full_num, length)[0] - if mode == 'discard': + if mode == "discard": return float(number) - elif mode == 'tuple': + elif mode == "tuple": return float(number), unit - elif mode == 'isabsolute': - return unit in ('mm', 'cm', 'in', 'px', 'pt') - elif mode == 'mm96.0' or mode == 'mm90.0': + elif mode == "isabsolute": + return unit in ("mm", "cm", "in", "px", "pt") + elif mode == "mm96.0" or mode == "mm90.0": return float(number) * tomm[unit] - elif mode == 'css96.0' or mode == 'css90.0': - if unit != '%': + elif mode == "css96.0" or mode == "css90.0": + if unit != "%": return float(number) * topx[unit] else: return float(number) * base @@ -450,8 +452,6 @@ def getrgb(color): return "#" + r + g + b - - class svgHandler(xml.sax.ContentHandler): """Parse SVG files and create FreeCAD objects.""" @@ -498,7 +498,6 @@ class svgHandler(xml.sax.ContentHandler): if self.fill: v.ShapeColor = self.fill - def __addFaceToDoc(self, named_face): """Create a named document object from a name/face tuple @@ -530,15 +529,15 @@ class svgHandler(xml.sax.ContentHandler): self.count += 1 precision = svg_precision() - _msg('processing element {0}: {1}'.format(self.count, name)) - _msg('existing group transform: {}'.format(self.grouptransform)) - _msg('existing group style: {}'.format(self.groupstyles)) + _msg("processing element {0}: {1}".format(self.count, name)) + _msg("existing group transform: {}".format(self.grouptransform)) + _msg("existing group style: {}".format(self.groupstyles)) data = {} - for (keyword, content) in list(attrs.items()): + for keyword, content in list(attrs.items()): # print(keyword, content) if keyword != "style": - content = content.replace(',', ' ') + content = content.replace(",", " ") content = content.split() # print(keyword, content) data[keyword] = content @@ -546,10 +545,10 @@ class svgHandler(xml.sax.ContentHandler): # If it's the first element, which is , # check if the file is created by Inkscape, and its version, # in order to consider some attributes of the SVG file. - if self.count == 1 and name == 'svg': - if 'inkscape:version' in data: - inks_doc_name = attrs.getValue('sodipodi:docname') - inks_full_ver = attrs.getValue('inkscape:version') + if self.count == 1 and name == "svg": + if "inkscape:version" in data: + inks_doc_name = attrs.getValue("sodipodi:docname") + inks_full_ver = attrs.getValue("inkscape:version") inks_ver_pars = re.search("\\d+\\.\\d+", inks_full_ver) if inks_ver_pars is not None: inks_ver_f = float(inks_ver_pars.group(0)) @@ -561,27 +560,32 @@ class svgHandler(xml.sax.ContentHandler): self.svgdpi = 90.0 else: self.svgdpi = 96.0 - if 'inkscape:version' not in data: + if "inkscape:version" not in data: # exact scaling is calculated later below. Here we just want # to skip the DPI dialog if a unit is specified in the viewbox - if "width" in data and "mm" in attrs.getValue('width'): + if "width" in data and "mm" in attrs.getValue("width"): self.svgdpi = 96.0 - elif "width" in data and "in" in attrs.getValue('width'): + elif "width" in data and "in" in attrs.getValue("width"): self.svgdpi = 96.0 - elif "width" in data and "cm" in attrs.getValue('width'): + elif "width" in data and "cm" in attrs.getValue("width"): self.svgdpi = 96.0 else: - _inf = ("This SVG file does not appear to have been produced " - "by Inkscape. If it does not contain absolute units " - "then a DPI setting will be used.") - _qst = ("Do you wish to use 96 dpi? Choosing 'No' " - "will use the older standard 90 dpi.") + _inf = ( + "This SVG file does not appear to have been produced " + "by Inkscape. If it does not contain absolute units " + "then a DPI setting will be used." + ) + _qst = ( + "Do you wish to use 96 dpi? Choosing 'No' " + "will use the older standard 90 dpi." + ) if FreeCAD.GuiUp: msgBox = QtWidgets.QMessageBox() msgBox.setText(translate("ImportSVG", _inf)) msgBox.setInformativeText(translate("ImportSVG", _qst)) - msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes - | QtWidgets.QMessageBox.No) + msgBox.setStandardButtons( + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No + ) msgBox.setDefaultButton(QtWidgets.QMessageBox.No) ret = msgBox.exec_() if ret == QtWidgets.QMessageBox.Yes: @@ -591,37 +595,37 @@ class svgHandler(xml.sax.ContentHandler): if ret: _msg(translate("ImportSVG", _inf)) _msg(translate("ImportSVG", _qst)) - _msg("*** User specified {} " - "dpi ***".format(self.svgdpi)) + _msg("*** User specified {} " "dpi ***".format(self.svgdpi)) else: self.svgdpi = 96.0 _msg(_inf) _msg("*** Assuming {} dpi ***".format(self.svgdpi)) if self.svgdpi == 1.0: - _wrn("This SVG file (" + inks_doc_name + ") " - "has an unrecognised format which means " - "the dpi could not be determined; " - "assuming 96 dpi") + _wrn( + "This SVG file (" + inks_doc_name + ") " + "has an unrecognised format which means " + "the dpi could not be determined; " + "assuming 96 dpi" + ) self.svgdpi = 96.0 - if 'style' in data: - if not data['style']: + if "style" in data: + if not data["style"]: # Empty style attribute stops inheriting from parent pass else: - content = data['style'].replace(' ', '') - content = content.split(';') + content = data["style"].replace(" ", "") + content = content.split(";") for i in content: - pair = i.split(':') + pair = i.split(":") if len(pair) > 1: data[pair[0]] = pair[1] - for k in ['x', 'y', 'x1', 'y1', 'x2', 'y2', - 'r', 'rx', 'ry', 'cx', 'cy', 'width', 'height']: + for k in ["x", "y", "x1", "y1", "x2", "y2", "r", "rx", "ry", "cx", "cy", "width", "height"]: if k in data: - data[k] = getsize(data[k][0], 'css' + str(self.svgdpi)) + data[k] = getsize(data[k][0], "css" + str(self.svgdpi)) - for k in ['fill', 'stroke', 'stroke-width', 'font-size']: + for k in ["fill", "stroke", "stroke-width", "font-size"]: if k in data: if isinstance(data[k], list): if data[k][0].lower().startswith("rgb("): @@ -635,60 +639,59 @@ class svgHandler(xml.sax.ContentHandler): self.width = None self.text = None - if name == 'svg': + if name == "svg": m = FreeCAD.Matrix() if not self.disableUnitScaling: - if 'width' in data \ - and 'height' in data \ - and 'viewBox' in data: + if "width" in data and "height" in data and "viewBox" in data: if len(self.grouptransform) == 0: - unitmode = 'mm' + str(self.svgdpi) + unitmode = "mm" + str(self.svgdpi) else: # nested svg element - unitmode = 'css' + str(self.svgdpi) - vbw = round(getsize(data['viewBox'][2], 'discard'),precision) - vbh = round(getsize(data['viewBox'][3], 'discard'), precision) - abw = round(getsize(attrs.getValue('width'), unitmode), precision) - abh = round(getsize(attrs.getValue('height'), unitmode), precision) + unitmode = "css" + str(self.svgdpi) + vbw = round(getsize(data["viewBox"][2], "discard"), precision) + vbh = round(getsize(data["viewBox"][3], "discard"), precision) + abw = round(getsize(attrs.getValue("width"), unitmode), precision) + abh = round(getsize(attrs.getValue("height"), unitmode), precision) self.viewbox = (vbw, vbh) sx = abw / vbw sy = abh / vbh - preserve_ar = ' '.join(data.get('preserveAspectRatio', [])).lower() - if preserve_ar.startswith('none'): + preserve_ar = " ".join(data.get("preserveAspectRatio", [])).lower() + if preserve_ar.startswith("none"): m.scale(Vector(sx, sy, 1)) if sx != sy: - _wrn('Non-uniform scaling with probably degenerating ' - + 'effects on Edges. ({} vs. {}).'.format(sx, sy)) + _wrn( + "Non-uniform scaling with probably degenerating " + + "effects on Edges. ({} vs. {}).".format(sx, sy) + ) else: # preserve aspect ratio - svg default is 'x/y-mid meet' - if preserve_ar.endswith('slice'): + if preserve_ar.endswith("slice"): sxy = max(sx, sy) else: sxy = min(sx, sy) m.scale(Vector(sxy, sxy, 1)) elif len(self.grouptransform) == 0: # fallback to current dpi - m.scale(Vector(25.4/self.svgdpi, 25.4/self.svgdpi, 1)) + m.scale(Vector(25.4 / self.svgdpi, 25.4 / self.svgdpi, 1)) self.grouptransform.append(m) - if 'fill' in data: - if data['fill'] != 'none': - self.fill = getcolor(data['fill']) - if 'stroke' in data: - if data['stroke'] != 'none': - self.color = getcolor(data['stroke']) - if 'stroke-width' in data: - if data['stroke-width'] != 'none': - self.width = getsize(data['stroke-width'], - 'css' + str(self.svgdpi)) - if 'transform' in data: - m = self.getMatrix(attrs.getValue('transform')) + if "fill" in data: + if data["fill"] != "none": + self.fill = getcolor(data["fill"]) + if "stroke" in data: + if data["stroke"] != "none": + self.color = getcolor(data["stroke"]) + if "stroke-width" in data: + if data["stroke-width"] != "none": + self.width = getsize(data["stroke-width"], "css" + str(self.svgdpi)) + if "transform" in data: + m = self.getMatrix(attrs.getValue("transform")) else: m = FreeCAD.Matrix() if name == "g" or name == "a": self.grouptransform.append(m) elif name == "freecad:used": - #use tag acts as g tag but has x,y attribute + # use tag acts as g tag but has x,y attribute x = data.get("x", 0) y = data.get("y", 0) if x != 0 or y != 0: @@ -696,12 +699,12 @@ class svgHandler(xml.sax.ContentHandler): xy.move(Vector(x, -y, 0)) m = m.multiply(xy) self.grouptransform.append(m) - elif 'transform' in data: + elif "transform" in data: self.transform = m if self.style == 0: if self.fill is not None: - self.fill = self.fill_default + self.fill = self.fill_default self.color = self.color_default self.width = self.width_default @@ -717,7 +720,7 @@ class svgHandler(xml.sax.ContentHandler): break if self.fill is None: # svg fill default is Black - self.fill = getcolor('Black') + self.fill = getcolor("Black") if self.color is None: for groupstyle in reversed(self.groupstyles): if groupstyle[1] is not None: @@ -730,15 +733,15 @@ class svgHandler(xml.sax.ContentHandler): break pathname = None - if 'id' in data: - pathname = data['id'][0] - _msg('name: {}'.format(pathname)) + if "id" in data: + pathname = data["id"][0] + _msg("name: {}".format(pathname)) # Process paths if name == "path": if not pathname: pathname = "Path" - _msg('data: {}'.format(data)) + _msg("data: {}".format(data)) if "freecad:basepoint1" in data: p1 = data["freecad:basepoint1"] @@ -751,7 +754,7 @@ class svgHandler(xml.sax.ContentHandler): self.applyTrans(obj) self.format(obj) self.lastdim = obj - data['d'] = [] + data["d"] = [] if "d" in data: svgPath = SvgPathParser(data, pathname) @@ -766,59 +769,43 @@ class svgHandler(xml.sax.ContentHandler): # Process rects if name == "rect": if not pathname: - pathname = 'Rectangle' + pathname = "Rectangle" edges = [] if "x" not in data: data["x"] = 0 if "y" not in data: data["y"] = 0 # Negative values are invalid - _precision = 10**(-precision) - if ('rx' not in data or data['rx'] < _precision) \ - and ('ry' not in data or data['ry'] < _precision): + _precision = 10 ** (-precision) + if ("rx" not in data or data["rx"] < _precision) and ( + "ry" not in data or data["ry"] < _precision + ): # if True: - p1 = Vector(data['x'], - -data['y'], - 0) - p2 = Vector(data['x'] + data['width'], - -data['y'], - 0) - p3 = Vector(data['x'] + data['width'], - -data['y'] - data['height'], - 0) - p4 = Vector(data['x'], - -data['y'] - data['height'], - 0) + p1 = Vector(data["x"], -data["y"], 0) + p2 = Vector(data["x"] + data["width"], -data["y"], 0) + p3 = Vector(data["x"] + data["width"], -data["y"] - data["height"], 0) + p4 = Vector(data["x"], -data["y"] - data["height"], 0) edges.append(Part.LineSegment(p1, p2).toShape()) edges.append(Part.LineSegment(p2, p3).toShape()) edges.append(Part.LineSegment(p3, p4).toShape()) edges.append(Part.LineSegment(p4, p1).toShape()) else: # rounded edges - rx = data.get('rx') - ry = data.get('ry') or rx + rx = data.get("rx") + ry = data.get("ry") or rx rx = rx or ry - if rx > 2 * data['width']: - rx = data['width'] / 2.0 - if ry > 2 * data['height']: - ry = data['height'] / 2.0 + if rx > 2 * data["width"]: + rx = data["width"] / 2.0 + if ry > 2 * data["height"]: + ry = data["height"] / 2.0 - p1 = Vector(data['x'] + rx, - -data['y'] - data['height'] + ry, - 0) - p2 = Vector(data['x'] + data['width'] - rx, - -data['y'] - data['height'] + ry, - 0) - p3 = Vector(data['x'] + data['width'] - rx, - -data['y'] - ry, - 0) - p4 = Vector(data['x'] + rx, - -data['y'] - ry, - 0) + p1 = Vector(data["x"] + rx, -data["y"] - data["height"] + ry, 0) + p2 = Vector(data["x"] + data["width"] - rx, -data["y"] - data["height"] + ry, 0) + p3 = Vector(data["x"] + data["width"] - rx, -data["y"] - ry, 0) + p4 = Vector(data["x"] + rx, -data["y"] - ry, 0) if rx < 0 or ry < 0: - _wrn("Warning: 'rx' or 'ry' is negative, " - "check the SVG file") + _wrn("Warning: 'rx' or 'ry' is negative, " "check the SVG file") if rx >= ry: e = Part.Ellipse(Vector(), rx, ry) @@ -836,8 +823,7 @@ class svgHandler(xml.sax.ContentHandler): # rotate +90 degrees m = FreeCAD.Matrix(0, -1, 0, 0, 1, 0) esh = [] - for arc, point in ((e1a, p1), (e2a, p2), - (e3a, p3), (e4a, p4)): + for arc, point in ((e1a, p1), (e2a, p2), (e3a, p3), (e4a, p4)): m1 = FreeCAD.Matrix(m) m1.move(point) arc.transform(m1) @@ -862,9 +848,9 @@ class svgHandler(xml.sax.ContentHandler): # Process lines if name == "line": if not pathname: - pathname = 'Line' - p1 = Vector(data['x1'], -data['y1'], 0) - p2 = Vector(data['x2'], -data['y2'], 0) + pathname = "Line" + p1 = Vector(data["x1"], -data["y1"], 0) + p2 = Vector(data["x2"], -data["y2"], 0) sh = Part.LineSegment(p1, p2).toShape() sh = self.applyTrans(sh) obj = self.doc.addObject("Part::Feature", pathname) @@ -882,13 +868,13 @@ class svgHandler(xml.sax.ContentHandler): # but it would be more difficult to search for duplicate # points beforehand. if not pathname: - pathname = 'Polyline' - points = [float(d) for d in data['points']] + pathname = "Polyline" + points = [float(d) for d in data["points"]] lenpoints = len(points) if lenpoints >= 4 and lenpoints % 2 == 0: lastvec = Vector(points[0], -points[1], 0) path = [] - if name == 'polygon': + if name == "polygon": points = points + points[:2] # emulate closepath for svgx, svgy in zip(points[2::2], points[3::2]): currentvec = Vector(svgx, -svgy, 0) @@ -909,10 +895,10 @@ class svgHandler(xml.sax.ContentHandler): # Process ellipses if name == "ellipse": if not pathname: - pathname = 'Ellipse' - c = Vector(data.get('cx', 0), -data.get('cy', 0), 0) - rx = data['rx'] - ry = data['ry'] + pathname = "Ellipse" + c = Vector(data.get("cx", 0), -data.get("cy", 0), 0) + rx = data["rx"] + ry = data["ry"] if rx < 0 or ry < 0: _wrn("Warning: 'rx' or 'ry' is negative, check the SVG file") @@ -933,9 +919,9 @@ class svgHandler(xml.sax.ContentHandler): # Process circles if name == "circle" and "freecad:skip" not in data: if not pathname: - pathname = 'Circle' - c = Vector(data.get('cx', 0), -data.get('cy', 0), 0) - r = data['r'] + pathname = "Circle" + c = Vector(data.get("cx", 0), -data.get("cy", 0), 0) + r = data["r"] sh = Part.makeCircle(r) if self.fill: sh = Part.Wire([sh]) @@ -950,37 +936,35 @@ class svgHandler(xml.sax.ContentHandler): if name in ["text", "tspan"]: if "freecad:skip" not in data: _msg("processing a text") - if 'x' in data: - self.x = data['x'] + if "x" in data: + self.x = data["x"] else: self.x = 0 - if 'y' in data: - self.y = data['y'] + if "y" in data: + self.y = data["y"] else: self.y = 0 - if 'font-size' in data: - if data['font-size'] != 'none': - self.text = getsize(data['font-size'], - 'css' + str(self.svgdpi)) + if "font-size" in data: + if data["font-size"] != "none": + self.text = getsize(data["font-size"], "css" + str(self.svgdpi)) else: self.text = 1 else: if self.lastdim: - _font_size = int(getsize(data['font-size'])) + _font_size = int(getsize(data["font-size"])) self.lastdim.ViewObject.FontSize = _font_size - - _msg("done processing element {}".format(self.count)) + # startElement() def characters(self, content): """Read characters from the given string.""" if self.text: _msg("reading characters {}".format(content)) - obj = self.doc.addObject("App::Annotation", 'Text') + obj = self.doc.addObject("App::Annotation", "Text") # use ignore to not break import if char is not found in latin1 - obj.LabelText = content.encode('latin1', 'ignore') + obj.LabelText = content.encode("latin1", "ignore") vec = Vector(self.x, -self.y, 0) if self.transform: vec = self.translateVec(vec, self.transform) @@ -1028,7 +1012,7 @@ class svgHandler(xml.sax.ContentHandler): for transform in self.grouptransform[::-1]: sh = transformCopyShape(sh, transform) return sh - elif Draft.getType(sh) in ["Dimension","LinearDimension"]: + elif Draft.getType(sh) in ["Dimension", "LinearDimension"]: pts = [] for p in [sh.Start, sh.End, sh.Dimline]: cp = Vector(p) @@ -1069,26 +1053,26 @@ class svgHandler(xml.sax.ContentHandler): Base::Matrix4D The translated matrix. """ - _op = '(matrix|translate|scale|rotate|skewX|skewY)' - _val = '\\((.*?)\\)' - _transf = _op + '\\s*?' + _val + _op = "(matrix|translate|scale|rotate|skewX|skewY)" + _val = "\\((.*?)\\)" + _transf = _op + "\\s*?" + _val transformre = re.compile(_transf, re.DOTALL) m = FreeCAD.Matrix() for transformation, arguments in reversed(transformre.findall(tr)): - _args_rep = arguments.replace(',', ' ').split() + _args_rep = arguments.replace(",", " ").split() argsplit = [float(arg) for arg in _args_rep] # m.multiply(FreeCAD.Matrix(1, 0, 0, 0, 0, -1)) # print('%s:%s %s %d' % (transformation, arguments, # argsplit, len(argsplit))) - if transformation == 'translate': + if transformation == "translate": tx = argsplit[0] ty = argsplit[1] if len(argsplit) > 1 else 0.0 m.move(Vector(tx, -ty, 0)) - elif transformation == 'scale': + elif transformation == "scale": sx = argsplit[0] sy = argsplit[1] if len(argsplit) > 1 else sx m.scale(Vector(sx, sy, 1)) - elif transformation == 'rotate': + elif transformation == "rotate": cx = 0 cy = 0 angle = argsplit[0] @@ -1096,21 +1080,19 @@ class svgHandler(xml.sax.ContentHandler): # Rotate around a non-origin centerpoint (note: SVG y axis is opposite FreeCAD y axis) cx = argsplit[1] cy = argsplit[2] - m.move(Vector(-cx, cy, 0)) # Reposition for rotation + m.move(Vector(-cx, cy, 0)) # Reposition for rotation # Mirroring one axis is equal to changing the direction # of rotation m.rotateZ(math.radians(-angle)) if len(argsplit) >= 3: - m.move(Vector(cx, -cy, 0)) # Reverse repositioning - elif transformation == 'skewX': - _m = FreeCAD.Matrix(1, - -math.tan(math.radians(argsplit[0]))) + m.move(Vector(cx, -cy, 0)) # Reverse repositioning + elif transformation == "skewX": + _m = FreeCAD.Matrix(1, -math.tan(math.radians(argsplit[0]))) m = m.multiply(_m) - elif transformation == 'skewY': - _m = FreeCAD.Matrix(1, 0, 0, 0, - -math.tan(math.radians(argsplit[0]))) + elif transformation == "skewY": + _m = FreeCAD.Matrix(1, 0, 0, 0, -math.tan(math.radians(argsplit[0]))) m = m.multiply(_m) - elif transformation == 'matrix': + elif transformation == "matrix": # transformation matrix: # FreeCAD SVG # (+A -C +0 +E) (A C 0 E) @@ -1131,7 +1113,10 @@ class svgHandler(xml.sax.ContentHandler): # print("m = ", m) # print("generating transformation: ", m) return m + # getMatrix + + # class svgHandler @@ -1168,16 +1153,16 @@ def getContents(filename, tag, stringmode=False): # Replace the newline character with a string # so that it's easiert to parse; later on the newline character # will be restored - contents = contents.replace('\n', '_linebreak') - searchpat = '<' + tag + '.*?' + contents = contents.replace("\n", "_linebreak") + searchpat = "<" + tag + ".*?" tags = re.findall(searchpat, contents) for t in tags: tagid = re.findall(r'id="(.*?)"', t) if tagid: tagid = tagid[0] else: - tagid = 'none' - res = t.replace('_linebreak', '\n') + tagid = "none" + res = t.replace("_linebreak", "\n") result[tagid] = res return result @@ -1206,9 +1191,9 @@ def open(filename): parser.setContentHandler(handler) parser._cont_handler.doc = doc - #preprocess file to replace use tag to it's referenced object + # preprocess file to replace use tag to it's referenced object new_svg_content = replace_use_with_reference(filename) - xml.sax.parseString(new_svg_content,handler) + xml.sax.parseString(new_svg_content, handler) doc.recompute() return doc @@ -1245,9 +1230,9 @@ def insert(filename, docname): parser.setContentHandler(handler) parser._cont_handler.doc = doc - #preprocess file to replace use tag to it's referenced object + # preprocess file to replace use tag to it's referenced object new_svg_content = replace_use_with_reference(filename) - xml.sax.parseString(new_svg_content,handler) + xml.sax.parseString(new_svg_content, handler) doc.recompute() @@ -1271,8 +1256,7 @@ def export(exportList, filename): """ svg_export_style = params.get_param("svg_export_style") if svg_export_style != 0 and svg_export_style != 1: - _msg(translate("ImportSVG", - "Unknown SVG export style, switching to Translated")) + _msg(translate("ImportSVG", "Unknown SVG export style, switching to Translated")) svg_export_style = 0 tmp = [] @@ -1301,20 +1285,19 @@ def export(exportList, filename): # of all shapes bb = FreeCAD.BoundBox() for obj in exportList: - if (hasattr(obj, "Shape") - and obj.Shape - and obj.Shape.BoundBox.isValid()): + if hasattr(obj, "Shape") and obj.Shape and obj.Shape.BoundBox.isValid(): bb.add(obj.Shape.BoundBox) else: # if Draft.get_type(obj) in ("Text", "LinearDimension", ...) - _wrn("'{}': no Shape, " - "calculate manual bounding box".format(obj.Label)) + _wrn("'{}': no Shape, " "calculate manual bounding box".format(obj.Label)) bb.add(Draft.get_bbox(obj)) if not bb.isValid(): - _err(translate("ImportSVG", - "The export list contains no object " - "with a valid bounding box")) + _err( + translate( + "ImportSVG", "The export list contains no object " "with a valid bounding box" + ) + ) return minx = bb.XMin @@ -1338,7 +1321,7 @@ def export(exportList, filename): miny += margin # Use the native Python open which was saved as `pyopen` - svg = pyopen(filename, 'w') + svg = pyopen(filename, "w") # Write header. # We specify the SVG width and height in FreeCAD's physical units (mm), @@ -1346,11 +1329,11 @@ def export(exportList, filename): svg.write('\n') svg.write('\n') - svg.write('\n') + svg.write(">\n") # Write paths for ob in exportList: @@ -1368,21 +1351,22 @@ def export(exportList, filename): # svg.write('\n') - svg.write('\n' % (ob.Name, -minx, maxy)) + svg.write( + '\n' % (ob.Name, -minx, maxy) + ) else: # raw-style exports do not translate the sketch svg.write('\n' % ob.Name) svg.write(Draft.get_svg(ob, override=False)) - _label_enc = str(ob.Label.encode('utf8')) - _label = _label_enc.replace('<', '<').replace('>', '>') + _label_enc = str(ob.Label.encode("utf8")) + _label = _label_enc.replace("<", "<").replace(">", ">") # replace('"', """) - svg.write('%s\n' % _label) - svg.write('\n') + svg.write("%s\n" % _label) + svg.write("\n") # Close the file - svg.write('') + svg.write("") svg.close() if hidden_doc is not None: try: @@ -1390,14 +1374,15 @@ def export(exportList, filename): except: pass + # function to replace use tag to it's referenced object def replace_use_with_reference(file_path): - #function that replace use tag to freecad:used + # function that replace use tag to freecad:used def register_svg_namespaces(svg_content): # register namespaces xmlns_attrs = re.findall(r'\s+xmlns(?::([a-zA-Z0-9_]+))?="([^"]+)"', svg_content) for prefix, uri in xmlns_attrs: - ns_prefix = '' if prefix is None or prefix == 'svg' else prefix + ns_prefix = "" if prefix is None or prefix == "svg" else prefix ET.register_namespace(ns_prefix, uri) def replace_use(element, tree): @@ -1424,12 +1409,15 @@ def replace_use_with_reference(file_path): new_element = ET.Element("freecad:used") for attr in use.attrib: # copy attribute to new one except href attribute - if attr not in {"href", "{http://www.w3.org/1999/xlink}href"} and attr not in new_element.attrib: + if ( + attr not in {"href", "{http://www.w3.org/1999/xlink}href"} + and attr not in new_element.attrib + ): new_element.set(attr, use.attrib[attr]) - ref_element=deepcopy(ref_element) + ref_element = deepcopy(ref_element) # change referenced symbol tag to g tag, because symbol tag will be ignored when importing. if ref_element.tag.endswith("symbol"): - ref_element.tag="g" + ref_element.tag = "g" # remove id from referenced element.(without this multiple same id problem) if "id" in ref_element.attrib: del ref_element.attrib["id"] @@ -1440,10 +1428,10 @@ def replace_use_with_reference(file_path): new_element.append(ref_element) # replace use tag by freecad:used tag. parent.append(new_element) - #remove use when referenced element is not found. + # remove use when referenced element is not found. parent.remove(use) - #now all use tag processd - #remove symbol and defs tag from tree. + # now all use tag processd + # remove symbol and defs tag from tree. parent_map = {child: parent for parent in tree.iter() for child in parent} symbols = element.findall(".//{http://www.w3.org/2000/svg}symbol") for symbol in symbols: @@ -1456,7 +1444,7 @@ def replace_use_with_reference(file_path): # open file and read svg_content = pyopen(file_path).read() - #register namespace before parsing + # register namespace before parsing register_svg_namespaces(svg_content) # parse as xml. tree = ET.ElementTree(ET.fromstring(svg_content)) @@ -1470,4 +1458,4 @@ def replace_use_with_reference(file_path): replace_use(root, tree) # return tree as xml string with namespace declaration. - return ET.tostring(root, encoding='unicode',xml_declaration=True) + return ET.tostring(root, encoding="unicode", xml_declaration=True)